1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex *) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 if (markers) { 167 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 168 } 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\\documentclass{article}\n\n\ 191 \\usepackage{tikz}\n\ 192 \\usepackage{pgflibraryshapes}\n\ 193 \\usetikzlibrary{backgrounds}\n\ 194 \\usetikzlibrary{arrows}\n\ 195 \\newenvironment{changemargin}[2]{%%\n\ 196 \\begin{list}{}{%%\n\ 197 \\setlength{\\topsep}{0pt}%%\n\ 198 \\setlength{\\leftmargin}{#1}%%\n\ 199 \\setlength{\\rightmargin}{#2}%%\n\ 200 \\setlength{\\listparindent}{\\parindent}%%\n\ 201 \\setlength{\\itemindent}{\\parindent}%%\n\ 202 \\setlength{\\parsep}{\\parskip}%%\n\ 203 }%%\n\ 204 \\item[]}{\\end{list}}\n\n\ 205 \\begin{document}\n\ 206 \\section{%s}\n\ 207 \\begin{changemargin}{-1cm}{0cm}\n\ 208 \\begin{center}\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", name, 8.0/scale);CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for(v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for(e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for(c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = PETSC_NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 276 for(p = 0; p < size; ++p) { 277 if (p > 0 && p == size-1) { 278 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 279 } else if (p > 0) { 280 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 281 } 282 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 283 } 284 ierr = PetscViewerASCIIPrintf(viewer, ".\n");CHKERRQ(ierr); 285 ierr = PetscViewerASCIIPrintf(viewer, "\\end{changemargin}\n\ 286 \\end{document}\n", name);CHKERRQ(ierr); 287 } else { 288 MPI_Comm comm = ((PetscObject) dm)->comm; 289 PetscInt *sizes; 290 PetscInt locDepth, depth, dim, d; 291 PetscInt pStart, pEnd, p; 292 PetscMPIInt size; 293 294 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 295 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 296 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 297 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 298 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 299 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 300 if (depth == 1) { 301 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 302 pEnd = pEnd - pStart; 303 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 304 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 305 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 306 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 307 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 308 pEnd = pEnd - pStart; 309 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 310 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 311 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 312 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 313 } else { 314 for (d = 0; d <= dim; d++) { 315 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 316 pEnd = pEnd - pStart; 317 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 318 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 319 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 320 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 321 } 322 } 323 ierr = PetscFree(sizes);CHKERRQ(ierr); 324 } 325 PetscFunctionReturn(0); 326 } 327 328 #undef __FUNCT__ 329 #define __FUNCT__ "DMView_Plex" 330 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 331 { 332 PetscBool iascii, isbinary; 333 PetscErrorCode ierr; 334 335 PetscFunctionBegin; 336 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 337 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 338 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 339 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 340 if (iascii) { 341 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 342 #if 0 343 } else if (isbinary) { 344 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 345 #endif 346 } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name); 347 PetscFunctionReturn(0); 348 } 349 350 #undef __FUNCT__ 351 #define __FUNCT__ "DMDestroy_Plex" 352 PetscErrorCode DMDestroy_Plex(DM dm) 353 { 354 DM_Plex *mesh = (DM_Plex *) dm->data; 355 DMLabel next = mesh->labels; 356 PetscErrorCode ierr; 357 358 PetscFunctionBegin; 359 if (--mesh->refct > 0) {PetscFunctionReturn(0);} 360 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 361 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 362 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 363 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 364 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 365 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 366 while(next) { 367 DMLabel tmp = next->next; 368 369 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 370 next = tmp; 371 } 372 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 373 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 374 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 375 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 376 ierr = PetscFree(mesh);CHKERRQ(ierr); 377 PetscFunctionReturn(0); 378 } 379 380 #undef __FUNCT__ 381 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 382 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 383 { 384 const PetscInt *support = PETSC_NULL; 385 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 386 PetscErrorCode ierr; 387 388 PetscFunctionBegin; 389 if (useClosure) { 390 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 391 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 392 for (s = 0; s < supportSize; ++s) { 393 const PetscInt *cone = PETSC_NULL; 394 PetscInt coneSize, c, q; 395 396 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 397 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 398 for (c = 0; c < coneSize; ++c) { 399 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 400 if (cone[c] == adj[q]) break; 401 } 402 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 403 } 404 } 405 } else { 406 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 407 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 408 for (s = 0; s < supportSize; ++s) { 409 const PetscInt *cone = PETSC_NULL; 410 PetscInt coneSize, c, q; 411 412 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 413 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 414 for (c = 0; c < coneSize; ++c) { 415 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 416 if (cone[c] == adj[q]) break; 417 } 418 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 419 } 420 } 421 } 422 *adjSize = numAdj; 423 PetscFunctionReturn(0); 424 } 425 426 #undef __FUNCT__ 427 #define __FUNCT__ "DMPlexGetAdjacency_Private" 428 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 429 { 430 const PetscInt *star = tmpClosure; 431 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 432 PetscErrorCode ierr; 433 434 PetscFunctionBegin; 435 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 436 for (s = 2; s < starSize*2; s += 2) { 437 const PetscInt *closure = PETSC_NULL; 438 PetscInt closureSize, c, q; 439 440 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 441 for (c = 0; c < closureSize*2; c += 2) { 442 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 443 if (closure[c] == adj[q]) break; 444 } 445 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 446 } 447 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 448 } 449 *adjSize = numAdj; 450 PetscFunctionReturn(0); 451 } 452 453 #undef __FUNCT__ 454 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 455 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 456 { 457 DM_Plex *mesh = (DM_Plex *) dm->data; 458 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 461 mesh->preallocCenterDim = preallocCenterDim; 462 PetscFunctionReturn(0); 463 } 464 465 #undef __FUNCT__ 466 #define __FUNCT__ "DMPlexPreallocateOperator" 467 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 468 { 469 DM_Plex *mesh = (DM_Plex *) dm->data; 470 MPI_Comm comm = ((PetscObject) dm)->comm; 471 PetscSF sf, sfDof, sfAdj; 472 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 473 PetscInt nleaves, l, p; 474 const PetscInt *leaves; 475 const PetscSFNode *remotes; 476 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 477 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 478 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 479 PetscLayout rLayout; 480 PetscInt locRows, rStart, rEnd, r; 481 PetscMPIInt size; 482 PetscBool useClosure, debug = PETSC_FALSE; 483 PetscErrorCode ierr; 484 485 PetscFunctionBegin; 486 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 487 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 488 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 489 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 490 /* Create dof SF based on point SF */ 491 if (debug) { 492 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 493 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 494 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 495 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 496 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 497 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 498 } 499 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 500 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 501 if (debug) { 502 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 503 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 504 } 505 /* Create section for dof adjacency (dof ==> # adj dof) */ 506 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 507 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 508 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 509 if (mesh->preallocCenterDim == dim) { 510 useClosure = PETSC_FALSE; 511 } else if (mesh->preallocCenterDim == 0) { 512 useClosure = PETSC_TRUE; 513 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 514 515 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 516 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 517 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 518 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 519 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 520 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 521 /* Fill in the ghost dofs on the interface */ 522 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 523 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 524 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 525 maxClosureSize = (PetscInt) (2*PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1)); 526 maxAdjSize = (PetscInt) (pow((PetscReal) mesh->maxConeSize, depth)*pow((PetscReal) mesh->maxSupportSize, depth)+1); 527 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 528 529 /* 530 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 531 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 532 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 533 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 534 Create sfAdj connecting rootSectionAdj and leafSectionAdj 535 3. Visit unowned points on interface, write adjacencies to adj 536 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 537 4. Visit owned points on interface, write adjacencies to rootAdj 538 Remove redundancy in rootAdj 539 ** The last two traversals use transitive closure 540 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 541 Allocate memory addressed by sectionAdj (cols) 542 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 543 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 544 */ 545 546 for (l = 0; l < nleaves; ++l) { 547 PetscInt dof, off, d, q; 548 PetscInt p = leaves[l], numAdj = maxAdjSize; 549 550 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 551 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 552 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 553 for (q = 0; q < numAdj; ++q) { 554 PetscInt ndof, ncdof; 555 556 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 557 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 558 for (d = off; d < off+dof; ++d) { 559 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 560 } 561 } 562 } 563 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 564 if (debug) { 565 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 566 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 567 } 568 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 569 if (size > 1) { 570 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 571 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 572 } 573 if (debug) { 574 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 575 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 576 } 577 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 578 for (p = pStart; p < pEnd; ++p) { 579 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 580 581 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 582 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 583 if (!dof) continue; 584 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 585 if (adof <= 0) continue; 586 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 587 for (q = 0; q < numAdj; ++q) { 588 PetscInt ndof, ncdof; 589 590 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 591 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 592 for (d = off; d < off+dof; ++d) { 593 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 594 } 595 } 596 } 597 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 598 if (debug) { 599 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 600 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 601 } 602 /* Create adj SF based on dof SF */ 603 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 604 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 605 if (debug) { 606 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 607 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 608 } 609 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 610 /* Create leaf adjacency */ 611 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 612 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 613 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 614 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 615 for (l = 0; l < nleaves; ++l) { 616 PetscInt dof, off, d, q; 617 PetscInt p = leaves[l], numAdj = maxAdjSize; 618 619 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 621 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 622 for (d = off; d < off+dof; ++d) { 623 PetscInt aoff, i = 0; 624 625 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 626 for (q = 0; q < numAdj; ++q) { 627 PetscInt ndof, ncdof, ngoff, nd; 628 629 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 630 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 631 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 632 for (nd = 0; nd < ndof-ncdof; ++nd) { 633 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 634 ++i; 635 } 636 } 637 } 638 } 639 /* Debugging */ 640 if (debug) { 641 IS tmp; 642 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 643 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 644 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 645 } 646 /* Gather adjacenct indices to root */ 647 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 648 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 649 for (r = 0; r < adjSize; ++r) { 650 rootAdj[r] = -1; 651 } 652 if (size > 1) { 653 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 654 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 655 } 656 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 657 ierr = PetscFree(adj);CHKERRQ(ierr); 658 /* Debugging */ 659 if (debug) { 660 IS tmp; 661 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 662 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 663 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 664 } 665 /* Add in local adjacency indices for owned dofs on interface (roots) */ 666 for (p = pStart; p < pEnd; ++p) { 667 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 668 669 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 670 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 671 if (!dof) continue; 672 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 673 if (adof <= 0) continue; 674 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 675 for (d = off; d < off+dof; ++d) { 676 PetscInt adof, aoff, i; 677 678 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 679 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 680 i = adof-1; 681 for (q = 0; q < numAdj; ++q) { 682 PetscInt ndof, ncdof, ngoff, nd; 683 684 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 685 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 686 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 687 for (nd = 0; nd < ndof-ncdof; ++nd) { 688 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 689 --i; 690 } 691 } 692 } 693 } 694 /* Debugging */ 695 if (debug) { 696 IS tmp; 697 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 698 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 699 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 700 } 701 /* Compress indices */ 702 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 703 for (p = pStart; p < pEnd; ++p) { 704 PetscInt dof, cdof, off, d; 705 PetscInt adof, aoff; 706 707 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 708 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 709 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 710 if (!dof) continue; 711 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 712 if (adof <= 0) continue; 713 for (d = off; d < off+dof-cdof; ++d) { 714 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 715 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 716 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 717 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 718 } 719 } 720 /* Debugging */ 721 if (debug) { 722 IS tmp; 723 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 724 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 725 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 726 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 727 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 728 } 729 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 730 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 731 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 732 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 733 for (p = pStart; p < pEnd; ++p) { 734 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 735 PetscBool found = PETSC_TRUE; 736 737 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 738 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 739 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 740 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 741 for (d = 0; d < dof-cdof; ++d) { 742 PetscInt ldof, rdof; 743 744 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 745 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 746 if (ldof > 0) { 747 /* We do not own this point */ 748 } else if (rdof > 0) { 749 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 750 } else { 751 found = PETSC_FALSE; 752 } 753 } 754 if (found) continue; 755 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 756 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 757 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 758 for (q = 0; q < numAdj; ++q) { 759 PetscInt ndof, ncdof, noff; 760 761 /* Adjacent points may not be in the section chart */ 762 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 763 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 764 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 765 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 766 for (d = goff; d < goff+dof-cdof; ++d) { 767 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 768 } 769 } 770 } 771 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 772 if (debug) { 773 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 774 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 775 } 776 /* Get adjacent indices */ 777 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 778 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 779 for (p = pStart; p < pEnd; ++p) { 780 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 781 PetscBool found = PETSC_TRUE; 782 783 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 784 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 786 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 787 for (d = 0; d < dof-cdof; ++d) { 788 PetscInt ldof, rdof; 789 790 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 791 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 792 if (ldof > 0) { 793 /* We do not own this point */ 794 } else if (rdof > 0) { 795 PetscInt aoff, roff; 796 797 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 798 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 799 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 800 } else { 801 found = PETSC_FALSE; 802 } 803 } 804 if (found) continue; 805 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 806 for (d = goff; d < goff+dof-cdof; ++d) { 807 PetscInt adof, aoff, i = 0; 808 809 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 810 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 811 for (q = 0; q < numAdj; ++q) { 812 PetscInt ndof, ncdof, ngoff, nd; 813 const PetscInt *ncind; 814 815 /* Adjacent points may not be in the section chart */ 816 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 817 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 818 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 819 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 820 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 821 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 822 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 823 } 824 } 825 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 } 827 } 828 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 829 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 830 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 831 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 832 /* Debugging */ 833 if (debug) { 834 IS tmp; 835 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 836 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 837 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 838 } 839 /* Create allocation vectors from adjacency graph */ 840 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 841 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 842 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 843 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 844 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 845 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 846 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 847 /* Only loop over blocks of rows */ 848 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 for (r = rStart/bs; r < rEnd/bs; ++r) { 850 const PetscInt row = r*bs; 851 PetscInt numCols, cStart, c; 852 853 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 854 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 855 for (c = cStart; c < cStart+numCols; ++c) { 856 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 857 ++dnz[r-rStart]; 858 if (cols[c] >= row) {++dnzu[r-rStart];} 859 } else { 860 ++onz[r-rStart]; 861 if (cols[c] >= row) {++onzu[r-rStart];} 862 } 863 } 864 } 865 if (bs > 1) { 866 for (r = 0; r < locRows/bs; ++r) { 867 dnz[r] /= bs; 868 onz[r] /= bs; 869 dnzu[r] /= bs; 870 onzu[r] /= bs; 871 } 872 } 873 /* Set matrix pattern */ 874 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 875 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 876 /* Fill matrix with zeros */ 877 if (fillMatrix) { 878 PetscScalar *values; 879 PetscInt maxRowLen = 0; 880 881 for (r = rStart; r < rEnd; ++r) { 882 PetscInt len; 883 884 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 885 maxRowLen = PetscMax(maxRowLen, len); 886 } 887 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 888 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 889 for (r = rStart; r < rEnd; ++r) { 890 PetscInt numCols, cStart; 891 892 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 893 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 894 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 895 } 896 ierr = PetscFree(values);CHKERRQ(ierr); 897 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 898 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 899 } 900 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 901 ierr = PetscFree(cols);CHKERRQ(ierr); 902 PetscFunctionReturn(0); 903 } 904 905 #if 0 906 #undef __FUNCT__ 907 #define __FUNCT__ "DMPlexPreallocateOperator_2" 908 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 909 { 910 PetscErrorCode ierr; 911 PetscInt c,cStart,cEnd,pStart,pEnd; 912 PetscInt *tmpClosure,*tmpAdj,*visits; 913 914 PetscFunctionBegin; 915 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 916 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 917 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 918 maxClosureSize = 2*PetscMax(pow(mesh->maxConeSize, depth)+1, pow(mesh->maxSupportSize, depth)+1); 919 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 920 npoints = pEnd - pStart; 921 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 922 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 923 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 924 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 925 for (c=cStart; c<cEnd; c++) { 926 PetscInt *support = tmpClosure; 927 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 928 for (p=0; p<supportSize; p++) { 929 lvisits[support[p]]++; 930 } 931 } 932 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 933 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 934 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 935 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 936 937 ierr = PetscSFGetRanks();CHKERRQ(ierr); 938 939 940 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 941 for (c=cStart; c<cEnd; c++) { 942 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 943 /* 944 Depth-first walk of transitive closure. 945 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 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 947 */ 948 } 949 950 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 951 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 952 PetscFunctionReturn(0); 953 } 954 #endif 955 956 #undef __FUNCT__ 957 #define __FUNCT__ "DMCreateMatrix_Plex" 958 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 959 { 960 PetscSection section, sectionGlobal; 961 PetscInt bs = -1; 962 PetscInt localSize; 963 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 964 PetscErrorCode ierr; 965 966 PetscFunctionBegin; 967 #ifndef PETSC_USE_DYNAMIC_LIBRARIES 968 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 969 #endif 970 if (!mtype) mtype = MATAIJ; 971 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 972 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 973 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 974 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 975 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 976 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 977 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 978 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 979 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 980 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 981 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 982 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 983 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 984 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 985 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 986 /* Check for symmetric storage */ 987 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 988 if (isSymmetric) { 989 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 990 } 991 if (!isShell) { 992 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 993 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal; 994 995 if (bs < 0) { 996 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 997 PetscInt pStart, pEnd, p, dof; 998 999 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1000 for (p = pStart; p < pEnd; ++p) { 1001 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1002 if (dof) { 1003 bs = dof; 1004 break; 1005 } 1006 } 1007 } else { 1008 bs = 1; 1009 } 1010 /* Must have same blocksize on all procs (some might have no points) */ 1011 bsLocal = bs; 1012 ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1013 } 1014 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1015 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1016 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1017 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1018 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1019 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1020 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1021 } 1022 PetscFunctionReturn(0); 1023 } 1024 1025 #undef __FUNCT__ 1026 #define __FUNCT__ "DMPlexGetDimension" 1027 /*@ 1028 DMPlexGetDimension - Return the topological mesh dimension 1029 1030 Not collective 1031 1032 Input Parameter: 1033 . mesh - The DMPlex 1034 1035 Output Parameter: 1036 . dim - The topological mesh dimension 1037 1038 Level: beginner 1039 1040 .seealso: DMPlexCreate() 1041 @*/ 1042 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1043 { 1044 DM_Plex *mesh = (DM_Plex *) dm->data; 1045 1046 PetscFunctionBegin; 1047 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1048 PetscValidPointer(dim, 2); 1049 *dim = mesh->dim; 1050 PetscFunctionReturn(0); 1051 } 1052 1053 #undef __FUNCT__ 1054 #define __FUNCT__ "DMPlexSetDimension" 1055 /*@ 1056 DMPlexSetDimension - Set the topological mesh dimension 1057 1058 Collective on mesh 1059 1060 Input Parameters: 1061 + mesh - The DMPlex 1062 - dim - The topological mesh dimension 1063 1064 Level: beginner 1065 1066 .seealso: DMPlexCreate() 1067 @*/ 1068 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1069 { 1070 DM_Plex *mesh = (DM_Plex *) dm->data; 1071 1072 PetscFunctionBegin; 1073 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1074 PetscValidLogicalCollectiveInt(dm, dim, 2); 1075 mesh->dim = dim; 1076 mesh->preallocCenterDim = dim; 1077 PetscFunctionReturn(0); 1078 } 1079 1080 #undef __FUNCT__ 1081 #define __FUNCT__ "DMPlexGetChart" 1082 /*@ 1083 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1084 1085 Not collective 1086 1087 Input Parameter: 1088 . mesh - The DMPlex 1089 1090 Output Parameters: 1091 + pStart - The first mesh point 1092 - pEnd - The upper bound for mesh points 1093 1094 Level: beginner 1095 1096 .seealso: DMPlexCreate(), DMPlexSetChart() 1097 @*/ 1098 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1099 { 1100 DM_Plex *mesh = (DM_Plex *) dm->data; 1101 PetscErrorCode ierr; 1102 1103 PetscFunctionBegin; 1104 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1105 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1106 PetscFunctionReturn(0); 1107 } 1108 1109 #undef __FUNCT__ 1110 #define __FUNCT__ "DMPlexSetChart" 1111 /*@ 1112 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1113 1114 Not collective 1115 1116 Input Parameters: 1117 + mesh - The DMPlex 1118 . pStart - The first mesh point 1119 - pEnd - The upper bound for mesh points 1120 1121 Output Parameters: 1122 1123 Level: beginner 1124 1125 .seealso: DMPlexCreate(), DMPlexGetChart() 1126 @*/ 1127 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1128 { 1129 DM_Plex *mesh = (DM_Plex *) dm->data; 1130 PetscErrorCode ierr; 1131 1132 PetscFunctionBegin; 1133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1134 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1135 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1136 PetscFunctionReturn(0); 1137 } 1138 1139 #undef __FUNCT__ 1140 #define __FUNCT__ "DMPlexGetConeSize" 1141 /*@ 1142 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1143 1144 Not collective 1145 1146 Input Parameters: 1147 + mesh - The DMPlex 1148 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1149 1150 Output Parameter: 1151 . size - The cone size for point p 1152 1153 Level: beginner 1154 1155 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1156 @*/ 1157 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1158 { 1159 DM_Plex *mesh = (DM_Plex *) dm->data; 1160 PetscErrorCode ierr; 1161 1162 PetscFunctionBegin; 1163 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1164 PetscValidPointer(size, 3); 1165 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1166 PetscFunctionReturn(0); 1167 } 1168 1169 #undef __FUNCT__ 1170 #define __FUNCT__ "DMPlexSetConeSize" 1171 /*@ 1172 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1173 1174 Not collective 1175 1176 Input Parameters: 1177 + mesh - The DMPlex 1178 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1179 - size - The cone size for point p 1180 1181 Output Parameter: 1182 1183 Note: 1184 This should be called after DMPlexSetChart(). 1185 1186 Level: beginner 1187 1188 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1189 @*/ 1190 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1191 { 1192 DM_Plex *mesh = (DM_Plex *) dm->data; 1193 PetscErrorCode ierr; 1194 1195 PetscFunctionBegin; 1196 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1197 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1198 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1199 PetscFunctionReturn(0); 1200 } 1201 1202 #undef __FUNCT__ 1203 #define __FUNCT__ "DMPlexGetCone" 1204 /*@C 1205 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1206 1207 Not collective 1208 1209 Input Parameters: 1210 + mesh - The DMPlex 1211 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1212 1213 Output Parameter: 1214 . cone - An array of points which are on the in-edges for point p 1215 1216 Level: beginner 1217 1218 Note: 1219 This routine is not available in Fortran. 1220 1221 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1222 @*/ 1223 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1224 { 1225 DM_Plex *mesh = (DM_Plex *) dm->data; 1226 PetscInt off; 1227 PetscErrorCode ierr; 1228 1229 PetscFunctionBegin; 1230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1231 PetscValidPointer(cone, 3); 1232 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1233 *cone = &mesh->cones[off]; 1234 PetscFunctionReturn(0); 1235 } 1236 1237 #undef __FUNCT__ 1238 #define __FUNCT__ "DMPlexSetCone" 1239 /*@ 1240 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1241 1242 Not collective 1243 1244 Input Parameters: 1245 + mesh - The DMPlex 1246 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1247 - cone - An array of points which are on the in-edges for point p 1248 1249 Output Parameter: 1250 1251 Note: 1252 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1253 1254 Level: beginner 1255 1256 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1257 @*/ 1258 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1259 { 1260 DM_Plex *mesh = (DM_Plex *) dm->data; 1261 PetscInt pStart, pEnd; 1262 PetscInt dof, off, c; 1263 PetscErrorCode ierr; 1264 1265 PetscFunctionBegin; 1266 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1267 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1268 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1269 if (dof) PetscValidPointer(cone, 3); 1270 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1271 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 for (c = 0; c < dof; ++c) { 1273 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 mesh->cones[off+c] = cone[c]; 1275 } 1276 PetscFunctionReturn(0); 1277 } 1278 1279 #undef __FUNCT__ 1280 #define __FUNCT__ "DMPlexGetConeOrientation" 1281 /*@C 1282 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1283 1284 Not collective 1285 1286 Input Parameters: 1287 + mesh - The DMPlex 1288 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1289 1290 Output Parameter: 1291 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1292 integer giving the prescription for cone traversal. If it is negative, the cone is 1293 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1294 the index of the cone point on which to start. 1295 1296 Level: beginner 1297 1298 Note: 1299 This routine is not available in Fortran. 1300 1301 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1302 @*/ 1303 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1304 { 1305 DM_Plex *mesh = (DM_Plex *) dm->data; 1306 PetscInt off; 1307 PetscErrorCode ierr; 1308 1309 PetscFunctionBegin; 1310 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1311 #if defined(PETSC_USE_DEBUG) 1312 { 1313 PetscInt dof; 1314 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1315 if (dof) PetscValidPointer(coneOrientation, 3); 1316 } 1317 #endif 1318 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1319 *coneOrientation = &mesh->coneOrientations[off]; 1320 PetscFunctionReturn(0); 1321 } 1322 1323 #undef __FUNCT__ 1324 #define __FUNCT__ "DMPlexSetConeOrientation" 1325 /*@ 1326 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1327 1328 Not collective 1329 1330 Input Parameters: 1331 + mesh - The DMPlex 1332 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1333 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1334 integer giving the prescription for cone traversal. If it is negative, the cone is 1335 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1336 the index of the cone point on which to start. 1337 1338 Output Parameter: 1339 1340 Note: 1341 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1342 1343 Level: beginner 1344 1345 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1346 @*/ 1347 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1348 { 1349 DM_Plex *mesh = (DM_Plex *) dm->data; 1350 PetscInt pStart, pEnd; 1351 PetscInt dof, off, c; 1352 PetscErrorCode ierr; 1353 1354 PetscFunctionBegin; 1355 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1356 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1357 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1358 if (dof) PetscValidPointer(coneOrientation, 3); 1359 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1360 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 for (c = 0; c < dof; ++c) { 1362 PetscInt cdof, o = coneOrientation[c]; 1363 1364 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1365 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 mesh->coneOrientations[off+c] = o; 1367 } 1368 PetscFunctionReturn(0); 1369 } 1370 1371 #undef __FUNCT__ 1372 #define __FUNCT__ "DMPlexInsertCone" 1373 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1374 { 1375 DM_Plex *mesh = (DM_Plex *) dm->data; 1376 PetscInt pStart, pEnd; 1377 PetscInt dof, off; 1378 PetscErrorCode ierr; 1379 1380 PetscFunctionBegin; 1381 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1382 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1383 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1384 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1385 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 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 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 mesh->cones[off+conePos] = conePoint; 1389 PetscFunctionReturn(0); 1390 } 1391 1392 #undef __FUNCT__ 1393 #define __FUNCT__ "DMPlexGetSupportSize" 1394 /*@ 1395 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1396 1397 Not collective 1398 1399 Input Parameters: 1400 + mesh - The DMPlex 1401 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1402 1403 Output Parameter: 1404 . size - The support size for point p 1405 1406 Level: beginner 1407 1408 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1409 @*/ 1410 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1411 { 1412 DM_Plex *mesh = (DM_Plex *) dm->data; 1413 PetscErrorCode ierr; 1414 1415 PetscFunctionBegin; 1416 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1417 PetscValidPointer(size, 3); 1418 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1419 PetscFunctionReturn(0); 1420 } 1421 1422 #undef __FUNCT__ 1423 #define __FUNCT__ "DMPlexSetSupportSize" 1424 /*@ 1425 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1426 1427 Not collective 1428 1429 Input Parameters: 1430 + mesh - The DMPlex 1431 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1432 - size - The support size for point p 1433 1434 Output Parameter: 1435 1436 Note: 1437 This should be called after DMPlexSetChart(). 1438 1439 Level: beginner 1440 1441 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1442 @*/ 1443 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1444 { 1445 DM_Plex *mesh = (DM_Plex *) dm->data; 1446 PetscErrorCode ierr; 1447 1448 PetscFunctionBegin; 1449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1450 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1451 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1452 PetscFunctionReturn(0); 1453 } 1454 1455 #undef __FUNCT__ 1456 #define __FUNCT__ "DMPlexGetSupport" 1457 /*@C 1458 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1459 1460 Not collective 1461 1462 Input Parameters: 1463 + mesh - The DMPlex 1464 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1465 1466 Output Parameter: 1467 . support - An array of points which are on the out-edges for point p 1468 1469 Level: beginner 1470 1471 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1472 @*/ 1473 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1474 { 1475 DM_Plex *mesh = (DM_Plex *) dm->data; 1476 PetscInt off; 1477 PetscErrorCode ierr; 1478 1479 PetscFunctionBegin; 1480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1481 PetscValidPointer(support, 3); 1482 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1483 *support = &mesh->supports[off]; 1484 PetscFunctionReturn(0); 1485 } 1486 1487 #undef __FUNCT__ 1488 #define __FUNCT__ "DMPlexSetSupport" 1489 /*@ 1490 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1491 1492 Not collective 1493 1494 Input Parameters: 1495 + mesh - The DMPlex 1496 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1497 - support - An array of points which are on the in-edges for point p 1498 1499 Output Parameter: 1500 1501 Note: 1502 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1503 1504 Level: beginner 1505 1506 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1507 @*/ 1508 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1509 { 1510 DM_Plex *mesh = (DM_Plex *) dm->data; 1511 PetscInt pStart, pEnd; 1512 PetscInt dof, off, c; 1513 PetscErrorCode ierr; 1514 1515 PetscFunctionBegin; 1516 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1517 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1518 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1519 if (dof) PetscValidPointer(support, 3); 1520 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1521 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 for (c = 0; c < dof; ++c) { 1523 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 mesh->supports[off+c] = support[c]; 1525 } 1526 PetscFunctionReturn(0); 1527 } 1528 1529 #undef __FUNCT__ 1530 #define __FUNCT__ "DMPlexInsertSupport" 1531 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1532 { 1533 DM_Plex *mesh = (DM_Plex *) dm->data; 1534 PetscInt pStart, pEnd; 1535 PetscInt dof, off; 1536 PetscErrorCode ierr; 1537 1538 PetscFunctionBegin; 1539 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1540 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1541 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1542 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1543 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 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 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 mesh->supports[off+supportPos] = supportPoint; 1547 PetscFunctionReturn(0); 1548 } 1549 1550 #undef __FUNCT__ 1551 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1552 /*@C 1553 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1554 1555 Not collective 1556 1557 Input Parameters: 1558 + mesh - The DMPlex 1559 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1560 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1561 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1562 1563 Output Parameters: 1564 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1565 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1566 1567 Note: 1568 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1569 1570 Level: beginner 1571 1572 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1573 @*/ 1574 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1575 { 1576 DM_Plex *mesh = (DM_Plex *) dm->data; 1577 PetscInt *closure, *fifo; 1578 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1579 PetscInt tmpSize, t; 1580 PetscInt depth = 0, maxSize; 1581 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1582 PetscErrorCode ierr; 1583 1584 PetscFunctionBegin; 1585 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1586 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1587 maxSize = (PetscInt) (2*PetscMax(PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1), depth+1)); 1588 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1589 if (*points) { 1590 closure = *points; 1591 } else { 1592 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1593 } 1594 closure[0] = p; closure[1] = 0; 1595 /* This is only 1-level */ 1596 if (useCone) { 1597 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1598 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1599 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1600 } else { 1601 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1602 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1603 } 1604 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1605 const PetscInt cp = tmp[t]; 1606 const PetscInt co = tmpO ? tmpO[t] : 0; 1607 1608 closure[closureSize] = cp; 1609 closure[closureSize+1] = co; 1610 fifo[fifoSize] = cp; 1611 fifo[fifoSize+1] = co; 1612 } 1613 while(fifoSize - fifoStart) { 1614 const PetscInt q = fifo[fifoStart]; 1615 const PetscInt o = fifo[fifoStart+1]; 1616 const PetscInt rev = o >= 0 ? 0 : 1; 1617 const PetscInt off = rev ? -(o+1) : o; 1618 1619 if (useCone) { 1620 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1621 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1622 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1623 } else { 1624 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1625 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1626 tmpO = PETSC_NULL; 1627 } 1628 for (t = 0; t < tmpSize; ++t) { 1629 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1630 const PetscInt cp = tmp[i]; 1631 /* Must propogate orientation */ 1632 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1633 PetscInt c; 1634 1635 /* Check for duplicate */ 1636 for (c = 0; c < closureSize; c += 2) { 1637 if (closure[c] == cp) break; 1638 } 1639 if (c == closureSize) { 1640 closure[closureSize] = cp; 1641 closure[closureSize+1] = co; 1642 fifo[fifoSize] = cp; 1643 fifo[fifoSize+1] = co; 1644 closureSize += 2; 1645 fifoSize += 2; 1646 } 1647 } 1648 fifoStart += 2; 1649 } 1650 if (numPoints) *numPoints = closureSize/2; 1651 if (points) *points = closure; 1652 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1653 PetscFunctionReturn(0); 1654 } 1655 1656 #undef __FUNCT__ 1657 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1658 /*@C 1659 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 1661 Not collective 1662 1663 Input Parameters: 1664 + mesh - The DMPlex 1665 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1666 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1667 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1668 1669 Output Parameters: 1670 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1671 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1672 1673 Note: 1674 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1675 1676 Level: beginner 1677 1678 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1679 @*/ 1680 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1681 { 1682 PetscErrorCode ierr; 1683 1684 PetscFunctionBegin; 1685 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1686 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1687 PetscFunctionReturn(0); 1688 } 1689 1690 #undef __FUNCT__ 1691 #define __FUNCT__ "DMPlexGetFaces" 1692 /* 1693 DMPlexGetFaces - 1694 1695 Note: This will only work for cell-vertex meshes. 1696 */ 1697 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1698 { 1699 DM_Plex *mesh = (DM_Plex *) dm->data; 1700 const PetscInt *cone = PETSC_NULL; 1701 PetscInt depth = 0, dim, coneSize; 1702 PetscErrorCode ierr; 1703 1704 PetscFunctionBegin; 1705 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1706 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1707 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1708 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1709 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1710 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1711 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1712 switch(dim) { 1713 case 2: 1714 switch(coneSize) { 1715 case 3: 1716 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1717 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1718 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1719 *numFaces = 3; 1720 *faceSize = 2; 1721 *faces = mesh->facesTmp; 1722 break; 1723 case 4: 1724 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1725 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1726 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1727 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1728 *numFaces = 4; 1729 *faceSize = 2; 1730 *faces = mesh->facesTmp; 1731 break; 1732 default: 1733 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1734 } 1735 break; 1736 case 3: 1737 switch(coneSize) { 1738 case 3: 1739 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1740 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1741 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1742 *numFaces = 3; 1743 *faceSize = 2; 1744 *faces = mesh->facesTmp; 1745 break; 1746 case 4: 1747 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1748 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1749 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1750 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1751 *numFaces = 4; 1752 *faceSize = 3; 1753 *faces = mesh->facesTmp; 1754 break; 1755 default: 1756 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1757 } 1758 break; 1759 default: 1760 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1761 } 1762 PetscFunctionReturn(0); 1763 } 1764 1765 #undef __FUNCT__ 1766 #define __FUNCT__ "DMPlexGetMaxSizes" 1767 /*@ 1768 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1769 1770 Not collective 1771 1772 Input Parameter: 1773 . mesh - The DMPlex 1774 1775 Output Parameters: 1776 + maxConeSize - The maximum number of in-edges 1777 - maxSupportSize - The maximum number of out-edges 1778 1779 Level: beginner 1780 1781 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1782 @*/ 1783 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1784 { 1785 DM_Plex *mesh = (DM_Plex *) dm->data; 1786 1787 PetscFunctionBegin; 1788 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1789 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1790 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1791 PetscFunctionReturn(0); 1792 } 1793 1794 #undef __FUNCT__ 1795 #define __FUNCT__ "DMSetUp_Plex" 1796 PetscErrorCode DMSetUp_Plex(DM dm) 1797 { 1798 DM_Plex *mesh = (DM_Plex *) dm->data; 1799 PetscInt size; 1800 PetscErrorCode ierr; 1801 1802 PetscFunctionBegin; 1803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1804 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1805 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1806 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1807 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1808 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1809 if (mesh->maxSupportSize) { 1810 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1811 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1812 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1813 } 1814 PetscFunctionReturn(0); 1815 } 1816 1817 #undef __FUNCT__ 1818 #define __FUNCT__ "DMCreateSubDM_Plex" 1819 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1820 { 1821 PetscSection section, sectionGlobal; 1822 PetscInt *subIndices; 1823 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1824 PetscErrorCode ierr; 1825 1826 PetscFunctionBegin; 1827 if (!numFields) PetscFunctionReturn(0); 1828 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1829 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1830 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1831 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1832 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1833 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 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1835 for (p = pStart; p < pEnd; ++p) { 1836 PetscInt gdof; 1837 1838 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1839 if (gdof > 0) { 1840 for (f = 0; f < numFields; ++f) { 1841 PetscInt fdof, fcdof; 1842 1843 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1844 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1845 subSize += fdof-fcdof; 1846 } 1847 } 1848 } 1849 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1850 for (p = pStart; p < pEnd; ++p) { 1851 PetscInt gdof, goff; 1852 1853 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1854 if (gdof > 0) { 1855 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1856 for (f = 0; f < numFields; ++f) { 1857 PetscInt fdof, fcdof, fc, f2, poff = 0; 1858 1859 /* Can get rid of this loop by storing field information in the global section */ 1860 for (f2 = 0; f2 < fields[f]; ++f2) { 1861 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1862 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1863 poff += fdof-fcdof; 1864 } 1865 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1866 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1867 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1868 subIndices[subOff] = goff+poff+fc; 1869 } 1870 } 1871 } 1872 } 1873 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1874 if (subdm) { 1875 PetscSection subsection; 1876 PetscBool haveNull = PETSC_FALSE; 1877 PetscInt f, nf = 0; 1878 1879 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1880 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1881 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1882 for (f = 0; f < numFields; ++f) { 1883 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1884 if ((*subdm)->nullspaceConstructors[f]) { 1885 haveNull = PETSC_TRUE; 1886 nf = f; 1887 } 1888 } 1889 if (haveNull) { 1890 MatNullSpace nullSpace; 1891 1892 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1893 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1894 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1895 } 1896 if (dm->fields) { 1897 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 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1899 for (f = 0; f < numFields; ++f) { 1900 ierr = PetscOListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist); 1901 } 1902 if (numFields == 1) { 1903 MatNullSpace space; 1904 Mat pmat; 1905 1906 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr); 1907 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1908 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr); 1909 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1910 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr); 1911 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1912 } 1913 } 1914 } 1915 PetscFunctionReturn(0); 1916 } 1917 1918 #undef __FUNCT__ 1919 #define __FUNCT__ "DMPlexSymmetrize" 1920 /*@ 1921 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1922 1923 Not collective 1924 1925 Input Parameter: 1926 . mesh - The DMPlex 1927 1928 Output Parameter: 1929 1930 Note: 1931 This should be called after all calls to DMPlexSetCone() 1932 1933 Level: beginner 1934 1935 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1936 @*/ 1937 PetscErrorCode DMPlexSymmetrize(DM dm) 1938 { 1939 DM_Plex *mesh = (DM_Plex *) dm->data; 1940 PetscInt *offsets; 1941 PetscInt supportSize; 1942 PetscInt pStart, pEnd, p; 1943 PetscErrorCode ierr; 1944 1945 PetscFunctionBegin; 1946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1947 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1948 /* Calculate support sizes */ 1949 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1950 for (p = pStart; p < pEnd; ++p) { 1951 PetscInt dof, off, c; 1952 1953 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1954 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1955 for (c = off; c < off+dof; ++c) { 1956 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1957 } 1958 } 1959 for (p = pStart; p < pEnd; ++p) { 1960 PetscInt dof; 1961 1962 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1963 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1964 } 1965 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1966 /* Calculate supports */ 1967 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1968 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1969 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1970 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1971 for (p = pStart; p < pEnd; ++p) { 1972 PetscInt dof, off, c; 1973 1974 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1975 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1976 for (c = off; c < off+dof; ++c) { 1977 const PetscInt q = mesh->cones[c]; 1978 PetscInt offS; 1979 1980 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1981 mesh->supports[offS+offsets[q]] = p; 1982 ++offsets[q]; 1983 } 1984 } 1985 ierr = PetscFree(offsets);CHKERRQ(ierr); 1986 PetscFunctionReturn(0); 1987 } 1988 1989 #undef __FUNCT__ 1990 #define __FUNCT__ "DMPlexSetDepth_Private" 1991 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1992 { 1993 PetscInt d; 1994 PetscErrorCode ierr; 1995 1996 PetscFunctionBegin; 1997 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1998 if (d < 0) { 1999 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2000 const PetscInt *cone = PETSC_NULL; 2001 PetscInt dCone; 2002 2003 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2004 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2005 d = dCone+1; 2006 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2007 } 2008 *depth = d; 2009 PetscFunctionReturn(0); 2010 } 2011 2012 #undef __FUNCT__ 2013 #define __FUNCT__ "DMPlexStratify" 2014 /*@ 2015 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2016 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2017 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2018 the DAG. 2019 2020 Not collective 2021 2022 Input Parameter: 2023 . mesh - The DMPlex 2024 2025 Output Parameter: 2026 2027 Notes: 2028 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2029 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2030 2031 This should be called after all calls to DMPlexSymmetrize() 2032 2033 Level: beginner 2034 2035 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2036 @*/ 2037 PetscErrorCode DMPlexStratify(DM dm) 2038 { 2039 DM_Plex *mesh = (DM_Plex *) dm->data; 2040 PetscInt pStart, pEnd, p; 2041 PetscInt numRoots = 0, numLeaves = 0; 2042 PetscErrorCode ierr; 2043 2044 PetscFunctionBegin; 2045 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2046 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2047 /* Calculate depth */ 2048 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2049 /* Initialize roots and count leaves */ 2050 for (p = pStart; p < pEnd; ++p) { 2051 PetscInt coneSize, supportSize; 2052 2053 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2054 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2055 if (!coneSize && supportSize) { 2056 ++numRoots; 2057 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2058 } else if (!supportSize && coneSize) { 2059 ++numLeaves; 2060 } else if (!supportSize && !coneSize) { 2061 /* Isolated points */ 2062 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2063 } 2064 } 2065 if (numRoots + numLeaves == (pEnd - pStart)) { 2066 for (p = pStart; p < pEnd; ++p) { 2067 PetscInt coneSize, supportSize; 2068 2069 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2070 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2071 if (!supportSize && coneSize) { 2072 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2073 } 2074 } 2075 } else { 2076 /* This might be slow since lookup is not fast */ 2077 for (p = pStart; p < pEnd; ++p) { 2078 PetscInt depth; 2079 2080 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2081 } 2082 } 2083 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2084 PetscFunctionReturn(0); 2085 } 2086 2087 #undef __FUNCT__ 2088 #define __FUNCT__ "DMPlexGetJoin" 2089 /*@C 2090 DMPlexGetJoin - Get an array for the join of the set of points 2091 2092 Not Collective 2093 2094 Input Parameters: 2095 + dm - The DMPlex object 2096 . numPoints - The number of input points for the join 2097 - points - The input points 2098 2099 Output Parameters: 2100 + numCoveredPoints - The number of points in the join 2101 - coveredPoints - The points in the join 2102 2103 Level: intermediate 2104 2105 Note: Currently, this is restricted to a single level join 2106 2107 .keywords: mesh 2108 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2109 @*/ 2110 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2111 { 2112 DM_Plex *mesh = (DM_Plex *) dm->data; 2113 PetscInt *join[2]; 2114 PetscInt joinSize, i = 0; 2115 PetscInt dof, off, p, c, m; 2116 PetscErrorCode ierr; 2117 2118 PetscFunctionBegin; 2119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2120 PetscValidPointer(points, 2); 2121 PetscValidPointer(numCoveredPoints, 3); 2122 PetscValidPointer(coveredPoints, 4); 2123 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2124 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2125 /* Copy in support of first point */ 2126 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2127 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2128 for (joinSize = 0; joinSize < dof; ++joinSize) { 2129 join[i][joinSize] = mesh->supports[off+joinSize]; 2130 } 2131 /* Check each successive support */ 2132 for (p = 1; p < numPoints; ++p) { 2133 PetscInt newJoinSize = 0; 2134 2135 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2136 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2137 for (c = 0; c < dof; ++c) { 2138 const PetscInt point = mesh->supports[off+c]; 2139 2140 for (m = 0; m < joinSize; ++m) { 2141 if (point == join[i][m]) { 2142 join[1-i][newJoinSize++] = point; 2143 break; 2144 } 2145 } 2146 } 2147 joinSize = newJoinSize; 2148 i = 1-i; 2149 } 2150 *numCoveredPoints = joinSize; 2151 *coveredPoints = join[i]; 2152 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2153 PetscFunctionReturn(0); 2154 } 2155 2156 #undef __FUNCT__ 2157 #define __FUNCT__ "DMPlexRestoreJoin" 2158 /*@C 2159 DMPlexRestoreJoin - Restore an array for the join of the set of points 2160 2161 Not Collective 2162 2163 Input Parameters: 2164 + dm - The DMPlex object 2165 . numPoints - The number of input points for the join 2166 - points - The input points 2167 2168 Output Parameters: 2169 + numCoveredPoints - The number of points in the join 2170 - coveredPoints - The points in the join 2171 2172 Level: intermediate 2173 2174 .keywords: mesh 2175 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2176 @*/ 2177 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2178 { 2179 PetscErrorCode ierr; 2180 2181 PetscFunctionBegin; 2182 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2183 PetscValidPointer(coveredPoints, 4); 2184 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2185 PetscFunctionReturn(0); 2186 } 2187 2188 #undef __FUNCT__ 2189 #define __FUNCT__ "DMPlexGetFullJoin" 2190 /*@C 2191 DMPlexGetFullJoin - Get an array for the join of the set of points 2192 2193 Not Collective 2194 2195 Input Parameters: 2196 + dm - The DMPlex object 2197 . numPoints - The number of input points for the join 2198 - points - The input points 2199 2200 Output Parameters: 2201 + numCoveredPoints - The number of points in the join 2202 - coveredPoints - The points in the join 2203 2204 Level: intermediate 2205 2206 .keywords: mesh 2207 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2208 @*/ 2209 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2210 { 2211 DM_Plex *mesh = (DM_Plex *) dm->data; 2212 PetscInt *offsets, **closures; 2213 PetscInt *join[2]; 2214 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2215 PetscInt p, d, c, m; 2216 PetscErrorCode ierr; 2217 2218 PetscFunctionBegin; 2219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2220 PetscValidPointer(points, 2); 2221 PetscValidPointer(numCoveredPoints, 3); 2222 PetscValidPointer(coveredPoints, 4); 2223 2224 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2225 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2226 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2227 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2228 maxSize = (PetscInt) (pow((PetscReal) mesh->maxSupportSize, depth)+1); 2229 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2230 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2231 2232 for (p = 0; p < numPoints; ++p) { 2233 PetscInt closureSize; 2234 2235 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2236 offsets[p*(depth+2)+0] = 0; 2237 for (d = 0; d < depth+1; ++d) { 2238 PetscInt pStart, pEnd, i; 2239 2240 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2241 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2242 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2243 offsets[p*(depth+2)+d+1] = i; 2244 break; 2245 } 2246 } 2247 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2248 } 2249 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 } 2251 for (d = 0; d < depth+1; ++d) { 2252 PetscInt dof; 2253 2254 /* Copy in support of first point */ 2255 dof = offsets[d+1] - offsets[d]; 2256 for (joinSize = 0; joinSize < dof; ++joinSize) { 2257 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2258 } 2259 /* Check each successive cone */ 2260 for (p = 1; p < numPoints && joinSize; ++p) { 2261 PetscInt newJoinSize = 0; 2262 2263 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2264 for (c = 0; c < dof; ++c) { 2265 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2266 2267 for (m = 0; m < joinSize; ++m) { 2268 if (point == join[i][m]) { 2269 join[1-i][newJoinSize++] = point; 2270 break; 2271 } 2272 } 2273 } 2274 joinSize = newJoinSize; 2275 i = 1-i; 2276 } 2277 if (joinSize) break; 2278 } 2279 *numCoveredPoints = joinSize; 2280 *coveredPoints = join[i]; 2281 for (p = 0; p < numPoints; ++p) { 2282 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2283 } 2284 ierr = PetscFree(closures);CHKERRQ(ierr); 2285 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2286 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2287 PetscFunctionReturn(0); 2288 } 2289 2290 #undef __FUNCT__ 2291 #define __FUNCT__ "DMPlexGetMeet" 2292 /*@C 2293 DMPlexGetMeet - Get an array for the meet of the set of points 2294 2295 Not Collective 2296 2297 Input Parameters: 2298 + dm - The DMPlex object 2299 . numPoints - The number of input points for the meet 2300 - points - The input points 2301 2302 Output Parameters: 2303 + numCoveredPoints - The number of points in the meet 2304 - coveredPoints - The points in the meet 2305 2306 Level: intermediate 2307 2308 Note: Currently, this is restricted to a single level meet 2309 2310 .keywords: mesh 2311 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2312 @*/ 2313 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2314 { 2315 DM_Plex *mesh = (DM_Plex *) dm->data; 2316 PetscInt *meet[2]; 2317 PetscInt meetSize, i = 0; 2318 PetscInt dof, off, p, c, m; 2319 PetscErrorCode ierr; 2320 2321 PetscFunctionBegin; 2322 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2323 PetscValidPointer(points, 2); 2324 PetscValidPointer(numCoveringPoints, 3); 2325 PetscValidPointer(coveringPoints, 4); 2326 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2327 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2328 /* Copy in cone of first point */ 2329 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2330 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2331 for (meetSize = 0; meetSize < dof; ++meetSize) { 2332 meet[i][meetSize] = mesh->cones[off+meetSize]; 2333 } 2334 /* Check each successive cone */ 2335 for (p = 1; p < numPoints; ++p) { 2336 PetscInt newMeetSize = 0; 2337 2338 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2339 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2340 for (c = 0; c < dof; ++c) { 2341 const PetscInt point = mesh->cones[off+c]; 2342 2343 for (m = 0; m < meetSize; ++m) { 2344 if (point == meet[i][m]) { 2345 meet[1-i][newMeetSize++] = point; 2346 break; 2347 } 2348 } 2349 } 2350 meetSize = newMeetSize; 2351 i = 1-i; 2352 } 2353 *numCoveringPoints = meetSize; 2354 *coveringPoints = meet[i]; 2355 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2356 PetscFunctionReturn(0); 2357 } 2358 2359 #undef __FUNCT__ 2360 #define __FUNCT__ "DMPlexRestoreMeet" 2361 /*@C 2362 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2363 2364 Not Collective 2365 2366 Input Parameters: 2367 + dm - The DMPlex object 2368 . numPoints - The number of input points for the meet 2369 - points - The input points 2370 2371 Output Parameters: 2372 + numCoveredPoints - The number of points in the meet 2373 - coveredPoints - The points in the meet 2374 2375 Level: intermediate 2376 2377 .keywords: mesh 2378 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2379 @*/ 2380 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2381 { 2382 PetscErrorCode ierr; 2383 2384 PetscFunctionBegin; 2385 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2386 PetscValidPointer(coveredPoints, 4); 2387 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2388 PetscFunctionReturn(0); 2389 } 2390 2391 #undef __FUNCT__ 2392 #define __FUNCT__ "DMPlexGetFullMeet" 2393 /*@C 2394 DMPlexGetFullMeet - Get an array for the meet of the set of points 2395 2396 Not Collective 2397 2398 Input Parameters: 2399 + dm - The DMPlex object 2400 . numPoints - The number of input points for the meet 2401 - points - The input points 2402 2403 Output Parameters: 2404 + numCoveredPoints - The number of points in the meet 2405 - coveredPoints - The points in the meet 2406 2407 Level: intermediate 2408 2409 .keywords: mesh 2410 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2411 @*/ 2412 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2413 { 2414 DM_Plex *mesh = (DM_Plex *) dm->data; 2415 PetscInt *offsets, **closures; 2416 PetscInt *meet[2]; 2417 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2418 PetscInt p, h, c, m; 2419 PetscErrorCode ierr; 2420 2421 PetscFunctionBegin; 2422 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2423 PetscValidPointer(points, 2); 2424 PetscValidPointer(numCoveredPoints, 3); 2425 PetscValidPointer(coveredPoints, 4); 2426 2427 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2428 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2429 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2430 maxSize = (PetscInt) (pow((PetscReal) mesh->maxConeSize, height)+1); 2431 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2432 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2433 2434 for (p = 0; p < numPoints; ++p) { 2435 PetscInt closureSize; 2436 2437 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2438 offsets[p*(height+2)+0] = 0; 2439 for (h = 0; h < height+1; ++h) { 2440 PetscInt pStart, pEnd, i; 2441 2442 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2443 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2444 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2445 offsets[p*(height+2)+h+1] = i; 2446 break; 2447 } 2448 } 2449 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2450 } 2451 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 } 2453 for (h = 0; h < height+1; ++h) { 2454 PetscInt dof; 2455 2456 /* Copy in cone of first point */ 2457 dof = offsets[h+1] - offsets[h]; 2458 for (meetSize = 0; meetSize < dof; ++meetSize) { 2459 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2460 } 2461 /* Check each successive cone */ 2462 for (p = 1; p < numPoints && meetSize; ++p) { 2463 PetscInt newMeetSize = 0; 2464 2465 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2466 for (c = 0; c < dof; ++c) { 2467 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2468 2469 for (m = 0; m < meetSize; ++m) { 2470 if (point == meet[i][m]) { 2471 meet[1-i][newMeetSize++] = point; 2472 break; 2473 } 2474 } 2475 } 2476 meetSize = newMeetSize; 2477 i = 1-i; 2478 } 2479 if (meetSize) break; 2480 } 2481 *numCoveredPoints = meetSize; 2482 *coveredPoints = meet[i]; 2483 for (p = 0; p < numPoints; ++p) { 2484 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2485 } 2486 ierr = PetscFree(closures);CHKERRQ(ierr); 2487 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2488 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2489 PetscFunctionReturn(0); 2490 } 2491 2492 #undef __FUNCT__ 2493 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2494 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) { 2495 MPI_Comm comm = ((PetscObject) dm)->comm; 2496 PetscInt cellDim; 2497 PetscErrorCode ierr; 2498 2499 PetscFunctionBegin; 2500 PetscValidPointer(numFaceVertices,3); 2501 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2502 switch(cellDim) { 2503 case 0: 2504 *numFaceVertices = 0; 2505 break; 2506 case 1: 2507 *numFaceVertices = 1; 2508 break; 2509 case 2: 2510 switch(numCorners) { 2511 case 3: // triangle 2512 *numFaceVertices = 2; // Edge has 2 vertices 2513 break; 2514 case 4: // quadrilateral 2515 *numFaceVertices = 2; // Edge has 2 vertices 2516 break; 2517 case 6: // quadratic triangle, tri and quad cohesive Lagrange cells 2518 *numFaceVertices = 3; // Edge has 3 vertices 2519 break; 2520 case 9: // quadratic quadrilateral, quadratic quad cohesive Lagrange cells 2521 *numFaceVertices = 3; // Edge has 3 vertices 2522 break; 2523 default: 2524 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2525 } 2526 break; 2527 case 3: 2528 switch(numCorners) { 2529 case 4: // tetradehdron 2530 *numFaceVertices = 3; // Face has 3 vertices 2531 break; 2532 case 6: // tet cohesive cells 2533 *numFaceVertices = 4; // Face has 4 vertices 2534 break; 2535 case 8: // hexahedron 2536 *numFaceVertices = 4; // Face has 4 vertices 2537 break; 2538 case 9: // tet cohesive Lagrange cells 2539 *numFaceVertices = 6; // Face has 6 vertices 2540 break; 2541 case 10: // quadratic tetrahedron 2542 *numFaceVertices = 6; // Face has 6 vertices 2543 break; 2544 case 12: // hex cohesive Lagrange cells 2545 *numFaceVertices = 6; // Face has 6 vertices 2546 break; 2547 case 18: // quadratic tet cohesive Lagrange cells 2548 *numFaceVertices = 6; // Face has 6 vertices 2549 break; 2550 case 27: // quadratic hexahedron, quadratic hex cohesive Lagrange cells 2551 *numFaceVertices = 9; // Face has 9 vertices 2552 break; 2553 default: 2554 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2555 } 2556 break; 2557 default: 2558 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2559 } 2560 PetscFunctionReturn(0); 2561 } 2562 2563 #undef __FUNCT__ 2564 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2565 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) { 2566 const PetscInt maxFaceCases = 30; 2567 PetscInt numFaceCases = 0; 2568 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2569 PetscInt *off, *adj; 2570 PetscInt *neighborCells, *tmpClosure; 2571 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2572 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2573 PetscErrorCode ierr; 2574 2575 PetscFunctionBegin; 2576 /* For parallel partitioning, I think you have to communicate supports */ 2577 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2578 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2579 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2580 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2581 if (cEnd - cStart == 0) { 2582 if (numVertices) *numVertices = 0; 2583 if (offsets) *offsets = PETSC_NULL; 2584 if (adjacency) *adjacency = PETSC_NULL; 2585 PetscFunctionReturn(0); 2586 } 2587 numCells = cEnd - cStart; 2588 /* Setup face recognition */ 2589 { 2590 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 2592 for (c = cStart; c < cEnd; ++c) { 2593 PetscInt corners; 2594 2595 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2596 if (!cornersSeen[corners]) { 2597 PetscInt nFV; 2598 2599 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2600 cornersSeen[corners] = 1; 2601 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2602 numFaceVertices[numFaceCases++] = nFV; 2603 } 2604 } 2605 } 2606 maxClosure = (PetscInt) (2*PetscMax(pow((PetscReal) maxConeSize, depth)+1, pow((PetscReal) maxSupportSize, depth)+1)); 2607 maxNeighbors = (PetscInt) (pow((PetscReal) maxConeSize, depth)*pow((PetscReal) maxSupportSize, depth)+1); 2608 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2609 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2610 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2611 /* Count neighboring cells */ 2612 for (cell = cStart; cell < cEnd; ++cell) { 2613 PetscInt numNeighbors = maxNeighbors, n; 2614 2615 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2616 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2617 for (n = 0; n < numNeighbors; ++n) { 2618 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2619 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2620 PetscInt meetSize = 0; 2621 const PetscInt *meet = PETSC_NULL; 2622 2623 if (cellPair[0] == cellPair[1]) continue; 2624 if (!found) { 2625 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2626 if (meetSize) { 2627 PetscInt f; 2628 2629 for (f = 0; f < numFaceCases; ++f) { 2630 if (numFaceVertices[f] == meetSize) { 2631 found = PETSC_TRUE; 2632 break; 2633 } 2634 } 2635 } 2636 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2637 } 2638 if (found) { 2639 ++off[cell-cStart+1]; 2640 } 2641 } 2642 } 2643 /* Prefix sum */ 2644 for (cell = 1; cell <= numCells; ++cell) { 2645 off[cell] += off[cell-1]; 2646 } 2647 if (adjacency) { 2648 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2649 /* Get neighboring cells */ 2650 for (cell = cStart; cell < cEnd; ++cell) { 2651 PetscInt numNeighbors = maxNeighbors, n; 2652 PetscInt cellOffset = 0; 2653 2654 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2655 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2656 for (n = 0; n < numNeighbors; ++n) { 2657 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2658 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2659 PetscInt meetSize = 0; 2660 const PetscInt *meet = PETSC_NULL; 2661 2662 if (cellPair[0] == cellPair[1]) continue; 2663 if (!found) { 2664 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2665 if (meetSize) { 2666 PetscInt f; 2667 2668 for (f = 0; f < numFaceCases; ++f) { 2669 if (numFaceVertices[f] == meetSize) { 2670 found = PETSC_TRUE; 2671 break; 2672 } 2673 } 2674 } 2675 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2676 } 2677 if (found) { 2678 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2679 ++cellOffset; 2680 } 2681 } 2682 } 2683 } 2684 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2685 if (numVertices) *numVertices = numCells; 2686 if (offsets) *offsets = off; 2687 if (adjacency) *adjacency = adj; 2688 PetscFunctionReturn(0); 2689 } 2690 2691 #ifdef PETSC_HAVE_CHACO 2692 #ifdef PETSC_HAVE_UNISTD_H 2693 #include <unistd.h> 2694 #endif 2695 /* Chaco does not have an include file */ 2696 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2697 float *ewgts, float *x, float *y, float *z, char *outassignname, 2698 char *outfilename, short *assignment, int architecture, int ndims_tot, 2699 int mesh_dims[3], double *goal, int global_method, int local_method, 2700 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2701 2702 extern int FREE_GRAPH; 2703 2704 #undef __FUNCT__ 2705 #define __FUNCT__ "DMPlexPartition_Chaco" 2706 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2707 { 2708 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2709 MPI_Comm comm = ((PetscObject) dm)->comm; 2710 int nvtxs = numVertices; /* number of vertices in full graph */ 2711 int *vwgts = NULL; /* weights for all vertices */ 2712 float *ewgts = NULL; /* weights for all edges */ 2713 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2714 char *outassignname = NULL; /* name of assignment output file */ 2715 char *outfilename = NULL; /* output file name */ 2716 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2717 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2718 int mesh_dims[3]; /* dimensions of mesh of processors */ 2719 double *goal = NULL; /* desired set sizes for each set */ 2720 int global_method = 1; /* global partitioning algorithm */ 2721 int local_method = 1; /* local partitioning algorithm */ 2722 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2723 int vmax = 200; /* how many vertices to coarsen down to? */ 2724 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2725 double eigtol = 0.001; /* tolerance on eigenvectors */ 2726 long seed = 123636512; /* for random graph mutations */ 2727 short int *assignment; /* Output partition */ 2728 int fd_stdout, fd_pipe[2]; 2729 PetscInt *points; 2730 PetscMPIInt commSize; 2731 int i, v, p; 2732 PetscErrorCode ierr; 2733 2734 PetscFunctionBegin; 2735 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2736 if (!numVertices) { 2737 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2738 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2739 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2740 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2741 PetscFunctionReturn(0); 2742 } 2743 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2744 for (i = 0; i < start[numVertices]; ++i) { 2745 ++adjacency[i]; 2746 } 2747 if (global_method == INERTIAL_METHOD) { 2748 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2749 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2750 } 2751 mesh_dims[0] = commSize; 2752 mesh_dims[1] = 1; 2753 mesh_dims[2] = 1; 2754 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2755 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2756 /* TODO: check error codes for UNIX calls */ 2757 #ifdef PETSC_HAVE_UNISTD_H 2758 { 2759 fd_stdout = dup(1); 2760 pipe(fd_pipe); 2761 close(1); 2762 dup2(fd_pipe[1], 1); 2763 } 2764 #endif 2765 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2766 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2767 vmax, ndims, eigtol, seed); 2768 #ifdef PETSC_HAVE_UNISTD_H 2769 { 2770 char msgLog[10000]; 2771 int count; 2772 2773 fflush(stdout); 2774 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2775 if (count < 0) count = 0; 2776 msgLog[count] = 0; 2777 close(1); 2778 dup2(fd_stdout, 1); 2779 close(fd_stdout); 2780 close(fd_pipe[0]); 2781 close(fd_pipe[1]); 2782 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2783 } 2784 #endif 2785 /* Convert to PetscSection+IS */ 2786 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2787 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2788 for (v = 0; v < nvtxs; ++v) { 2789 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2790 } 2791 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2792 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2793 for (p = 0, i = 0; p < commSize; ++p) { 2794 for (v = 0; v < nvtxs; ++v) { 2795 if (assignment[v] == p) points[i++] = v; 2796 } 2797 } 2798 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2799 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2800 if (global_method == INERTIAL_METHOD) { 2801 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2802 } 2803 ierr = PetscFree(assignment);CHKERRQ(ierr); 2804 for (i = 0; i < start[numVertices]; ++i) { 2805 --adjacency[i]; 2806 } 2807 PetscFunctionReturn(0); 2808 } 2809 #endif 2810 2811 #ifdef PETSC_HAVE_PARMETIS 2812 #undef __FUNCT__ 2813 #define __FUNCT__ "DMPlexPartition_ParMetis" 2814 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2815 { 2816 PetscFunctionBegin; 2817 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2818 PetscFunctionReturn(0); 2819 } 2820 #endif 2821 2822 #undef __FUNCT__ 2823 #define __FUNCT__ "DMPlexEnlargePartition" 2824 /* Expand the partition by BFS on the adjacency graph */ 2825 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) { 2826 PetscHashI h; 2827 const PetscInt *points; 2828 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2829 PetscInt pStart, pEnd, part, q; 2830 PetscErrorCode ierr; 2831 2832 PetscFunctionBegin; 2833 PetscHashICreate(h); 2834 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2835 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2836 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2837 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2838 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2839 for(part = pStart; part < pEnd; ++part) { 2840 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2841 2842 PetscHashIClear(h); 2843 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2844 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2845 /* Add all existing points to h */ 2846 for(p = 0; p < numPoints; ++p) { 2847 const PetscInt point = points[off+p]; 2848 PetscHashIAdd(h, point, 1); 2849 } 2850 PetscHashISize(h, nP); 2851 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2852 /* Add all points in next BFS level */ 2853 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2854 for(p = 0; p < numPoints; ++p) { 2855 const PetscInt point = points[off+p]; 2856 PetscInt s = start[point], e = start[point+1], a; 2857 2858 for(a = s; a < e; ++a) { 2859 PetscHashIAdd(h, adjacency[a], 1); 2860 } 2861 } 2862 PetscHashISize(h, numNewPoints); 2863 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2864 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2865 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2866 totPoints += numNewPoints; 2867 } 2868 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2869 PetscHashIDestroy(h); 2870 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2871 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2872 for(part = pStart, q = 0; part < pEnd; ++part) { 2873 PetscInt numPoints, p; 2874 2875 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2876 for(p = 0; p < numPoints; ++p, ++q) { 2877 newPoints[q] = tmpPoints[part][p]; 2878 } 2879 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2880 } 2881 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2882 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2883 PetscFunctionReturn(0); 2884 } 2885 2886 #undef __FUNCT__ 2887 #define __FUNCT__ "DMPlexCreatePartition" 2888 /* 2889 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2890 2891 Collective on DM 2892 2893 Input Parameters: 2894 + dm - The DM 2895 . height - The height for points in the partition 2896 - enlarge - Expand each partition with neighbors 2897 2898 Output Parameters: 2899 + partSection - The PetscSection giving the division of points by partition 2900 . partition - The list of points by partition 2901 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2902 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2903 2904 Level: developer 2905 2906 .seealso DMPlexDistribute() 2907 */ 2908 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) { 2909 PetscMPIInt size; 2910 PetscErrorCode ierr; 2911 2912 PetscFunctionBegin; 2913 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2914 *origPartSection = PETSC_NULL; 2915 *origPartition = PETSC_NULL; 2916 if (size == 1) { 2917 PetscInt *points; 2918 PetscInt cStart, cEnd, c; 2919 2920 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2921 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2922 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2923 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2924 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2925 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2926 for (c = cStart; c < cEnd; ++c) { 2927 points[c] = c; 2928 } 2929 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2930 PetscFunctionReturn(0); 2931 } 2932 if (height == 0) { 2933 PetscInt numVertices; 2934 PetscInt *start = PETSC_NULL; 2935 PetscInt *adjacency = PETSC_NULL; 2936 2937 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2938 if (1) { 2939 #ifdef PETSC_HAVE_CHACO 2940 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2941 #endif 2942 } else { 2943 #ifdef PETSC_HAVE_PARMETIS 2944 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2945 #endif 2946 } 2947 if (enlarge) { 2948 *origPartSection = *partSection; 2949 *origPartition = *partition; 2950 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2951 } 2952 ierr = PetscFree(start);CHKERRQ(ierr); 2953 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2954 # if 0 2955 } else if (height == 1) { 2956 /* Build the dual graph for faces and partition the hypergraph */ 2957 PetscInt numEdges; 2958 2959 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2960 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2961 destroyCSR(numEdges, start, adjacency); 2962 #endif 2963 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2964 PetscFunctionReturn(0); 2965 } 2966 2967 #undef __FUNCT__ 2968 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2969 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) { 2970 /* const PetscInt height = 0; */ 2971 const PetscInt *partArray; 2972 PetscInt *allPoints, *partPoints = PETSC_NULL; 2973 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2974 PetscErrorCode ierr; 2975 2976 PetscFunctionBegin; 2977 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2978 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2979 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2980 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2981 for (rank = rStart; rank < rEnd; ++rank) { 2982 PetscInt partSize = 0; 2983 PetscInt numPoints, offset, p; 2984 2985 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2986 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2987 for (p = 0; p < numPoints; ++p) { 2988 PetscInt point = partArray[offset+p], closureSize, c; 2989 PetscInt *closure = PETSC_NULL; 2990 2991 /* TODO Include support for height > 0 case */ 2992 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2993 /* Merge into existing points */ 2994 if (partSize+closureSize > maxPartSize) { 2995 PetscInt *tmpPoints; 2996 2997 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2998 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2999 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3000 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3001 partPoints = tmpPoints; 3002 } 3003 for (c = 0; c < closureSize; ++c) { 3004 partPoints[partSize+c] = closure[c*2]; 3005 } 3006 partSize += closureSize; 3007 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3008 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3009 } 3010 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3011 } 3012 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3013 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3014 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3015 3016 for (rank = rStart; rank < rEnd; ++rank) { 3017 PetscInt partSize = 0, newOffset; 3018 PetscInt numPoints, offset, p; 3019 3020 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3021 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3022 for (p = 0; p < numPoints; ++p) { 3023 PetscInt point = partArray[offset+p], closureSize, c; 3024 PetscInt *closure = PETSC_NULL; 3025 3026 /* TODO Include support for height > 0 case */ 3027 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3028 /* Merge into existing points */ 3029 for (c = 0; c < closureSize; ++c) { 3030 partPoints[partSize+c] = closure[c*2]; 3031 } 3032 partSize += closureSize; 3033 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3034 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3035 } 3036 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3037 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3038 } 3039 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3040 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3041 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3042 PetscFunctionReturn(0); 3043 } 3044 3045 #undef __FUNCT__ 3046 #define __FUNCT__ "DMPlexDistributeField" 3047 /* 3048 Input Parameters: 3049 . originalSection 3050 , originalVec 3051 3052 Output Parameters: 3053 . newSection 3054 . newVec 3055 */ 3056 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3057 { 3058 PetscSF fieldSF; 3059 PetscInt *remoteOffsets, fieldSize; 3060 PetscScalar *originalValues, *newValues; 3061 PetscErrorCode ierr; 3062 3063 PetscFunctionBegin; 3064 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3065 3066 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3067 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3068 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3069 3070 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3071 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3072 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3073 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3074 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3075 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3076 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3077 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3078 PetscFunctionReturn(0); 3079 } 3080 3081 #undef __FUNCT__ 3082 #define __FUNCT__ "DMPlexDistribute" 3083 /*@C 3084 DMPlexDistribute - Distributes the mesh and any associated sections. 3085 3086 Not Collective 3087 3088 Input Parameter: 3089 + dm - The original DMPlex object 3090 . partitioner - The partitioning package, or NULL for the default 3091 - overlap - The overlap of partitions, 0 is the default 3092 3093 Output Parameter: 3094 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3095 3096 Note: If the mesh was not distributed, the return value is PETSC_NULL 3097 3098 Level: intermediate 3099 3100 .keywords: mesh, elements 3101 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3102 @*/ 3103 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3104 { 3105 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3106 MPI_Comm comm = ((PetscObject) dm)->comm; 3107 const PetscInt height = 0; 3108 PetscInt dim, numRemoteRanks; 3109 IS origCellPart, cellPart, part; 3110 PetscSection origCellPartSection, cellPartSection, partSection; 3111 PetscSFNode *remoteRanks; 3112 PetscSF partSF, pointSF, coneSF; 3113 ISLocalToGlobalMapping renumbering; 3114 PetscSection originalConeSection, newConeSection; 3115 PetscInt *remoteOffsets; 3116 PetscInt *cones, *newCones, newConesSize; 3117 PetscBool flg; 3118 PetscMPIInt rank, numProcs, p; 3119 PetscErrorCode ierr; 3120 3121 PetscFunctionBegin; 3122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3123 PetscValidPointer(dmParallel,4); 3124 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3125 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3126 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3127 *dmParallel = PETSC_NULL; 3128 if (numProcs == 1) PetscFunctionReturn(0); 3129 3130 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3131 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3132 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3133 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3134 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3135 if (!rank) { 3136 numRemoteRanks = numProcs; 3137 } else { 3138 numRemoteRanks = 0; 3139 } 3140 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3141 for (p = 0; p < numRemoteRanks; ++p) { 3142 remoteRanks[p].rank = p; 3143 remoteRanks[p].index = 0; 3144 } 3145 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3146 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3147 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3148 if (flg) { 3149 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3150 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3151 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3152 if (origCellPart) { 3153 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3154 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3155 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3156 } 3157 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3158 } 3159 /* Close the partition over the mesh */ 3160 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3161 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3162 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3163 /* Create new mesh */ 3164 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3165 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3166 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3167 pmesh = (DM_Plex *) (*dmParallel)->data; 3168 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3169 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3170 if (flg) { 3171 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3172 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3173 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3174 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3175 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3176 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3177 } 3178 /* Distribute cone section */ 3179 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3180 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3181 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3182 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3183 { 3184 PetscInt pStart, pEnd, p; 3185 3186 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3187 for (p = pStart; p < pEnd; ++p) { 3188 PetscInt coneSize; 3189 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3190 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3191 } 3192 } 3193 /* Communicate and renumber cones */ 3194 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3195 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3196 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3197 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3198 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3199 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3200 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3201 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3202 if (flg) { 3203 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3204 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3205 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3206 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3207 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3208 } 3209 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3210 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3211 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3212 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3213 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3214 /* Create supports and stratify sieve */ 3215 { 3216 PetscInt pStart, pEnd; 3217 3218 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3219 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3220 } 3221 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3222 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3223 /* Distribute Coordinates */ 3224 { 3225 PetscSection originalCoordSection, newCoordSection; 3226 Vec originalCoordinates, newCoordinates; 3227 const char *name; 3228 3229 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3230 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3231 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3232 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3233 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3234 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3235 3236 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3237 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3238 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3239 } 3240 /* Distribute labels */ 3241 { 3242 DMLabel next = mesh->labels, newNext = pmesh->labels; 3243 PetscInt numLabels = 0, l; 3244 3245 /* Bcast number of labels */ 3246 while(next) {++numLabels; next = next->next;} 3247 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3248 next = mesh->labels; 3249 for (l = 0; l < numLabels; ++l) { 3250 DMLabel newLabel; 3251 const PetscInt *partArray; 3252 char *name; 3253 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3254 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3255 PetscInt nameSize, s, p; 3256 PetscBool isdepth; 3257 size_t len = 0; 3258 3259 /* Bcast name (could filter for no points) */ 3260 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3261 nameSize = len; 3262 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3263 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3264 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3265 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3266 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3267 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3268 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3269 newLabel->name = name; 3270 /* Bcast numStrata (could filter for no points in stratum) */ 3271 if (!rank) {newLabel->numStrata = next->numStrata;} 3272 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3273 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3274 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3275 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3276 /* Bcast stratumValues (could filter for no points in stratum) */ 3277 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3278 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3279 /* Find size on each process and Scatter */ 3280 if (!rank) { 3281 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3282 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3283 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3284 for (s = 0; s < next->numStrata; ++s) { 3285 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3286 const PetscInt point = next->points[p]; 3287 PetscInt proc; 3288 3289 for (proc = 0; proc < numProcs; ++proc) { 3290 PetscInt dof, off, pPart; 3291 3292 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3293 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3294 for (pPart = off; pPart < off+dof; ++pPart) { 3295 if (partArray[pPart] == point) { 3296 ++stratumSizes[proc*next->numStrata+s]; 3297 break; 3298 } 3299 } 3300 } 3301 } 3302 } 3303 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3304 } 3305 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3306 /* Calculate stratumOffsets */ 3307 newLabel->stratumOffsets[0] = 0; 3308 for (s = 0; s < newLabel->numStrata; ++s) { 3309 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3310 } 3311 /* Pack points and Scatter */ 3312 if (!rank) { 3313 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3314 displs[0] = 0; 3315 for (p = 0; p < numProcs; ++p) { 3316 sendcnts[p] = 0; 3317 for (s = 0; s < next->numStrata; ++s) { 3318 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3319 } 3320 offsets[p] = displs[p]; 3321 displs[p+1] = displs[p] + sendcnts[p]; 3322 } 3323 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3324 for (s = 0; s < next->numStrata; ++s) { 3325 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3326 const PetscInt point = next->points[p]; 3327 PetscInt proc; 3328 3329 for (proc = 0; proc < numProcs; ++proc) { 3330 PetscInt dof, off, pPart; 3331 3332 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3333 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3334 for (pPart = off; pPart < off+dof; ++pPart) { 3335 if (partArray[pPart] == point) { 3336 points[offsets[proc]++] = point; 3337 break; 3338 } 3339 } 3340 } 3341 } 3342 } 3343 } 3344 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3345 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3346 ierr = PetscFree(points);CHKERRQ(ierr); 3347 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3348 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3349 /* Renumber points */ 3350 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3351 /* Sort points */ 3352 for (s = 0; s < newLabel->numStrata; ++s) { 3353 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3354 } 3355 /* Insert into list */ 3356 if (newNext) { 3357 newNext->next = newLabel; 3358 } else { 3359 pmesh->labels = newLabel; 3360 } 3361 newNext = newLabel; 3362 if (!rank) {next = next->next;} 3363 } 3364 } 3365 /* Cleanup Partition */ 3366 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3367 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3368 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3369 ierr = ISDestroy(&part);CHKERRQ(ierr); 3370 /* Create point SF for parallel mesh */ 3371 { 3372 const PetscInt *leaves; 3373 PetscSFNode *remotePoints, *rowners, *lowners; 3374 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3375 PetscInt pStart, pEnd; 3376 3377 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3378 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3379 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3380 for (p=0; p<numRoots; p++) { 3381 rowners[p].rank = -1; 3382 rowners[p].index = -1; 3383 } 3384 if (origCellPart) { 3385 /* Make sure cells in the original partition are not assigned to other procs */ 3386 const PetscInt *origCells; 3387 3388 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3389 for (p = 0; p < numProcs; ++p) { 3390 PetscInt dof, off, d; 3391 3392 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3393 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3394 for(d = off; d < off+dof; ++d) { 3395 rowners[origCells[d]].rank = p; 3396 } 3397 } 3398 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3399 } 3400 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3401 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3402 3403 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3404 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3405 for (p = 0; p < numLeaves; ++p) { 3406 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3407 lowners[p].rank = rank; 3408 lowners[p].index = leaves ? leaves[p] : p; 3409 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3410 lowners[p].rank = -2; 3411 lowners[p].index = -2; 3412 } 3413 } 3414 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3415 rowners[p].rank = -3; 3416 rowners[p].index = -3; 3417 } 3418 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3419 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3420 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3421 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3422 for (p = 0; p < numLeaves; ++p) { 3423 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3424 if (lowners[p].rank != rank) ++numGhostPoints; 3425 } 3426 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3427 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3428 for (p = 0, gp = 0; p < numLeaves; ++p) { 3429 if (lowners[p].rank != rank) { 3430 ghostPoints[gp] = leaves ? leaves[p] : p; 3431 remotePoints[gp].rank = lowners[p].rank; 3432 remotePoints[gp].index = lowners[p].index; 3433 ++gp; 3434 } 3435 } 3436 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3437 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3438 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3439 } 3440 /* Cleanup */ 3441 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3442 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3443 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3444 PetscFunctionReturn(0); 3445 } 3446 3447 #undef __FUNCT__ 3448 #define __FUNCT__ "DMPlexRenumber_Private" 3449 /* 3450 Reasons to renumber: 3451 3452 1) Permute points, e.g. bandwidth reduction (Renumber) 3453 3454 a) Must not mix strata 3455 3456 2) Shift numbers for point insertion (Shift) 3457 3458 a) Want operation brken into parts so that insertion can be interleaved 3459 3460 renumbering - An IS which provides the new numbering 3461 */ 3462 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3463 { 3464 PetscFunctionBegin; 3465 PetscFunctionReturn(0); 3466 } 3467 3468 #undef __FUNCT__ 3469 #define __FUNCT__ "DMPlexShiftPoint_Private" 3470 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3471 { 3472 if (depth < 0) return p; 3473 /* Cells */ if (p < depthEnd[depth]) return p; 3474 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3475 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3476 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3477 } 3478 3479 #undef __FUNCT__ 3480 #define __FUNCT__ "DMPlexShiftSizes_Private" 3481 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3482 { 3483 PetscInt *depthEnd; 3484 PetscInt depth = 0, d, pStart, pEnd, p; 3485 PetscErrorCode ierr; 3486 3487 PetscFunctionBegin; 3488 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3489 if (depth < 0) PetscFunctionReturn(0); 3490 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3491 /* Step 1: Expand chart */ 3492 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3493 for(d = 0; d <= depth; ++d) { 3494 pEnd += depthShift[d]; 3495 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3496 } 3497 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3498 /* Step 2: Set cone and support sizes */ 3499 for(d = 0; d <= depth; ++d) { 3500 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3501 for(p = pStart; p < pEnd; ++p) { 3502 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3503 PetscInt size; 3504 3505 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3506 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3507 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3508 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3509 } 3510 } 3511 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3512 PetscFunctionReturn(0); 3513 } 3514 3515 #undef __FUNCT__ 3516 #define __FUNCT__ "DMPlexShiftPoints_Private" 3517 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3518 { 3519 PetscInt *depthEnd, *newpoints; 3520 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3521 PetscErrorCode ierr; 3522 3523 PetscFunctionBegin; 3524 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3525 if (depth < 0) PetscFunctionReturn(0); 3526 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3527 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3528 for(d = 0; d <= depth; ++d) { 3529 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3530 } 3531 /* Step 5: Set cones and supports */ 3532 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3533 for(p = pStart; p < pEnd; ++p) { 3534 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3535 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3536 3537 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3538 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3539 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3540 for(i = 0; i < size; ++i) { 3541 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3542 } 3543 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3544 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3545 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3546 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3547 for(i = 0; i < size; ++i) { 3548 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3549 } 3550 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3551 } 3552 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3553 PetscFunctionReturn(0); 3554 } 3555 3556 #undef __FUNCT__ 3557 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3558 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3559 { 3560 PetscSection coordSection, newCoordSection; 3561 Vec coordinates; 3562 PetscInt *depthEnd; 3563 PetscInt dim, depth = 0, d, vStart, vEnd, v; 3564 PetscErrorCode ierr; 3565 3566 PetscFunctionBegin; 3567 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3568 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3569 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3570 for(d = 0; d <= depth; ++d) { 3571 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3572 } 3573 /* Step 8: Convert coordinates */ 3574 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3575 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3576 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3577 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3578 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3579 ierr = PetscSectionSetChart(newCoordSection, DMPlexShiftPoint_Private(vStart, depth, depthEnd, depthShift), DMPlexShiftPoint_Private(vEnd, depth, depthEnd, depthShift));CHKERRQ(ierr); 3580 for(v = vStart; v < vEnd; ++v) { 3581 const PetscInt newv = DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift); 3582 ierr = PetscSectionSetDof(newCoordSection, newv, dim);CHKERRQ(ierr); 3583 ierr = PetscSectionSetFieldDof(newCoordSection, newv, 0, dim);CHKERRQ(ierr); 3584 } 3585 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3586 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3587 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3588 ierr = DMSetCoordinatesLocal(dmNew, coordinates);CHKERRQ(ierr); 3589 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3590 PetscFunctionReturn(0); 3591 } 3592 3593 #undef __FUNCT__ 3594 #define __FUNCT__ "DMPlexShiftSF_Private" 3595 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3596 { 3597 PetscInt *depthEnd; 3598 PetscInt depth = 0, d; 3599 PetscSF sfPoint, sfPointNew; 3600 const PetscSFNode *remotePoints; 3601 PetscSFNode *gremotePoints; 3602 const PetscInt *localPoints; 3603 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3604 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3605 PetscMPIInt numProcs; 3606 PetscErrorCode ierr; 3607 3608 PetscFunctionBegin; 3609 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3610 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3611 for(d = 0; d <= depth; ++d) { 3612 totShift += depthShift[d]; 3613 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3614 } 3615 /* Step 9: Convert pointSF */ 3616 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3617 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3618 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3619 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3620 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3621 if (numRoots >= 0) { 3622 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3623 for(l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3624 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3625 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3626 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3627 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3628 for(l = 0; l < numLeaves; ++l) { 3629 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3630 gremotePoints[l].rank = remotePoints[l].rank; 3631 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3632 } 3633 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3634 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3635 } 3636 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3637 PetscFunctionReturn(0); 3638 } 3639 3640 #undef __FUNCT__ 3641 #define __FUNCT__ "DMPlexShiftLabels_Private" 3642 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3643 { 3644 PetscSF sfPoint; 3645 DMLabel vtkLabel, ghostLabel; 3646 PetscInt *depthEnd; 3647 const PetscSFNode *leafRemote; 3648 const PetscInt *leafLocal; 3649 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3650 PetscMPIInt rank; 3651 PetscErrorCode ierr; 3652 3653 PetscFunctionBegin; 3654 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3655 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3656 for(d = 0; d <= depth; ++d) { 3657 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3658 } 3659 /* Step 10: Convert labels */ 3660 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3661 for(l = 0; l < numLabels; ++l) { 3662 DMLabel label, newlabel; 3663 const char *lname; 3664 PetscBool isDepth; 3665 IS valueIS; 3666 const PetscInt *values; 3667 PetscInt numValues, val; 3668 3669 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3670 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3671 if (isDepth) continue; 3672 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3673 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3674 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3675 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3676 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3677 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3678 for(val = 0; val < numValues; ++val) { 3679 IS pointIS; 3680 const PetscInt *points; 3681 PetscInt numPoints, p; 3682 3683 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3684 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3685 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3686 for(p = 0; p < numPoints; ++p) { 3687 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3688 3689 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3690 } 3691 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3692 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3693 } 3694 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3695 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3696 } 3697 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3698 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3699 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3700 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3701 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3702 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3703 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3704 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3705 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3706 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3707 for(l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3708 for(; c < leafLocal[l] && c < cEnd; ++c) { 3709 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3710 } 3711 if (leafLocal[l] >= cEnd) break; 3712 if (leafRemote[l].rank == rank) { 3713 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3714 } else { 3715 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3716 } 3717 } 3718 for(; c < cEnd; ++c) { 3719 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3720 } 3721 if (0) { 3722 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3723 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3724 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3725 } 3726 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3727 for(f = fStart; f < fEnd; ++f) { 3728 PetscInt numCells; 3729 3730 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3731 if (numCells < 2) { 3732 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3733 } else { 3734 const PetscInt *cells = PETSC_NULL; 3735 PetscInt vA, vB; 3736 3737 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3738 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3739 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3740 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3741 } 3742 } 3743 if (0) { 3744 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3745 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3746 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3747 } 3748 PetscFunctionReturn(0); 3749 } 3750 3751 #undef __FUNCT__ 3752 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3753 /*@C 3754 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3755 3756 Collective on dm 3757 3758 Input Parameters: 3759 + dm - The original DM 3760 - labelName - The label specifying the boundary faces (this could be auto-generated) 3761 3762 Output Parameters: 3763 + numGhostCells - The number of ghost cells added to the DM 3764 - dmGhosted - The new DM 3765 3766 Level: developer 3767 3768 .seealso: DMCreate() 3769 */ 3770 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3771 { 3772 DMLabel label; 3773 IS valueIS; 3774 const PetscInt *values; 3775 PetscInt *depthShift; 3776 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3777 PetscErrorCode ierr; 3778 3779 PetscFunctionBegin; 3780 /* Count ghost cells */ 3781 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3782 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3783 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3784 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3785 *numGhostCells = 0; 3786 for(fs = 0; fs < numFS; ++fs) { 3787 PetscInt numBdFaces; 3788 3789 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3790 *numGhostCells += numBdFaces; 3791 } 3792 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3793 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3794 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3795 if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3796 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3797 /* Step 3: Set cone/support sizes for new points */ 3798 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3799 for(c = cEnd; c < cEnd + *numGhostCells; ++c) { 3800 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3801 } 3802 for(fs = 0; fs < numFS; ++fs) { 3803 IS faceIS; 3804 const PetscInt *faces; 3805 PetscInt numFaces, f; 3806 3807 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3808 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3809 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3810 for(f = 0; f < numFaces; ++f) { 3811 PetscInt size; 3812 3813 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3814 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3815 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3816 } 3817 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3818 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3819 } 3820 /* Step 4: Setup ghosted DM */ 3821 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3822 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3823 /* Step 6: Set cones and supports for new points */ 3824 ghostCell = cEnd; 3825 for(fs = 0; fs < numFS; ++fs) { 3826 IS faceIS; 3827 const PetscInt *faces; 3828 PetscInt numFaces, f; 3829 3830 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3831 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3832 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3833 for(f = 0; f < numFaces; ++f, ++ghostCell) { 3834 PetscInt newFace = faces[f] + *numGhostCells; 3835 3836 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3837 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3838 } 3839 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3840 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3841 } 3842 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3843 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3844 /* Step 7: Stratify */ 3845 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3846 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3847 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3848 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3849 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3850 PetscFunctionReturn(0); 3851 } 3852 3853 #undef __FUNCT__ 3854 #define __FUNCT__ "DMPlexConstructGhostCells" 3855 /*@C 3856 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3857 3858 Collective on dm 3859 3860 Input Parameters: 3861 + dm - The original DM 3862 - labelName - The label specifying the boundary faces (this could be auto-generated) 3863 3864 Output Parameters: 3865 + numGhostCells - The number of ghost cells added to the DM 3866 - dmGhosted - The new DM 3867 3868 Level: developer 3869 3870 .seealso: DMCreate() 3871 */ 3872 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3873 { 3874 DM gdm; 3875 PetscInt dim; 3876 PetscErrorCode ierr; 3877 3878 PetscFunctionBegin; 3879 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3880 PetscValidPointer(numGhostCells, 3); 3881 PetscValidPointer(dmGhosted, 4); 3882 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3883 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3884 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3885 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3886 switch(dim) { 3887 case 2: 3888 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3889 break; 3890 default: 3891 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3892 } 3893 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3894 *dmGhosted = gdm; 3895 PetscFunctionReturn(0); 3896 } 3897 3898 #undef __FUNCT__ 3899 #define __FUNCT__ "DMPlexInterpolate_2D" 3900 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 3901 { 3902 DM idm; 3903 DM_Plex *mesh; 3904 PetscHashIJ edgeTable; 3905 PetscInt *off; 3906 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 3907 PetscInt numEdges, firstEdge, edge, e; 3908 PetscErrorCode ierr; 3909 3910 PetscFunctionBegin; 3911 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3912 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3913 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3914 numCells = cEnd - cStart; 3915 numVertices = vEnd - vStart; 3916 firstEdge = numCells + numVertices; 3917 numEdges = 0 ; 3918 /* Count edges using algorithm from CreateNeighborCSR */ 3919 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 3920 if (off) { 3921 PetscInt numCorners = 0; 3922 3923 numEdges = off[numCells]/2; 3924 #if 0 3925 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 3926 numEdges += 3*numCells - off[numCells]; 3927 #else 3928 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 3929 for(c = cStart; c < cEnd; ++c) { 3930 PetscInt coneSize; 3931 3932 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 3933 numCorners += coneSize; 3934 } 3935 numEdges += numCorners - off[numCells]; 3936 #endif 3937 } 3938 #if 0 3939 /* Check Euler characteristic V - E + F = 1 */ 3940 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 3941 #endif 3942 /* Create interpolated mesh */ 3943 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 3944 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 3945 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 3946 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 3947 for (c = 0; c < numCells; ++c) { 3948 PetscInt numCorners; 3949 3950 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 3951 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 3952 } 3953 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 3954 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 3955 } 3956 ierr = DMSetUp(idm);CHKERRQ(ierr); 3957 /* Get edge cones from subsets of cell vertices */ 3958 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 3959 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 3960 3961 for (c = 0, edge = firstEdge; c < numCells; ++c) { 3962 const PetscInt *cellFaces; 3963 PetscInt numCellFaces, faceSize, cf; 3964 3965 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 3966 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 3967 for (cf = 0; cf < numCellFaces; ++cf) { 3968 #if 1 3969 PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]), 3970 PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])}; 3971 3972 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 3973 if (e < 0) { 3974 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3975 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 3976 e = edge++; 3977 } 3978 #else 3979 PetscBool found = PETSC_FALSE; 3980 3981 /* 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 for (e = firstEdge; e < edge; ++e) { 3983 const PetscInt *cone; 3984 3985 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 3986 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 3987 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 3988 found = PETSC_TRUE; 3989 break; 3990 } 3991 } 3992 if (!found) { 3993 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3994 ++edge; 3995 } 3996 #endif 3997 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 3998 } 3999 } 4000 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4001 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4002 ierr = PetscFree(off);CHKERRQ(ierr); 4003 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4004 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4005 mesh = (DM_Plex *) (idm)->data; 4006 /* Orient edges */ 4007 for (c = 0; c < numCells; ++c) { 4008 const PetscInt *cone = PETSC_NULL, *cellFaces; 4009 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4010 4011 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4012 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4013 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4014 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4015 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 for (cf = 0; cf < numCellFaces; ++cf) { 4017 const PetscInt *econe = PETSC_NULL; 4018 PetscInt esize; 4019 4020 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4021 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4022 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 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4024 /* Correctly oriented */ 4025 mesh->coneOrientations[coff+cf] = 0; 4026 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4027 /* Start at index 1, and reverse orientation */ 4028 mesh->coneOrientations[coff+cf] = -(1+1); 4029 } 4030 } 4031 } 4032 *dmInt = idm; 4033 PetscFunctionReturn(0); 4034 } 4035 4036 #undef __FUNCT__ 4037 #define __FUNCT__ "DMPlexInterpolate_3D" 4038 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4039 { 4040 DM idm, fdm; 4041 DM_Plex *mesh; 4042 PetscInt *off; 4043 const PetscInt numCorners = 4; 4044 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4045 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4046 PetscErrorCode ierr; 4047 4048 PetscFunctionBegin; 4049 { 4050 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4051 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4052 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4053 } 4054 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4055 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4056 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4057 numCells = cEnd - cStart; 4058 numVertices = vEnd - vStart; 4059 firstFace = numCells + numVertices; 4060 numFaces = 0 ; 4061 /* Count faces using algorithm from CreateNeighborCSR */ 4062 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4063 if (off) { 4064 numFaces = off[numCells]/2; 4065 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4066 numFaces += 4*numCells - off[numCells]; 4067 } 4068 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4069 firstEdge = firstFace + numFaces; 4070 numEdges = numVertices + numFaces - numCells - 1; 4071 /* Create interpolated mesh */ 4072 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4073 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4074 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4075 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4076 for (c = 0; c < numCells; ++c) { 4077 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4078 } 4079 for (f = firstFace; f < firstFace+numFaces; ++f) { 4080 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4081 } 4082 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4083 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4084 } 4085 ierr = DMSetUp(idm);CHKERRQ(ierr); 4086 /* Get face cones from subsets of cell vertices */ 4087 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4088 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4089 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4090 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4091 for (f = firstFace; f < firstFace+numFaces; ++f) { 4092 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4093 } 4094 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4095 for (c = 0, face = firstFace; c < numCells; ++c) { 4096 const PetscInt *cellFaces; 4097 PetscInt numCellFaces, faceSize, cf; 4098 4099 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4100 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4101 for (cf = 0; cf < numCellFaces; ++cf) { 4102 PetscBool found = PETSC_FALSE; 4103 4104 /* 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 for (f = firstFace; f < face; ++f) { 4106 const PetscInt *cone = PETSC_NULL; 4107 4108 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4109 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4110 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4111 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4112 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4113 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4114 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4115 found = PETSC_TRUE; 4116 break; 4117 } 4118 } 4119 if (!found) { 4120 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4121 /* Save the vertices for orientation calculation */ 4122 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4123 ++face; 4124 } 4125 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4126 } 4127 } 4128 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4129 /* Get edge cones from subsets of face vertices */ 4130 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4131 const PetscInt *cellFaces; 4132 PetscInt numCellFaces, faceSize, cf; 4133 4134 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4135 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4136 for (cf = 0; cf < numCellFaces; ++cf) { 4137 PetscBool found = PETSC_FALSE; 4138 4139 /* 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 for (e = firstEdge; e < edge; ++e) { 4141 const PetscInt *cone = PETSC_NULL; 4142 4143 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4144 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4145 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4146 found = PETSC_TRUE; 4147 break; 4148 } 4149 } 4150 if (!found) { 4151 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4152 ++edge; 4153 } 4154 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4155 } 4156 } 4157 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4158 ierr = PetscFree(off);CHKERRQ(ierr); 4159 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4160 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4161 mesh = (DM_Plex *) (idm)->data; 4162 /* Orient edges */ 4163 for (f = firstFace; f < firstFace+numFaces; ++f) { 4164 const PetscInt *cone, *cellFaces; 4165 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4166 4167 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4168 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4169 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4170 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4171 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 for (cf = 0; cf < numCellFaces; ++cf) { 4173 const PetscInt *econe; 4174 PetscInt esize; 4175 4176 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4177 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4178 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 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4180 /* Correctly oriented */ 4181 mesh->coneOrientations[coff+cf] = 0; 4182 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4183 /* Start at index 1, and reverse orientation */ 4184 mesh->coneOrientations[coff+cf] = -(1+1); 4185 } 4186 } 4187 } 4188 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4189 /* Orient faces */ 4190 for (c = 0; c < numCells; ++c) { 4191 const PetscInt *cone, *cellFaces; 4192 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4193 4194 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4195 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4196 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4197 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4198 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 for (cf = 0; cf < numCellFaces; ++cf) { 4200 PetscInt *origClosure = PETSC_NULL, *closure; 4201 PetscInt closureSize, i; 4202 4203 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4204 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4205 for (i = 4; i < 7; ++i) { 4206 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 } 4208 closure = &origClosure[4*2]; 4209 /* Remember that this is the orientation for edges, not vertices */ 4210 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4211 /* Correctly oriented */ 4212 mesh->coneOrientations[coff+cf] = 0; 4213 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4214 /* Shifted by 1 */ 4215 mesh->coneOrientations[coff+cf] = 1; 4216 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4217 /* Shifted by 2 */ 4218 mesh->coneOrientations[coff+cf] = 2; 4219 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4220 /* Start at edge 1, and reverse orientation */ 4221 mesh->coneOrientations[coff+cf] = -(1+1); 4222 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4223 /* Start at index 0, and reverse orientation */ 4224 mesh->coneOrientations[coff+cf] = -(0+1); 4225 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4226 /* Start at index 2, and reverse orientation */ 4227 mesh->coneOrientations[coff+cf] = -(2+1); 4228 } 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 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4230 } 4231 } 4232 { 4233 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4234 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4235 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4236 } 4237 *dmInt = idm; 4238 PetscFunctionReturn(0); 4239 } 4240 4241 #undef __FUNCT__ 4242 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4243 /* 4244 This takes as input the common mesh generator output, a list of the vertices for each cell 4245 */ 4246 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4247 { 4248 PetscInt *cone, c, p; 4249 PetscErrorCode ierr; 4250 4251 PetscFunctionBegin; 4252 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4253 for (c = 0; c < numCells; ++c) { 4254 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4255 } 4256 ierr = DMSetUp(dm);CHKERRQ(ierr); 4257 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4258 for (c = 0; c < numCells; ++c) { 4259 for (p = 0; p < numCorners; ++p) { 4260 cone[p] = cells[c*numCorners+p]+numCells; 4261 } 4262 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4263 } 4264 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4265 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4266 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4267 PetscFunctionReturn(0); 4268 } 4269 4270 #undef __FUNCT__ 4271 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4272 /* 4273 This takes as input the coordinates for each vertex 4274 */ 4275 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4276 { 4277 PetscSection coordSection; 4278 Vec coordinates; 4279 PetscScalar *coords; 4280 PetscInt coordSize, v, d; 4281 PetscErrorCode ierr; 4282 4283 PetscFunctionBegin; 4284 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4285 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4286 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4287 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4288 for (v = numCells; v < numCells+numVertices; ++v) { 4289 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4290 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4291 } 4292 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4293 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4294 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4295 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4296 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4297 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4298 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4299 for (v = 0; v < numVertices; ++v) { 4300 for (d = 0; d < spaceDim; ++d) { 4301 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4302 } 4303 } 4304 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4305 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4306 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4307 PetscFunctionReturn(0); 4308 } 4309 4310 #undef __FUNCT__ 4311 #define __FUNCT__ "DMPlexCreateFromCellList" 4312 /* 4313 This takes as input the common mesh generator output, a list of the vertices for each cell 4314 */ 4315 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4316 { 4317 PetscErrorCode ierr; 4318 4319 PetscFunctionBegin; 4320 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4321 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4322 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4323 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4324 if (interpolate) { 4325 DM idm; 4326 4327 switch(dim) { 4328 case 2: 4329 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4330 case 3: 4331 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4332 default: 4333 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4334 } 4335 ierr = DMDestroy(dm);CHKERRQ(ierr); 4336 *dm = idm; 4337 } 4338 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4339 PetscFunctionReturn(0); 4340 } 4341 4342 #ifdef PETSC_HAVE_TRIANGLE 4343 #include <triangle.h> 4344 4345 #undef __FUNCT__ 4346 #define __FUNCT__ "InitInput_Triangle" 4347 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) { 4348 PetscFunctionBegin; 4349 inputCtx->numberofpoints = 0; 4350 inputCtx->numberofpointattributes = 0; 4351 inputCtx->pointlist = PETSC_NULL; 4352 inputCtx->pointattributelist = PETSC_NULL; 4353 inputCtx->pointmarkerlist = PETSC_NULL; 4354 inputCtx->numberofsegments = 0; 4355 inputCtx->segmentlist = PETSC_NULL; 4356 inputCtx->segmentmarkerlist = PETSC_NULL; 4357 inputCtx->numberoftriangleattributes = 0; 4358 inputCtx->trianglelist = PETSC_NULL; 4359 inputCtx->numberofholes = 0; 4360 inputCtx->holelist = PETSC_NULL; 4361 inputCtx->numberofregions = 0; 4362 inputCtx->regionlist = PETSC_NULL; 4363 PetscFunctionReturn(0); 4364 } 4365 4366 #undef __FUNCT__ 4367 #define __FUNCT__ "InitOutput_Triangle" 4368 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) { 4369 PetscFunctionBegin; 4370 outputCtx->numberofpoints = 0; 4371 outputCtx->pointlist = PETSC_NULL; 4372 outputCtx->pointattributelist = PETSC_NULL; 4373 outputCtx->pointmarkerlist = PETSC_NULL; 4374 outputCtx->numberoftriangles = 0; 4375 outputCtx->trianglelist = PETSC_NULL; 4376 outputCtx->triangleattributelist = PETSC_NULL; 4377 outputCtx->neighborlist = PETSC_NULL; 4378 outputCtx->segmentlist = PETSC_NULL; 4379 outputCtx->segmentmarkerlist = PETSC_NULL; 4380 outputCtx->numberofedges = 0; 4381 outputCtx->edgelist = PETSC_NULL; 4382 outputCtx->edgemarkerlist = PETSC_NULL; 4383 PetscFunctionReturn(0); 4384 } 4385 4386 #undef __FUNCT__ 4387 #define __FUNCT__ "FiniOutput_Triangle" 4388 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) { 4389 PetscFunctionBegin; 4390 free(outputCtx->pointmarkerlist); 4391 free(outputCtx->edgelist); 4392 free(outputCtx->edgemarkerlist); 4393 free(outputCtx->trianglelist); 4394 free(outputCtx->neighborlist); 4395 PetscFunctionReturn(0); 4396 } 4397 4398 #undef __FUNCT__ 4399 #define __FUNCT__ "DMPlexGenerate_Triangle" 4400 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4401 { 4402 MPI_Comm comm = ((PetscObject) boundary)->comm; 4403 PetscInt dim = 2; 4404 const PetscBool createConvexHull = PETSC_FALSE; 4405 const PetscBool constrained = PETSC_FALSE; 4406 struct triangulateio in; 4407 struct triangulateio out; 4408 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4409 PetscMPIInt rank; 4410 PetscErrorCode ierr; 4411 4412 PetscFunctionBegin; 4413 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4414 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4415 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4416 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4417 in.numberofpoints = vEnd - vStart; 4418 if (in.numberofpoints > 0) { 4419 PetscSection coordSection; 4420 Vec coordinates; 4421 PetscScalar *array; 4422 4423 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4424 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4425 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4426 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4427 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4428 for (v = vStart; v < vEnd; ++v) { 4429 const PetscInt idx = v - vStart; 4430 PetscInt off, d; 4431 4432 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4433 for (d = 0; d < dim; ++d) { 4434 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4435 } 4436 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4437 } 4438 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4439 } 4440 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4441 in.numberofsegments = eEnd - eStart; 4442 if (in.numberofsegments > 0) { 4443 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4444 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4445 for (e = eStart; e < eEnd; ++e) { 4446 const PetscInt idx = e - eStart; 4447 const PetscInt *cone; 4448 4449 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4450 in.segmentlist[idx*2+0] = cone[0] - vStart; 4451 in.segmentlist[idx*2+1] = cone[1] - vStart; 4452 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4453 } 4454 } 4455 #if 0 /* Do not currently support holes */ 4456 PetscReal *holeCoords; 4457 PetscInt h, d; 4458 4459 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4460 if (in.numberofholes > 0) { 4461 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4462 for (h = 0; h < in.numberofholes; ++h) { 4463 for (d = 0; d < dim; ++d) { 4464 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4465 } 4466 } 4467 } 4468 #endif 4469 if (!rank) { 4470 char args[32]; 4471 4472 /* Take away 'Q' for verbose output */ 4473 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4474 if (createConvexHull) { 4475 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4476 } 4477 if (constrained) { 4478 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4479 } 4480 triangulate(args, &in, &out, PETSC_NULL); 4481 } 4482 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4483 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4484 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4485 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4486 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4487 4488 { 4489 const PetscInt numCorners = 3; 4490 const PetscInt numCells = out.numberoftriangles; 4491 const PetscInt numVertices = out.numberofpoints; 4492 const int *cells = out.trianglelist; 4493 const double *meshCoords = out.pointlist; 4494 4495 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4496 /* Set labels */ 4497 for (v = 0; v < numVertices; ++v) { 4498 if (out.pointmarkerlist[v]) { 4499 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4500 } 4501 } 4502 if (interpolate) { 4503 for (e = 0; e < out.numberofedges; e++) { 4504 if (out.edgemarkerlist[e]) { 4505 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4506 const PetscInt *edges; 4507 PetscInt numEdges; 4508 4509 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4510 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4511 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4512 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4513 } 4514 } 4515 } 4516 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4517 } 4518 #if 0 /* Do not currently support holes */ 4519 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4520 #endif 4521 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4522 PetscFunctionReturn(0); 4523 } 4524 4525 #undef __FUNCT__ 4526 #define __FUNCT__ "DMPlexRefine_Triangle" 4527 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4528 { 4529 MPI_Comm comm = ((PetscObject) dm)->comm; 4530 PetscInt dim = 2; 4531 struct triangulateio in; 4532 struct triangulateio out; 4533 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4534 PetscMPIInt rank; 4535 PetscErrorCode ierr; 4536 4537 PetscFunctionBegin; 4538 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4539 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4540 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4541 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4542 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4543 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4544 in.numberofpoints = vEnd - vStart; 4545 if (in.numberofpoints > 0) { 4546 PetscSection coordSection; 4547 Vec coordinates; 4548 PetscScalar *array; 4549 4550 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4551 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4552 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4553 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4554 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4555 for (v = vStart; v < vEnd; ++v) { 4556 const PetscInt idx = v - vStart; 4557 PetscInt off, d; 4558 4559 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4560 for (d = 0; d < dim; ++d) { 4561 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4562 } 4563 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4564 } 4565 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4566 } 4567 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4568 in.numberofcorners = 3; 4569 in.numberoftriangles = cEnd - cStart; 4570 in.trianglearealist = (double *) maxVolumes; 4571 if (in.numberoftriangles > 0) { 4572 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4573 for (c = cStart; c < cEnd; ++c) { 4574 const PetscInt idx = c - cStart; 4575 PetscInt *closure = PETSC_NULL; 4576 PetscInt closureSize; 4577 4578 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4579 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 for (v = 0; v < 3; ++v) { 4581 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4582 } 4583 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4584 } 4585 } 4586 /* TODO: Segment markers are missing on input */ 4587 #if 0 /* Do not currently support holes */ 4588 PetscReal *holeCoords; 4589 PetscInt h, d; 4590 4591 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4592 if (in.numberofholes > 0) { 4593 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4594 for (h = 0; h < in.numberofholes; ++h) { 4595 for (d = 0; d < dim; ++d) { 4596 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4597 } 4598 } 4599 } 4600 #endif 4601 if (!rank) { 4602 char args[32]; 4603 4604 /* Take away 'Q' for verbose output */ 4605 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4606 triangulate(args, &in, &out, PETSC_NULL); 4607 } 4608 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4609 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4610 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4611 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4612 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4613 4614 { 4615 const PetscInt numCorners = 3; 4616 const PetscInt numCells = out.numberoftriangles; 4617 const PetscInt numVertices = out.numberofpoints; 4618 const int *cells = out.trianglelist; 4619 const double *meshCoords = out.pointlist; 4620 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4621 4622 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4623 /* Set labels */ 4624 for (v = 0; v < numVertices; ++v) { 4625 if (out.pointmarkerlist[v]) { 4626 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4627 } 4628 } 4629 if (interpolate) { 4630 PetscInt e; 4631 4632 for (e = 0; e < out.numberofedges; e++) { 4633 if (out.edgemarkerlist[e]) { 4634 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4635 const PetscInt *edges; 4636 PetscInt numEdges; 4637 4638 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4639 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4640 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4641 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4642 } 4643 } 4644 } 4645 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4646 } 4647 #if 0 /* Do not currently support holes */ 4648 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4649 #endif 4650 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4651 PetscFunctionReturn(0); 4652 } 4653 #endif 4654 4655 #ifdef PETSC_HAVE_TETGEN 4656 #include <tetgen.h> 4657 #undef __FUNCT__ 4658 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4659 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4660 { 4661 MPI_Comm comm = ((PetscObject) boundary)->comm; 4662 const PetscInt dim = 3; 4663 ::tetgenio in; 4664 ::tetgenio out; 4665 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4666 PetscMPIInt rank; 4667 PetscErrorCode ierr; 4668 4669 PetscFunctionBegin; 4670 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4671 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4672 in.numberofpoints = vEnd - vStart; 4673 if (in.numberofpoints > 0) { 4674 PetscSection coordSection; 4675 Vec coordinates; 4676 PetscScalar *array; 4677 4678 in.pointlist = new double[in.numberofpoints*dim]; 4679 in.pointmarkerlist = new int[in.numberofpoints]; 4680 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4681 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4682 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4683 for (v = vStart; v < vEnd; ++v) { 4684 const PetscInt idx = v - vStart; 4685 PetscInt off, d; 4686 4687 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4688 for (d = 0; d < dim; ++d) { 4689 in.pointlist[idx*dim + d] = array[off+d]; 4690 } 4691 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4692 } 4693 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4694 } 4695 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4696 in.numberoffacets = fEnd - fStart; 4697 if (in.numberoffacets > 0) { 4698 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4699 in.facetmarkerlist = new int[in.numberoffacets]; 4700 for (f = fStart; f < fEnd; ++f) { 4701 const PetscInt idx = f - fStart; 4702 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 4703 4704 in.facetlist[idx].numberofpolygons = 1; 4705 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4706 in.facetlist[idx].numberofholes = 0; 4707 in.facetlist[idx].holelist = NULL; 4708 4709 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4710 for (p = 0; p < numPoints*2; p += 2) { 4711 const PetscInt point = points[p]; 4712 if ((point >= vStart) && (point < vEnd)) { 4713 points[numVertices++] = point; 4714 } 4715 } 4716 4717 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4718 poly->numberofvertices = numVertices; 4719 poly->vertexlist = new int[poly->numberofvertices]; 4720 for (v = 0; v < numVertices; ++v) { 4721 const PetscInt vIdx = points[v] - vStart; 4722 poly->vertexlist[v] = vIdx; 4723 } 4724 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4725 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4726 } 4727 } 4728 if (!rank) { 4729 char args[32]; 4730 4731 /* Take away 'Q' for verbose output */ 4732 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4733 ::tetrahedralize(args, &in, &out); 4734 } 4735 { 4736 const PetscInt numCorners = 4; 4737 const PetscInt numCells = out.numberoftetrahedra; 4738 const PetscInt numVertices = out.numberofpoints; 4739 const int *cells = out.tetrahedronlist; 4740 const double *meshCoords = out.pointlist; 4741 4742 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4743 /* Set labels */ 4744 for (v = 0; v < numVertices; ++v) { 4745 if (out.pointmarkerlist[v]) { 4746 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4747 } 4748 } 4749 if (interpolate) { 4750 PetscInt e; 4751 4752 for (e = 0; e < out.numberofedges; e++) { 4753 if (out.edgemarkerlist[e]) { 4754 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4755 const PetscInt *edges; 4756 PetscInt numEdges; 4757 4758 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4759 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4760 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4761 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4762 } 4763 } 4764 for (f = 0; f < out.numberoftrifaces; f++) { 4765 if (out.trifacemarkerlist[f]) { 4766 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4767 const PetscInt *faces; 4768 PetscInt numFaces; 4769 4770 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4771 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4772 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4773 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4774 } 4775 } 4776 } 4777 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4778 } 4779 PetscFunctionReturn(0); 4780 } 4781 4782 #undef __FUNCT__ 4783 #define __FUNCT__ "DMPlexRefine_Tetgen" 4784 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4785 { 4786 MPI_Comm comm = ((PetscObject) dm)->comm; 4787 const PetscInt dim = 3; 4788 ::tetgenio in; 4789 ::tetgenio out; 4790 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4791 PetscMPIInt rank; 4792 PetscErrorCode ierr; 4793 4794 PetscFunctionBegin; 4795 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4796 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4797 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4798 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4799 in.numberofpoints = vEnd - vStart; 4800 if (in.numberofpoints > 0) { 4801 PetscSection coordSection; 4802 Vec coordinates; 4803 PetscScalar *array; 4804 4805 in.pointlist = new double[in.numberofpoints*dim]; 4806 in.pointmarkerlist = new int[in.numberofpoints]; 4807 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4808 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4809 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4810 for (v = vStart; v < vEnd; ++v) { 4811 const PetscInt idx = v - vStart; 4812 PetscInt off, d; 4813 4814 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4815 for (d = 0; d < dim; ++d) { 4816 in.pointlist[idx*dim + d] = array[off+d]; 4817 } 4818 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4819 } 4820 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4821 } 4822 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4823 in.numberofcorners = 4; 4824 in.numberoftetrahedra = cEnd - cStart; 4825 in.tetrahedronvolumelist = (double *) maxVolumes; 4826 if (in.numberoftetrahedra > 0) { 4827 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4828 for (c = cStart; c < cEnd; ++c) { 4829 const PetscInt idx = c - cStart; 4830 PetscInt *closure = PETSC_NULL; 4831 PetscInt closureSize; 4832 4833 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4834 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 for (v = 0; v < 4; ++v) { 4836 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4837 } 4838 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4839 } 4840 } 4841 // TODO: Put in boundary faces with markers 4842 if (!rank) { 4843 char args[32]; 4844 4845 /* Take away 'Q' for verbose output */ 4846 //ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); 4847 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4848 ::tetrahedralize(args, &in, &out); 4849 } 4850 in.tetrahedronvolumelist = NULL; 4851 4852 { 4853 const PetscInt numCorners = 4; 4854 const PetscInt numCells = out.numberoftetrahedra; 4855 const PetscInt numVertices = out.numberofpoints; 4856 const int *cells = out.tetrahedronlist; 4857 const double *meshCoords = out.pointlist; 4858 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4859 4860 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4861 /* Set labels */ 4862 for (v = 0; v < numVertices; ++v) { 4863 if (out.pointmarkerlist[v]) { 4864 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4865 } 4866 } 4867 if (interpolate) { 4868 PetscInt e, f; 4869 4870 for (e = 0; e < out.numberofedges; e++) { 4871 if (out.edgemarkerlist[e]) { 4872 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4873 const PetscInt *edges; 4874 PetscInt numEdges; 4875 4876 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4877 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4878 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4879 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4880 } 4881 } 4882 for (f = 0; f < out.numberoftrifaces; f++) { 4883 if (out.trifacemarkerlist[f]) { 4884 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4885 const PetscInt *faces; 4886 PetscInt numFaces; 4887 4888 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4889 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4890 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4891 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4892 } 4893 } 4894 } 4895 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4896 } 4897 PetscFunctionReturn(0); 4898 } 4899 #endif 4900 4901 #ifdef PETSC_HAVE_CTETGEN 4902 #include "ctetgen.h" 4903 4904 #undef __FUNCT__ 4905 #define __FUNCT__ "DMPlexGenerate_CTetgen" 4906 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 4907 { 4908 MPI_Comm comm = ((PetscObject) boundary)->comm; 4909 const PetscInt dim = 3; 4910 PLC *in, *out; 4911 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 4912 PetscMPIInt rank; 4913 PetscErrorCode ierr; 4914 4915 PetscFunctionBegin; 4916 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 4917 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4918 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4919 ierr = PLCCreate(&in);CHKERRQ(ierr); 4920 ierr = PLCCreate(&out);CHKERRQ(ierr); 4921 in->numberofpoints = vEnd - vStart; 4922 if (in->numberofpoints > 0) { 4923 PetscSection coordSection; 4924 Vec coordinates; 4925 PetscScalar *array; 4926 4927 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 4928 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 4929 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4930 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4931 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4932 for (v = vStart; v < vEnd; ++v) { 4933 const PetscInt idx = v - vStart; 4934 PetscInt off, d, m; 4935 4936 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4937 for (d = 0; d < dim; ++d) { 4938 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4939 } 4940 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 4941 in->pointmarkerlist[idx] = (int) m; 4942 } 4943 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4944 } 4945 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4946 in->numberoffacets = fEnd - fStart; 4947 if (in->numberoffacets > 0) { 4948 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 4949 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 4950 for (f = fStart; f < fEnd; ++f) { 4951 const PetscInt idx = f - fStart; 4952 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 4953 polygon *poly; 4954 4955 in->facetlist[idx].numberofpolygons = 1; 4956 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 4957 in->facetlist[idx].numberofholes = 0; 4958 in->facetlist[idx].holelist = PETSC_NULL; 4959 4960 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4961 for (p = 0; p < numPoints*2; p += 2) { 4962 const PetscInt point = points[p]; 4963 if ((point >= vStart) && (point < vEnd)) { 4964 points[numVertices++] = point; 4965 } 4966 } 4967 4968 poly = in->facetlist[idx].polygonlist; 4969 poly->numberofvertices = numVertices; 4970 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 4971 for (v = 0; v < numVertices; ++v) { 4972 const PetscInt vIdx = points[v] - vStart; 4973 poly->vertexlist[v] = vIdx; 4974 } 4975 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 4976 in->facetmarkerlist[idx] = (int) m; 4977 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4978 } 4979 } 4980 if (!rank) { 4981 TetGenOpts t; 4982 4983 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 4984 t.in = boundary; /* Should go away */ 4985 t.plc = 1; 4986 t.quality = 1; 4987 t.edgesout = 1; 4988 t.zeroindex = 1; 4989 t.quiet = 1; 4990 t.verbose = verbose; 4991 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 4992 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 4993 } 4994 { 4995 const PetscInt numCorners = 4; 4996 const PetscInt numCells = out->numberoftetrahedra; 4997 const PetscInt numVertices = out->numberofpoints; 4998 const int *cells = out->tetrahedronlist; 4999 const double *meshCoords = out->pointlist; 5000 5001 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5002 /* Set labels */ 5003 for (v = 0; v < numVertices; ++v) { 5004 if (out->pointmarkerlist[v]) { 5005 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5006 } 5007 } 5008 if (interpolate) { 5009 PetscInt e; 5010 5011 for (e = 0; e < out->numberofedges; e++) { 5012 if (out->edgemarkerlist[e]) { 5013 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5014 const PetscInt *edges; 5015 PetscInt numEdges; 5016 5017 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5018 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5019 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5020 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5021 } 5022 } 5023 for (f = 0; f < out->numberoftrifaces; f++) { 5024 if (out->trifacemarkerlist[f]) { 5025 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5026 const PetscInt *faces; 5027 PetscInt numFaces; 5028 5029 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5030 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5031 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5032 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5033 } 5034 } 5035 } 5036 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5037 } 5038 5039 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5040 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5041 PetscFunctionReturn(0); 5042 } 5043 5044 #undef __FUNCT__ 5045 #define __FUNCT__ "DMPlexRefine_CTetgen" 5046 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5047 { 5048 MPI_Comm comm = ((PetscObject) dm)->comm; 5049 const PetscInt dim = 3; 5050 PLC *in, *out; 5051 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5052 PetscMPIInt rank; 5053 PetscErrorCode ierr; 5054 5055 PetscFunctionBegin; 5056 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5057 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5058 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5059 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5060 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5061 ierr = PLCCreate(&in);CHKERRQ(ierr); 5062 ierr = PLCCreate(&out);CHKERRQ(ierr); 5063 in->numberofpoints = vEnd - vStart; 5064 if (in->numberofpoints > 0) { 5065 PetscSection coordSection; 5066 Vec coordinates; 5067 PetscScalar *array; 5068 5069 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5070 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5071 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5072 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5073 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5074 for (v = vStart; v < vEnd; ++v) { 5075 const PetscInt idx = v - vStart; 5076 PetscInt off, d, m; 5077 5078 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5079 for (d = 0; d < dim; ++d) { 5080 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5081 } 5082 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5083 in->pointmarkerlist[idx] = (int) m; 5084 } 5085 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5086 } 5087 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5088 in->numberofcorners = 4; 5089 in->numberoftetrahedra = cEnd - cStart; 5090 in->tetrahedronvolumelist = maxVolumes; 5091 if (in->numberoftetrahedra > 0) { 5092 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5093 for (c = cStart; c < cEnd; ++c) { 5094 const PetscInt idx = c - cStart; 5095 PetscInt *closure = PETSC_NULL; 5096 PetscInt closureSize; 5097 5098 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5099 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 for (v = 0; v < 4; ++v) { 5101 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5102 } 5103 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5104 } 5105 } 5106 if (!rank) { 5107 TetGenOpts t; 5108 5109 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5110 t.in = dm; /* Should go away */ 5111 t.refine = 1; 5112 t.varvolume = 1; 5113 t.quality = 1; 5114 t.edgesout = 1; 5115 t.zeroindex = 1; 5116 t.quiet = 1; 5117 t.verbose = verbose; /* Change this */ 5118 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5119 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5120 } 5121 { 5122 const PetscInt numCorners = 4; 5123 const PetscInt numCells = out->numberoftetrahedra; 5124 const PetscInt numVertices = out->numberofpoints; 5125 const int *cells = out->tetrahedronlist; 5126 const double *meshCoords = out->pointlist; 5127 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5128 5129 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5130 /* Set labels */ 5131 for (v = 0; v < numVertices; ++v) { 5132 if (out->pointmarkerlist[v]) { 5133 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5134 } 5135 } 5136 if (interpolate) { 5137 PetscInt e, f; 5138 5139 for (e = 0; e < out->numberofedges; e++) { 5140 if (out->edgemarkerlist[e]) { 5141 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5142 const PetscInt *edges; 5143 PetscInt numEdges; 5144 5145 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5146 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5147 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5148 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5149 } 5150 } 5151 for (f = 0; f < out->numberoftrifaces; f++) { 5152 if (out->trifacemarkerlist[f]) { 5153 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5154 const PetscInt *faces; 5155 PetscInt numFaces; 5156 5157 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5158 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5159 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5160 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5161 } 5162 } 5163 } 5164 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5165 } 5166 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5167 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5168 PetscFunctionReturn(0); 5169 } 5170 #endif 5171 5172 #undef __FUNCT__ 5173 #define __FUNCT__ "DMPlexGenerate" 5174 /*@C 5175 DMPlexGenerate - Generates a mesh. 5176 5177 Not Collective 5178 5179 Input Parameters: 5180 + boundary - The DMPlex boundary object 5181 . name - The mesh generation package name 5182 - interpolate - Flag to create intermediate mesh elements 5183 5184 Output Parameter: 5185 . mesh - The DMPlex object 5186 5187 Level: intermediate 5188 5189 .keywords: mesh, elements 5190 .seealso: DMPlexCreate(), DMRefine() 5191 @*/ 5192 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5193 { 5194 PetscInt dim; 5195 char genname[1024]; 5196 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5197 PetscErrorCode ierr; 5198 5199 PetscFunctionBegin; 5200 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5201 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5202 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5203 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5204 if (flg) {name = genname;} 5205 if (name) { 5206 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5207 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5208 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5209 } 5210 switch(dim) { 5211 case 1: 5212 if (!name || isTriangle) { 5213 #ifdef PETSC_HAVE_TRIANGLE 5214 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5215 #else 5216 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5217 #endif 5218 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5219 break; 5220 case 2: 5221 if (!name || isCTetgen) { 5222 #ifdef PETSC_HAVE_CTETGEN 5223 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5224 #else 5225 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5226 #endif 5227 } else if (isTetgen) { 5228 #ifdef PETSC_HAVE_TETGEN 5229 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5230 #else 5231 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5232 #endif 5233 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5234 break; 5235 default: 5236 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5237 } 5238 PetscFunctionReturn(0); 5239 } 5240 5241 typedef PetscInt CellRefiner; 5242 5243 #undef __FUNCT__ 5244 #define __FUNCT__ "GetDepthStart_Private" 5245 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5246 { 5247 PetscFunctionBegin; 5248 if (cStart) *cStart = 0; 5249 if (vStart) *vStart = depthSize[depth]; 5250 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5251 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5252 PetscFunctionReturn(0); 5253 } 5254 5255 #undef __FUNCT__ 5256 #define __FUNCT__ "GetDepthEnd_Private" 5257 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5258 { 5259 PetscFunctionBegin; 5260 if (cEnd) *cEnd = depthSize[depth]; 5261 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5262 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5263 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5264 PetscFunctionReturn(0); 5265 } 5266 5267 #undef __FUNCT__ 5268 #define __FUNCT__ "CellRefinerGetSizes" 5269 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5270 { 5271 PetscInt cStart, cEnd, vStart, vEnd, fStart, fEnd, eStart, eEnd; 5272 PetscErrorCode ierr; 5273 5274 PetscFunctionBegin; 5275 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5276 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5277 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5278 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5279 switch(refiner) { 5280 case 1: 5281 /* Simplicial 2D */ 5282 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5283 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5284 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5285 break; 5286 case 2: 5287 /* Hex 2D */ 5288 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5289 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5290 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5291 break; 5292 default: 5293 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5294 } 5295 PetscFunctionReturn(0); 5296 } 5297 5298 #undef __FUNCT__ 5299 #define __FUNCT__ "CellRefinerSetConeSizes" 5300 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5301 { 5302 PetscInt depth, cStart, cStartNew, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fStartNew, fEnd, f, eStart, eStartNew, eEnd, r; 5303 PetscErrorCode ierr; 5304 5305 PetscFunctionBegin; 5306 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5307 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5308 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5309 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5310 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5311 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5312 switch(refiner) { 5313 case 1: 5314 /* Simplicial 2D */ 5315 /* All cells have 3 faces */ 5316 for(c = cStart; c < cEnd; ++c) { 5317 for(r = 0; r < 4; ++r) { 5318 const PetscInt newp = (c - cStart)*4 + r; 5319 5320 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5321 } 5322 } 5323 /* Split faces have 2 vertices and the same cells as the parent */ 5324 for(f = fStart; f < fEnd; ++f) { 5325 for(r = 0; r < 2; ++r) { 5326 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5327 PetscInt size; 5328 5329 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5330 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5331 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5332 } 5333 } 5334 /* Interior faces have 2 vertices and 2 cells */ 5335 for(c = cStart; c < cEnd; ++c) { 5336 for(r = 0; r < 3; ++r) { 5337 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5338 5339 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5340 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5341 } 5342 } 5343 /* Old vertices have identical supports */ 5344 for(v = vStart; v < vEnd; ++v) { 5345 const PetscInt newp = vStartNew + (v - vStart); 5346 PetscInt size; 5347 5348 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5349 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5350 } 5351 /* Face vertices have 2 + cells*2 supports */ 5352 for(f = fStart; f < fEnd; ++f) { 5353 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5354 PetscInt size; 5355 5356 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5357 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5358 } 5359 break; 5360 case 2: 5361 /* Hex 2D */ 5362 /* All cells have 4 faces */ 5363 for(c = cStart; c < cEnd; ++c) { 5364 for(r = 0; r < 4; ++r) { 5365 const PetscInt newp = (c - cStart)*4 + r; 5366 5367 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5368 } 5369 } 5370 /* Split faces have 2 vertices and the same cells as the parent */ 5371 for(f = fStart; f < fEnd; ++f) { 5372 for(r = 0; r < 2; ++r) { 5373 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5374 PetscInt size; 5375 5376 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5377 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5378 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5379 } 5380 } 5381 /* Interior faces have 2 vertices and 2 cells */ 5382 for(c = cStart; c < cEnd; ++c) { 5383 for(r = 0; r < 4; ++r) { 5384 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5385 5386 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5387 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5388 } 5389 } 5390 /* Old vertices have identical supports */ 5391 for(v = vStart; v < vEnd; ++v) { 5392 const PetscInt newp = vStartNew + (v - vStart); 5393 PetscInt size; 5394 5395 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5396 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5397 } 5398 /* Face vertices have 2 + cells supports */ 5399 for(f = fStart; f < fEnd; ++f) { 5400 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5401 PetscInt size; 5402 5403 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5404 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5405 } 5406 /* Cell vertices have 4 supports */ 5407 for(c = cStart; c < cEnd; ++c) { 5408 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5409 5410 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5411 } 5412 break; 5413 default: 5414 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5415 } 5416 PetscFunctionReturn(0); 5417 } 5418 5419 #undef __FUNCT__ 5420 #define __FUNCT__ "CellRefinerSetCones" 5421 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5422 { 5423 PetscInt depth, cStart, cEnd, cStartNew, cEndNew, c, vStart, vEnd, vStartNew, vEndNew, v, fStart, fEnd, fStartNew, fEndNew, f, eStart, eEnd, eStartNew, eEndNew, r, p; 5424 PetscInt maxSupportSize, *supportRef; 5425 PetscErrorCode ierr; 5426 5427 PetscFunctionBegin; 5428 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5429 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5430 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5431 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5432 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5433 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5434 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5435 switch(refiner) { 5436 case 1: 5437 /* Simplicial 2D */ 5438 /* 5439 2 5440 |\ 5441 | \ 5442 | \ 5443 | \ 5444 | C \ 5445 | \ 5446 | \ 5447 2---1---1 5448 |\ D / \ 5449 | 2 0 \ 5450 |A \ / B \ 5451 0---0-------1 5452 */ 5453 /* All cells have 3 faces */ 5454 for(c = cStart; c < cEnd; ++c) { 5455 const PetscInt newp = (c - cStart)*4; 5456 const PetscInt *cone, *ornt; 5457 PetscInt coneNew[3], orntNew[3]; 5458 5459 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5460 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5461 /* A triangle */ 5462 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5463 orntNew[0] = ornt[0]; 5464 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5465 orntNew[1] = -2; 5466 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5467 orntNew[2] = ornt[2]; 5468 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5469 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5470 #if 1 5471 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 for(p = 0; p < 3; ++p) { 5473 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 } 5475 #endif 5476 /* B triangle */ 5477 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5478 orntNew[0] = ornt[0]; 5479 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5480 orntNew[1] = ornt[1]; 5481 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5482 orntNew[2] = -2; 5483 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5484 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5485 #if 1 5486 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 for(p = 0; p < 3; ++p) { 5488 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 } 5490 #endif 5491 /* C triangle */ 5492 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5493 orntNew[0] = -2; 5494 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5495 orntNew[1] = ornt[1]; 5496 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5497 orntNew[2] = ornt[2]; 5498 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5499 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5500 #if 1 5501 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 for(p = 0; p < 3; ++p) { 5503 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 } 5505 #endif 5506 /* D triangle */ 5507 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5508 orntNew[0] = 0; 5509 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5510 orntNew[1] = 0; 5511 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5512 orntNew[2] = 0; 5513 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5514 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5515 #if 1 5516 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 for(p = 0; p < 3; ++p) { 5518 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 } 5520 #endif 5521 } 5522 /* Split faces have 2 vertices and the same cells as the parent */ 5523 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5524 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5525 for(f = fStart; f < fEnd; ++f) { 5526 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5527 5528 for(r = 0; r < 2; ++r) { 5529 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5530 const PetscInt *cone, *support; 5531 PetscInt coneNew[2], coneSize, c, supportSize, s; 5532 5533 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5534 coneNew[0] = vStartNew + (cone[0] - vStart); 5535 coneNew[1] = vStartNew + (cone[1] - vStart); 5536 coneNew[(r+1)%2] = newv; 5537 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5538 #if 1 5539 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5540 for(p = 0; p < 2; ++p) { 5541 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 } 5543 #endif 5544 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5545 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5546 for(s = 0; s < supportSize; ++s) { 5547 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5548 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5549 for(c = 0; c < coneSize; ++c) { 5550 if (cone[c] == f) { 5551 break; 5552 } 5553 } 5554 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5555 } 5556 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5557 #if 1 5558 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5559 for(p = 0; p < supportSize; ++p) { 5560 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 } 5562 #endif 5563 } 5564 } 5565 /* Interior faces have 2 vertices and 2 cells */ 5566 for(c = cStart; c < cEnd; ++c) { 5567 const PetscInt *cone; 5568 5569 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5570 for(r = 0; r < 3; ++r) { 5571 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5572 PetscInt coneNew[2]; 5573 PetscInt supportNew[2]; 5574 5575 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5576 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5577 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5578 #if 1 5579 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5580 for(p = 0; p < 2; ++p) { 5581 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 } 5583 #endif 5584 supportNew[0] = (c - cStart)*4 + r; 5585 supportNew[1] = (c - cStart)*4 + 3; 5586 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5587 #if 1 5588 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5589 for(p = 0; p < 2; ++p) { 5590 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 } 5592 #endif 5593 } 5594 } 5595 /* Old vertices have identical supports */ 5596 for(v = vStart; v < vEnd; ++v) { 5597 const PetscInt newp = vStartNew + (v - vStart); 5598 const PetscInt *support, *cone; 5599 PetscInt size, s; 5600 5601 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5602 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5603 for(s = 0; s < size; ++s) { 5604 PetscInt r = 0; 5605 5606 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5607 if (cone[1] == v) r = 1; 5608 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5609 } 5610 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5611 #if 1 5612 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5613 for(p = 0; p < size; ++p) { 5614 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 } 5616 #endif 5617 } 5618 /* Face vertices have 2 + cells*2 supports */ 5619 for(f = fStart; f < fEnd; ++f) { 5620 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5621 const PetscInt *cone, *support; 5622 PetscInt size, s; 5623 5624 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5625 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5626 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5627 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5628 for(s = 0; s < size; ++s) { 5629 PetscInt r = 0; 5630 5631 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5632 if (cone[1] == f) r = 1; 5633 else if (cone[2] == f) r = 2; 5634 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5635 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5636 } 5637 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5638 #if 1 5639 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5640 for(p = 0; p < 2+size*2; ++p) { 5641 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 } 5643 #endif 5644 } 5645 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5646 break; 5647 case 2: 5648 /* Hex 2D */ 5649 /* 5650 3---------2---------2 5651 | | | 5652 | D 2 C | 5653 | | | 5654 3----3----0----1----1 5655 | | | 5656 | A 0 B | 5657 | | | 5658 0---------0---------1 5659 */ 5660 /* All cells have 4 faces */ 5661 for(c = cStart; c < cEnd; ++c) { 5662 const PetscInt newp = (c - cStart)*4; 5663 const PetscInt *cone, *ornt; 5664 PetscInt coneNew[4], orntNew[4]; 5665 5666 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5667 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5668 /* A quad */ 5669 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5670 orntNew[0] = ornt[0]; 5671 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5672 orntNew[1] = 0; 5673 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5674 orntNew[2] = -2; 5675 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5676 orntNew[3] = ornt[3]; 5677 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5678 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5679 #if 1 5680 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 for(p = 0; p < 4; ++p) { 5682 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 } 5684 #endif 5685 /* B quad */ 5686 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5687 orntNew[0] = ornt[0]; 5688 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5689 orntNew[1] = ornt[1]; 5690 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5691 orntNew[2] = 0; 5692 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5693 orntNew[3] = -2; 5694 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5695 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5696 #if 1 5697 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 for(p = 0; p < 4; ++p) { 5699 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 } 5701 #endif 5702 /* C quad */ 5703 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5704 orntNew[0] = -2; 5705 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5706 orntNew[1] = ornt[1]; 5707 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5708 orntNew[2] = ornt[2]; 5709 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5710 orntNew[3] = 0; 5711 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5712 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5713 #if 1 5714 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 for(p = 0; p < 4; ++p) { 5716 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 } 5718 #endif 5719 /* D quad */ 5720 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5721 orntNew[0] = 0; 5722 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5723 orntNew[1] = -2; 5724 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5725 orntNew[2] = ornt[2]; 5726 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5727 orntNew[3] = ornt[3]; 5728 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5729 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5730 #if 1 5731 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 for(p = 0; p < 4; ++p) { 5733 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 } 5735 #endif 5736 } 5737 /* Split faces have 2 vertices and the same cells as the parent */ 5738 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5739 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5740 for(f = fStart; f < fEnd; ++f) { 5741 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5742 5743 for(r = 0; r < 2; ++r) { 5744 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5745 const PetscInt *cone, *support; 5746 PetscInt coneNew[2], coneSize, c, supportSize, s; 5747 5748 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5749 coneNew[0] = vStartNew + (cone[0] - vStart); 5750 coneNew[1] = vStartNew + (cone[1] - vStart); 5751 coneNew[(r+1)%2] = newv; 5752 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5753 #if 1 5754 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5755 for(p = 0; p < 2; ++p) { 5756 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 } 5758 #endif 5759 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5760 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5761 for(s = 0; s < supportSize; ++s) { 5762 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5763 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5764 for(c = 0; c < coneSize; ++c) { 5765 if (cone[c] == f) { 5766 break; 5767 } 5768 } 5769 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5770 } 5771 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5772 #if 1 5773 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5774 for(p = 0; p < supportSize; ++p) { 5775 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 } 5777 #endif 5778 } 5779 } 5780 /* Interior faces have 2 vertices and 2 cells */ 5781 for(c = cStart; c < cEnd; ++c) { 5782 const PetscInt *cone; 5783 PetscInt coneNew[2], supportNew[2]; 5784 5785 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5786 for(r = 0; r < 4; ++r) { 5787 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5788 5789 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5790 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5791 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5792 #if 1 5793 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5794 for(p = 0; p < 2; ++p) { 5795 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 } 5797 #endif 5798 supportNew[0] = (c - cStart)*4 + r; 5799 supportNew[1] = (c - cStart)*4 + (r+1)%4; 5800 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5801 #if 1 5802 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5803 for(p = 0; p < 2; ++p) { 5804 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 } 5806 #endif 5807 } 5808 } 5809 /* Old vertices have identical supports */ 5810 for(v = vStart; v < vEnd; ++v) { 5811 const PetscInt newp = vStartNew + (v - vStart); 5812 const PetscInt *support, *cone; 5813 PetscInt size, s; 5814 5815 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5816 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5817 for(s = 0; s < size; ++s) { 5818 PetscInt r = 0; 5819 5820 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5821 if (cone[1] == v) r = 1; 5822 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5823 } 5824 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5825 #if 1 5826 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5827 for(p = 0; p < size; ++p) { 5828 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 } 5830 #endif 5831 } 5832 /* Face vertices have 2 + cells supports */ 5833 for(f = fStart; f < fEnd; ++f) { 5834 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5835 const PetscInt *cone, *support; 5836 PetscInt size, s; 5837 5838 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5839 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5840 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5841 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5842 for(s = 0; s < size; ++s) { 5843 PetscInt r = 0; 5844 5845 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5846 if (cone[1] == f) r = 1; 5847 else if (cone[2] == f) r = 2; 5848 else if (cone[3] == f) r = 3; 5849 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 5850 } 5851 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5852 #if 1 5853 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5854 for(p = 0; p < 2+size; ++p) { 5855 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 } 5857 #endif 5858 } 5859 /* Cell vertices have 4 supports */ 5860 for(c = cStart; c < cEnd; ++c) { 5861 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5862 PetscInt supportNew[4]; 5863 5864 for(r = 0; r < 4; ++r) { 5865 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5866 } 5867 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5868 } 5869 break; 5870 default: 5871 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5872 } 5873 PetscFunctionReturn(0); 5874 } 5875 5876 #undef __FUNCT__ 5877 #define __FUNCT__ "CellRefinerSetCoordinates" 5878 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5879 { 5880 PetscSection coordSection, coordSectionNew; 5881 Vec coordinates, coordinatesNew; 5882 PetscScalar *coords, *coordsNew; 5883 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, f; 5884 PetscErrorCode ierr; 5885 5886 PetscFunctionBegin; 5887 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5888 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5889 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5890 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5891 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5892 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 5893 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5894 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 5895 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 5896 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 5897 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 5898 switch(refiner) { 5899 case 1: 5900 case 2: 5901 /* Simplicial and Hex 2D */ 5902 /* All vertices have the dim coordinates */ 5903 for(v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 5904 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 5905 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 5906 } 5907 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 5908 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 5909 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5910 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 5911 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 5912 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 5913 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 5914 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 5915 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 5916 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5917 /* Old vertices have the same coordinates */ 5918 for(v = vStart; v < vEnd; ++v) { 5919 const PetscInt newv = vStartNew + (v - vStart); 5920 PetscInt off, offnew, d; 5921 5922 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5923 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5924 for(d = 0; d < dim; ++d) { 5925 coordsNew[offnew+d] = coords[off+d]; 5926 } 5927 } 5928 /* Face vertices have the average of endpoint coordinates */ 5929 for(f = fStart; f < fEnd; ++f) { 5930 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5931 const PetscInt *cone; 5932 PetscInt coneSize, offA, offB, offnew, d; 5933 5934 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 5935 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 5936 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5937 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5938 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5939 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5940 for(d = 0; d < dim; ++d) { 5941 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 5942 } 5943 } 5944 /* Just Hex 2D */ 5945 if (refiner == 2) { 5946 /* Cell vertices have the average of corner coordinates */ 5947 for(c = cStart; c < cEnd; ++c) { 5948 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5949 PetscInt *cone = PETSC_NULL; 5950 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 5951 5952 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5953 for(p = 0; p < closureSize*2; p += 2) { 5954 const PetscInt point = cone[p]; 5955 if ((point >= vStart) && (point < vEnd)) { 5956 cone[coneSize++] = point; 5957 } 5958 } 5959 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 5960 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5961 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5962 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 5963 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 5964 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5965 for(d = 0; d < dim; ++d) { 5966 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 5967 } 5968 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5969 } 5970 } 5971 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 5972 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5973 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 5974 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 5975 break; 5976 default: 5977 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5978 } 5979 PetscFunctionReturn(0); 5980 } 5981 5982 #undef __FUNCT__ 5983 #define __FUNCT__ "DMPlexCreateProcessSF" 5984 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 5985 { 5986 PetscInt numRoots, numLeaves, l; 5987 const PetscInt *localPoints; 5988 const PetscSFNode *remotePoints; 5989 PetscInt *localPointsNew; 5990 PetscSFNode *remotePointsNew; 5991 PetscInt *ranks, *ranksNew; 5992 PetscErrorCode ierr; 5993 5994 PetscFunctionBegin; 5995 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5996 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 5997 for(l = 0; l < numLeaves; ++l) { 5998 ranks[l] = remotePoints[l].rank; 5999 } 6000 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6001 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6002 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6003 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6004 for(l = 0; l < numLeaves; ++l) { 6005 ranksNew[l] = ranks[l]; 6006 localPointsNew[l] = l; 6007 remotePointsNew[l].index = 0; 6008 remotePointsNew[l].rank = ranksNew[l]; 6009 } 6010 ierr = PetscFree(ranks);CHKERRQ(ierr); 6011 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6012 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6013 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6014 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6015 PetscFunctionReturn(0); 6016 } 6017 6018 #undef __FUNCT__ 6019 #define __FUNCT__ "CellRefinerCreateSF" 6020 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6021 { 6022 PetscSF sf, sfNew, sfProcess; 6023 IS processRanks; 6024 MPI_Datatype depthType; 6025 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6026 const PetscInt *localPoints, *neighbors; 6027 const PetscSFNode *remotePoints; 6028 PetscInt *localPointsNew; 6029 PetscSFNode *remotePointsNew; 6030 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6031 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, vStart, vStartNew, vEnd, fStart, fStartNew, fEnd, eStart, eStartNew, eEnd, r, n; 6032 PetscErrorCode ierr; 6033 6034 PetscFunctionBegin; 6035 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6036 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6037 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6038 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6039 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6040 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6041 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6042 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6043 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6044 /* Caculate size of new SF */ 6045 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6046 if (numRoots < 0) PetscFunctionReturn(0); 6047 for(l = 0; l < numLeaves; ++l) { 6048 const PetscInt p = localPoints[l]; 6049 6050 switch(refiner) { 6051 case 1: 6052 /* Simplicial 2D */ 6053 if ((p >= vStart) && (p < vEnd)) { 6054 /* Old vertices stay the same */ 6055 ++numLeavesNew; 6056 } else if ((p >= fStart) && (p < fEnd)) { 6057 /* Old faces add new faces and vertex */ 6058 numLeavesNew += 1 + 2; 6059 } else if ((p >= cStart) && (p < cEnd)) { 6060 /* Old cells add new cells and interior faces */ 6061 numLeavesNew += 4 + 3; 6062 } 6063 break; 6064 case 2: 6065 /* Hex 2D */ 6066 if ((p >= vStart) && (p < vEnd)) { 6067 /* Old vertices stay the same */ 6068 ++numLeavesNew; 6069 } else if ((p >= fStart) && (p < fEnd)) { 6070 /* Old faces add new faces and vertex */ 6071 numLeavesNew += 1 + 2; 6072 } else if ((p >= cStart) && (p < cEnd)) { 6073 /* Old cells add new cells and interior faces */ 6074 numLeavesNew += 4 + 4; 6075 } 6076 break; 6077 default: 6078 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6079 } 6080 } 6081 /* Communicate depthSizes for each remote rank */ 6082 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6083 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6084 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6085 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 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6087 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6088 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6089 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6090 for(n = 0; n < numNeighbors; ++n) { 6091 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6092 } 6093 depthSizeOld[depth] = cEnd - cStart; 6094 depthSizeOld[0] = vEnd - vStart; 6095 depthSizeOld[depth-1] = fEnd - fStart; 6096 depthSizeOld[1] = eEnd - eStart; 6097 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6098 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6099 for(n = 0; n < numNeighbors; ++n) { 6100 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6101 } 6102 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6103 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6104 /* Calculate new point SF */ 6105 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6106 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6107 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6108 for(l = 0, m = 0; l < numLeaves; ++l) { 6109 PetscInt p = localPoints[l]; 6110 PetscInt rp = remotePoints[l].index, n; 6111 PetscMPIInt rrank = remotePoints[l].rank; 6112 6113 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6114 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6115 switch(refiner) { 6116 case 1: 6117 /* Simplicial 2D */ 6118 if ((p >= vStart) && (p < vEnd)) { 6119 /* Old vertices stay the same */ 6120 localPointsNew[m] = vStartNew + (p - vStart); 6121 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6122 remotePointsNew[m].rank = rrank; 6123 ++m; 6124 } else if ((p >= fStart) && (p < fEnd)) { 6125 /* Old faces add new faces and vertex */ 6126 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6127 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6128 remotePointsNew[m].rank = rrank; 6129 ++m; 6130 for(r = 0; r < 2; ++r, ++m) { 6131 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6132 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6133 remotePointsNew[m].rank = rrank; 6134 } 6135 } else if ((p >= cStart) && (p < cEnd)) { 6136 /* Old cells add new cells and interior faces */ 6137 for(r = 0; r < 4; ++r, ++m) { 6138 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6139 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6140 remotePointsNew[m].rank = rrank; 6141 } 6142 for(r = 0; r < 3; ++r, ++m) { 6143 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6144 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6145 remotePointsNew[m].rank = rrank; 6146 } 6147 } 6148 break; 6149 case 2: 6150 /* Hex 2D */ 6151 if ((p >= vStart) && (p < vEnd)) { 6152 /* Old vertices stay the same */ 6153 localPointsNew[m] = vStartNew + (p - vStart); 6154 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6155 remotePointsNew[m].rank = rrank; 6156 ++m; 6157 } else if ((p >= fStart) && (p < fEnd)) { 6158 /* Old faces add new faces and vertex */ 6159 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6160 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6161 remotePointsNew[m].rank = rrank; 6162 ++m; 6163 for(r = 0; r < 2; ++r, ++m) { 6164 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6165 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6166 remotePointsNew[m].rank = rrank; 6167 } 6168 } else if ((p >= cStart) && (p < cEnd)) { 6169 /* Old cells add new cells and interior faces */ 6170 for(r = 0; r < 4; ++r, ++m) { 6171 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6172 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6173 remotePointsNew[m].rank = rrank; 6174 } 6175 for(r = 0; r < 4; ++r, ++m) { 6176 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6177 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6178 remotePointsNew[m].rank = rrank; 6179 } 6180 } 6181 break; 6182 default: 6183 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6184 } 6185 } 6186 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6187 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6188 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6189 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6190 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6191 PetscFunctionReturn(0); 6192 } 6193 6194 #undef __FUNCT__ 6195 #define __FUNCT__ "CellRefinerCreateLabels" 6196 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6197 { 6198 PetscInt numLabels, l; 6199 PetscInt newp, cStart, cEnd, vStart, vStartNew, vEnd, fStart, fStartNew, fEnd, eStart, eEnd, r; 6200 PetscErrorCode ierr; 6201 6202 PetscFunctionBegin; 6203 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6204 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6205 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6206 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6207 vStartNew = depthSize[2]; 6208 fStartNew = depthSize[2] + depthSize[0]; 6209 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6210 for(l = 0; l < numLabels; ++l) { 6211 DMLabel label, labelNew; 6212 const char *lname; 6213 PetscBool isDepth; 6214 IS valueIS; 6215 const PetscInt *values; 6216 PetscInt numValues, val; 6217 6218 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6219 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6220 if (isDepth) continue; 6221 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6222 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6223 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6224 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6225 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6226 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6227 for(val = 0; val < numValues; ++val) { 6228 IS pointIS; 6229 const PetscInt *points; 6230 PetscInt numPoints, n; 6231 6232 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6233 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6234 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6235 for(n = 0; n < numPoints; ++n) { 6236 const PetscInt p = points[n]; 6237 switch(refiner) { 6238 case 1: 6239 /* Simplicial 2D */ 6240 if ((p >= vStart) && (p < vEnd)) { 6241 /* Old vertices stay the same */ 6242 newp = vStartNew + (p - vStart); 6243 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6244 } else if ((p >= fStart) && (p < fEnd)) { 6245 /* Old faces add new faces and vertex */ 6246 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6247 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6248 for(r = 0; r < 2; ++r) { 6249 newp = fStartNew + (p - fStart)*2 + r; 6250 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6251 } 6252 } else if ((p >= cStart) && (p < cEnd)) { 6253 /* Old cells add new cells and interior faces */ 6254 for(r = 0; r < 4; ++r) { 6255 newp = (p - cStart)*4 + r; 6256 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6257 } 6258 for(r = 0; r < 3; ++r) { 6259 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6260 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6261 } 6262 } 6263 break; 6264 case 2: 6265 /* Hex 2D */ 6266 if ((p >= vStart) && (p < vEnd)) { 6267 /* Old vertices stay the same */ 6268 newp = vStartNew + (p - vStart); 6269 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6270 } else if ((p >= fStart) && (p < fEnd)) { 6271 /* Old faces add new faces and vertex */ 6272 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6273 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6274 for(r = 0; r < 2; ++r) { 6275 newp = fStartNew + (p - fStart)*2 + r; 6276 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6277 } 6278 } else if ((p >= cStart) && (p < cEnd)) { 6279 /* Old cells add new cells and interior faces and vertex */ 6280 for(r = 0; r < 4; ++r) { 6281 newp = (p - cStart)*4 + r; 6282 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6283 } 6284 for(r = 0; r < 4; ++r) { 6285 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6286 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6287 } 6288 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6289 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6290 } 6291 break; 6292 default: 6293 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6294 } 6295 } 6296 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6297 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6298 } 6299 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6300 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6301 if (0) { 6302 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6303 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6304 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6305 } 6306 } 6307 PetscFunctionReturn(0); 6308 } 6309 6310 #undef __FUNCT__ 6311 #define __FUNCT__ "DMPlexRefine_Uniform" 6312 /* This will only work for interpolated meshes */ 6313 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6314 { 6315 DM rdm; 6316 PetscInt *depthSize; 6317 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6318 PetscErrorCode ierr; 6319 6320 PetscFunctionBegin; 6321 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 6322 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6323 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6324 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6325 /* Calculate number of new points of each depth */ 6326 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6327 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6328 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6329 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6330 /* Step 1: Set chart */ 6331 for(d = 0; d <= depth; ++d) { 6332 pEnd += depthSize[d]; 6333 } 6334 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6335 /* Step 2: Set cone/support sizes */ 6336 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6337 /* Step 3: Setup refined DM */ 6338 ierr = DMSetUp(rdm);CHKERRQ(ierr); 6339 /* Step 4: Set cones and supports */ 6340 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6341 /* Step 5: Stratify */ 6342 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6343 /* Step 6: Set coordinates for vertices */ 6344 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6345 /* Step 7: Create pointSF */ 6346 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6347 /* Step 8: Create labels */ 6348 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6349 ierr = PetscFree(depthSize);CHKERRQ(ierr); 6350 6351 *dmRefined = rdm; 6352 #if 0 6353 DM_Plex *mesh = (DM_Plex *) dm->data; 6354 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 6355 //ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); 6356 6357 PetscFunctionBegin; 6358 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6359 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 6360 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6361 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6362 ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr); 6363 6364 /* Count number of new cells which are normal and extra */ 6365 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 6366 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 6367 for(c = cStart; c < cEnd2; ++c) { 6368 PetscInt n; 6369 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); // refiner.numNewCells 6370 newNumCellsNormal += n; 6371 } 6372 for(c = cEnd2; c < cEnd; ++c) { 6373 PetscInt n; 6374 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); // refiner.numNewCells 6375 newNumCellsExtra += n; 6376 } 6377 newNumCells = newNumCellsNormal + newNumCellsExtra; 6378 /* Count number of new vertices which are normal and extra */ 6379 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 6380 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 6381 for(c = cStart; c < cEnd; ++c) { 6382 PetscInt *closure = PETSC_NULL; 6383 PetscInt closureSize, numCorners = 0, p; 6384 6385 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6386 for(p = 0; p < closureSize*2; p += 2) { 6387 const PetscInt point = closure[p]; 6388 if ((point >= vStart) && (point < vEnd)) { 6389 closure[numCorners++] = point; 6390 } 6391 } 6392 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); // refiner.splitCell 6393 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6394 } 6395 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 6396 for(c = cEnd2; c < cEnd; ++c) { 6397 PetscInt *closure = PETSC_NULL; 6398 PetscInt closureSize, numCorners = 0, p; 6399 6400 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6401 for(p = 0; p < closureSize*2; p += 2) { 6402 const PetscInt point = closure[p]; 6403 if ((point >= vStart) && (point < vEnd)) { 6404 closure[numCorners++] = point; 6405 } 6406 } 6407 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); // refiner.splitCellUncensored 6408 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6409 } // for 6410 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 6411 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 6412 6413 #if 1 6414 PetscInt oldNumCellsNormal = cEnd2 - cStart; 6415 PetscInt oldNumCellsExtra = cEnd - cEnd2; 6416 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 6417 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 6418 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 6419 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 6420 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 6421 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 6422 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 6423 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 6424 ierr = PetscSynchronizedFlush(comm); 6425 #endif 6426 6427 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 6428 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 6429 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 6430 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 6431 ierr = DMPlexGetVTKBounds(*dmRefined, newNumCellsNormal, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 6432 /* Set cone and support sizes for new normal cells */ 6433 PetscInt newCell = 0; 6434 for(c = cStart; c < cEnd2; ++c) { 6435 PetscInt coneSize, n, i; 6436 6437 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6438 ierr = CellRefinerGetNumSubcells(refiner, c, &n); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6439 for(i = 0; i < n; ++i, ++newCell) { 6440 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 6441 } 6442 6443 PetscInt *closure = PETSC_NULL; 6444 PetscInt closureSize, numCorners = 0, p; 6445 6446 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6447 for(p = 0; p < closureSize*2; p += 2) { 6448 const PetscInt point = closure[p]; 6449 if ((point >= vStart) && (point < vEnd)) { 6450 closure[numCorners++] = point; 6451 } 6452 } 6453 // ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6454 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6455 } 6456 6457 // Reset current new cell value and loop over censored cells. 6458 curNewCell = _orderNewMesh->cellsCensored().min(); 6459 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 6460 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 6461 // Set new cone and support sizes 6462 cV.clear(); 6463 sieve->cone(*c_iter, cV); 6464 const point_type* cone = cV.getPoints(); 6465 const int coneSize = cV.getSize(); 6466 6467 const point_type* newCells; 6468 int numNewCells = 0; 6469 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6470 6471 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6472 newSieve->setConeSize(curNewCell, coneSize); 6473 for(int iVertex=0; iVertex < coneSize; ++iVertex) { 6474 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 6475 } // for 6476 } // for 6477 } // for 6478 newSieve->allocate(); 6479 6480 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 6481 6482 // Create refined cells in new sieve. 6483 curNewCell = _orderNewMesh->cellsNormal().min(); 6484 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 6485 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 6486 cV.clear(); 6487 sieve->cone(*c_iter, cV); 6488 const point_type *cone = cV.getPoints(); 6489 const int coneSize = cV.getSize(); 6490 6491 const point_type* newCells; 6492 int numNewCells = 0; 6493 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6494 6495 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6496 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 6497 } // for 6498 } // for 6499 curNewCell = _orderNewMesh->cellsCensored().min(); 6500 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 6501 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 6502 cV.clear(); 6503 sieve->cone(*c_iter, cV); 6504 const point_type *cone = cV.getPoints(); 6505 const int coneSize = cV.getSize(); 6506 6507 const point_type* newCells; 6508 int numNewCells = 0; 6509 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6510 6511 for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6512 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 6513 } // for 6514 } // for 6515 newSieve->symmetrize(); 6516 6517 // Set coordinates in refined mesh. 6518 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 6519 assert(!coordinates.isNull()); 6520 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 6521 assert(!newCoordinates.isNull()); 6522 6523 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 6524 assert(vertices->size() > 0); 6525 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 6526 assert(spaceDim > 0); 6527 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 6528 6529 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 6530 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 6531 newCoordinates->setFiberDimension(*v_iter, spaceDim); 6532 } // for 6533 newCoordinates->allocatePoint(); 6534 6535 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 6536 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 6537 //std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; 6538 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 6539 } // for 6540 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 6541 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 6542 //std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; 6543 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 6544 } // for 6545 6546 refiner.setCoordsNewVertices(newCoordinates, coordinates); 6547 6548 // Create sensored depth 6549 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 6550 assert(!censoredLabel.isNull()); 6551 6552 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 6553 6554 newSieve->roots(depthVisitor); 6555 while(depthVisitor.isModified()) { 6556 // FIX: Avoid the copy here somehow by fixing the traversal 6557 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 6558 6559 depthVisitor.clear(); 6560 newSieve->support(modifiedPoints, depthVisitor); 6561 } // while 6562 // Stratify refined mesh 6563 // Calculate new point SF 6564 _calcNewOverlap(newMesh, mesh, refiner); 6565 // Calculate new labels 6566 _createLabels(newMesh, mesh, refiner); 6567 #endif 6568 PetscFunctionReturn(0); 6569 } 6570 6571 #undef __FUNCT__ 6572 #define __FUNCT__ "DMPlexSetRefinementUniform" 6573 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 6574 { 6575 DM_Plex *mesh = (DM_Plex *) dm->data; 6576 6577 PetscFunctionBegin; 6578 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6579 mesh->refinementUniform = refinementUniform; 6580 PetscFunctionReturn(0); 6581 } 6582 6583 #undef __FUNCT__ 6584 #define __FUNCT__ "DMPlexGetRefinementUniform" 6585 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 6586 { 6587 DM_Plex *mesh = (DM_Plex *) dm->data; 6588 6589 PetscFunctionBegin; 6590 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6591 PetscValidPointer(refinementUniform, 2); 6592 *refinementUniform = mesh->refinementUniform; 6593 PetscFunctionReturn(0); 6594 } 6595 6596 #undef __FUNCT__ 6597 #define __FUNCT__ "DMPlexSetRefinementLimit" 6598 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 6599 { 6600 DM_Plex *mesh = (DM_Plex *) dm->data; 6601 6602 PetscFunctionBegin; 6603 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6604 mesh->refinementLimit = refinementLimit; 6605 PetscFunctionReturn(0); 6606 } 6607 6608 #undef __FUNCT__ 6609 #define __FUNCT__ "DMPlexGetRefinementLimit" 6610 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 6611 { 6612 DM_Plex *mesh = (DM_Plex *) dm->data; 6613 6614 PetscFunctionBegin; 6615 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6616 PetscValidPointer(refinementLimit, 2); 6617 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 6618 *refinementLimit = mesh->refinementLimit; 6619 PetscFunctionReturn(0); 6620 } 6621 6622 #undef __FUNCT__ 6623 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 6624 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 6625 { 6626 PetscInt dim, cStart, coneSize; 6627 PetscErrorCode ierr; 6628 6629 PetscFunctionBegin; 6630 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6631 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 6632 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 6633 switch(dim) { 6634 case 2: 6635 switch(coneSize) { 6636 case 3: 6637 *cellRefiner = 1;break; 6638 case 4: 6639 *cellRefiner = 2;break; 6640 default: 6641 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 6642 } 6643 break; 6644 default: 6645 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 6646 } 6647 PetscFunctionReturn(0); 6648 } 6649 6650 #undef __FUNCT__ 6651 #define __FUNCT__ "DMRefine_Plex" 6652 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 6653 { 6654 PetscReal refinementLimit; 6655 PetscInt dim, cStart, cEnd; 6656 char genname[1024], *name = PETSC_NULL; 6657 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 6658 PetscErrorCode ierr; 6659 6660 PetscFunctionBegin; 6661 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 6662 if (isUniform) { 6663 CellRefiner cellRefiner; 6664 6665 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 6666 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 6667 PetscFunctionReturn(0); 6668 } 6669 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 6670 if (refinementLimit == 0.0) PetscFunctionReturn(0); 6671 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6672 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6673 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 6674 if (flg) {name = genname;} 6675 if (name) { 6676 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 6677 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 6678 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 6679 } 6680 switch(dim) { 6681 case 2: 6682 if (!name || isTriangle) { 6683 #ifdef PETSC_HAVE_TRIANGLE 6684 double *maxVolumes; 6685 PetscInt c; 6686 6687 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 6688 for (c = 0; c < cEnd-cStart; ++c) { 6689 maxVolumes[c] = refinementLimit; 6690 } 6691 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6692 #else 6693 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 6694 #endif 6695 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 6696 break; 6697 case 3: 6698 if (!name || isCTetgen) { 6699 #ifdef PETSC_HAVE_CTETGEN 6700 PetscReal *maxVolumes; 6701 PetscInt c; 6702 6703 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 6704 for (c = 0; c < cEnd-cStart; ++c) { 6705 maxVolumes[c] = refinementLimit; 6706 } 6707 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6708 #else 6709 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 6710 #endif 6711 } else if (isTetgen) { 6712 #ifdef PETSC_HAVE_TETGEN 6713 double *maxVolumes; 6714 PetscInt c; 6715 6716 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 6717 for (c = 0; c < cEnd-cStart; ++c) { 6718 maxVolumes[c] = refinementLimit; 6719 } 6720 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6721 #else 6722 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 6723 #endif 6724 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 6725 break; 6726 default: 6727 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 6728 } 6729 PetscFunctionReturn(0); 6730 } 6731 6732 #undef __FUNCT__ 6733 #define __FUNCT__ "DMPlexGetDepth" 6734 /*@ 6735 DMPlexGetDepth - get the number of strata 6736 6737 Not Collective 6738 6739 Input Parameters: 6740 . dm - The DMPlex object 6741 6742 Output Parameters: 6743 . depth - number of strata 6744 6745 Level: developer 6746 6747 Notes: 6748 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 6749 6750 .keywords: mesh, points 6751 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 6752 @*/ 6753 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 6754 { 6755 PetscInt d; 6756 PetscErrorCode ierr; 6757 6758 PetscFunctionBegin; 6759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6760 PetscValidPointer(depth, 2); 6761 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 6762 *depth = d-1; 6763 PetscFunctionReturn(0); 6764 } 6765 6766 #undef __FUNCT__ 6767 #define __FUNCT__ "DMPlexGetDepthStratum" 6768 /*@ 6769 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 6770 6771 Not Collective 6772 6773 Input Parameters: 6774 + dm - The DMPlex object 6775 - stratumValue - The requested depth 6776 6777 Output Parameters: 6778 + start - The first point at this depth 6779 - end - One beyond the last point at this depth 6780 6781 Level: developer 6782 6783 .keywords: mesh, points 6784 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 6785 @*/ 6786 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) { 6787 DM_Plex *mesh = (DM_Plex *) dm->data; 6788 DMLabel next = mesh->labels; 6789 PetscBool flg = PETSC_FALSE; 6790 PetscInt depth; 6791 PetscErrorCode ierr; 6792 6793 PetscFunctionBegin; 6794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6795 if (stratumValue < 0) { 6796 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6797 PetscFunctionReturn(0); 6798 } else { 6799 PetscInt pStart, pEnd; 6800 6801 if (start) {*start = 0;} 6802 if (end) {*end = 0;} 6803 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6804 if (pStart == pEnd) {PetscFunctionReturn(0);} 6805 } 6806 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6807 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6808 /* We should have a generic GetLabel() and a Label class */ 6809 while(next) { 6810 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6811 if (flg) break; 6812 next = next->next; 6813 } 6814 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6815 depth = stratumValue; 6816 if ((depth < 0) || (depth >= next->numStrata)) { 6817 if (start) {*start = 0;} 6818 if (end) {*end = 0;} 6819 } else { 6820 if (start) {*start = next->points[next->stratumOffsets[depth]];} 6821 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 6822 } 6823 PetscFunctionReturn(0); 6824 } 6825 6826 #undef __FUNCT__ 6827 #define __FUNCT__ "DMPlexGetHeightStratum" 6828 /*@ 6829 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 6830 6831 Not Collective 6832 6833 Input Parameters: 6834 + dm - The DMPlex object 6835 - stratumValue - The requested height 6836 6837 Output Parameters: 6838 + start - The first point at this height 6839 - end - One beyond the last point at this height 6840 6841 Level: developer 6842 6843 .keywords: mesh, points 6844 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 6845 @*/ 6846 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) { 6847 DM_Plex *mesh = (DM_Plex *) dm->data; 6848 DMLabel next = mesh->labels; 6849 PetscBool flg = PETSC_FALSE; 6850 PetscInt depth; 6851 PetscErrorCode ierr; 6852 6853 PetscFunctionBegin; 6854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6855 if (stratumValue < 0) { 6856 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6857 } else { 6858 PetscInt pStart, pEnd; 6859 6860 if (start) {*start = 0;} 6861 if (end) {*end = 0;} 6862 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6863 if (pStart == pEnd) {PetscFunctionReturn(0);} 6864 } 6865 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6866 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6867 /* We should have a generic GetLabel() and a Label class */ 6868 while(next) { 6869 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6870 if (flg) break; 6871 next = next->next; 6872 } 6873 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6874 depth = next->stratumValues[next->numStrata-1] - stratumValue; 6875 if ((depth < 0) || (depth >= next->numStrata)) { 6876 if (start) {*start = 0;} 6877 if (end) {*end = 0;} 6878 } else { 6879 if (start) {*start = next->points[next->stratumOffsets[depth]];} 6880 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 6881 } 6882 PetscFunctionReturn(0); 6883 } 6884 6885 #undef __FUNCT__ 6886 #define __FUNCT__ "DMPlexCreateSectionInitial" 6887 /* Set the number of dof on each point and separate by fields */ 6888 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) { 6889 PetscInt *numDofTot; 6890 PetscInt pStart = 0, pEnd = 0; 6891 PetscInt p, d, f; 6892 PetscErrorCode ierr; 6893 6894 PetscFunctionBegin; 6895 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 6896 for(d = 0; d <= dim; ++d) { 6897 numDofTot[d] = 0; 6898 for(f = 0; f < numFields; ++f) { 6899 numDofTot[d] += numDof[f*(dim+1)+d]; 6900 } 6901 } 6902 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 6903 if (numFields > 0) { 6904 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 6905 if (numComp) { 6906 for(f = 0; f < numFields; ++f) { 6907 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 6908 } 6909 } 6910 } 6911 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6912 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 6913 for(d = 0; d <= dim; ++d) { 6914 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 6915 for(p = pStart; p < pEnd; ++p) { 6916 for(f = 0; f < numFields; ++f) { 6917 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 6918 } 6919 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 6920 } 6921 } 6922 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 6923 PetscFunctionReturn(0); 6924 } 6925 6926 #undef __FUNCT__ 6927 #define __FUNCT__ "DMPlexCreateSectionBCDof" 6928 /* Set the number of dof on each point and separate by fields 6929 If constDof is PETSC_DETERMINE, constrain every dof on the point 6930 */ 6931 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) { 6932 PetscInt numFields; 6933 PetscInt bc; 6934 PetscErrorCode ierr; 6935 6936 PetscFunctionBegin; 6937 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6938 for (bc = 0; bc < numBC; ++bc) { 6939 PetscInt field = 0; 6940 const PetscInt *idx; 6941 PetscInt n, i; 6942 6943 if (numFields) {field = bcField[bc];} 6944 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 6945 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6946 for (i = 0; i < n; ++i) { 6947 const PetscInt p = idx[i]; 6948 PetscInt numConst = constDof; 6949 6950 /* Constrain every dof on the point */ 6951 if (numConst < 0) { 6952 if (numFields) { 6953 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 6954 } else { 6955 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 6956 } 6957 } 6958 if (numFields) { 6959 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 6960 } 6961 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 6962 } 6963 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6964 } 6965 PetscFunctionReturn(0); 6966 } 6967 6968 #undef __FUNCT__ 6969 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 6970 /* Set the constrained indices on each point and separate by fields */ 6971 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) { 6972 PetscInt *maxConstraints; 6973 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 6974 PetscErrorCode ierr; 6975 6976 PetscFunctionBegin; 6977 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6978 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6979 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 6980 for(f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 6981 for(p = pStart; p < pEnd; ++p) { 6982 PetscInt cdof; 6983 6984 if (numFields) { 6985 for(f = 0; f < numFields; ++f) { 6986 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 6987 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 6988 } 6989 } else { 6990 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6991 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 6992 } 6993 } 6994 for (f = 0; f < numFields; ++f) { 6995 maxConstraints[numFields] += maxConstraints[f]; 6996 } 6997 if (maxConstraints[numFields]) { 6998 PetscInt *indices; 6999 7000 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7001 for (p = pStart; p < pEnd; ++p) { 7002 PetscInt cdof, d; 7003 7004 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7005 if (cdof) { 7006 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 if (numFields) { 7008 PetscInt numConst = 0, foff = 0; 7009 7010 for (f = 0; f < numFields; ++f) { 7011 PetscInt cfdof, fdof; 7012 7013 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7014 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7015 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7016 for(d = 0; d < cfdof; ++d) { 7017 indices[numConst+d] = d; 7018 } 7019 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7020 for(d = 0; d < cfdof; ++d) { 7021 indices[numConst+d] += foff; 7022 } 7023 numConst += cfdof; 7024 foff += fdof; 7025 } 7026 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7027 } else { 7028 for (d = 0; d < cdof; ++d) { 7029 indices[d] = d; 7030 } 7031 } 7032 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7033 } 7034 } 7035 ierr = PetscFree(indices);CHKERRQ(ierr); 7036 } 7037 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7038 PetscFunctionReturn(0); 7039 } 7040 7041 #undef __FUNCT__ 7042 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7043 /* Set the constrained field indices on each point */ 7044 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) { 7045 const PetscInt *points, *indices; 7046 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7047 PetscErrorCode ierr; 7048 7049 PetscFunctionBegin; 7050 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7051 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 7053 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7054 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7055 if (!constraintIndices) { 7056 PetscInt *idx, i; 7057 7058 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7059 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7060 for(i = 0; i < maxDof; ++i) {idx[i] = i;} 7061 for(p = 0; p < numPoints; ++p) { 7062 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7063 } 7064 ierr = PetscFree(idx);CHKERRQ(ierr); 7065 } else { 7066 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7067 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7068 for(p = 0; p < numPoints; ++p) { 7069 PetscInt fcdof; 7070 7071 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7072 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 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7074 } 7075 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7076 } 7077 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7078 PetscFunctionReturn(0); 7079 } 7080 7081 #undef __FUNCT__ 7082 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7083 /* Set the constrained indices on each point and separate by fields */ 7084 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) { 7085 PetscInt *indices; 7086 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7087 PetscErrorCode ierr; 7088 7089 PetscFunctionBegin; 7090 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7091 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7092 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7093 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7094 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7095 for (p = pStart; p < pEnd; ++p) { 7096 PetscInt cdof, d; 7097 7098 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7099 if (cdof) { 7100 PetscInt numConst = 0, foff = 0; 7101 7102 for (f = 0; f < numFields; ++f) { 7103 const PetscInt *fcind; 7104 PetscInt fdof, fcdof; 7105 7106 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7107 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7108 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7109 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7110 for(d = 0; d < fcdof; ++d) { 7111 indices[numConst+d] = fcind[d]+foff; 7112 } 7113 foff += fdof; 7114 numConst += fcdof; 7115 } 7116 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7117 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7118 } 7119 } 7120 ierr = PetscFree(indices);CHKERRQ(ierr); 7121 PetscFunctionReturn(0); 7122 } 7123 7124 #undef __FUNCT__ 7125 #define __FUNCT__ "DMPlexCreateSection" 7126 /*@C 7127 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7128 7129 Not Collective 7130 7131 Input Parameters: 7132 + dm - The DMPlex object 7133 . dim - The spatial dimension of the problem 7134 . numFields - The number of fields in the problem 7135 . numComp - An array of size numFields that holds the number of components for each field 7136 . 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 . numBC - The number of boundary conditions 7138 . bcField - An array of size numBC giving the field number for each boundry condition 7139 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7140 7141 Output Parameter: 7142 . section - The PetscSection object 7143 7144 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 nubmer of dof for field 0 on each edge. 7146 7147 Level: developer 7148 7149 .keywords: mesh, elements 7150 .seealso: DMPlexCreate(), PetscSectionCreate() 7151 @*/ 7152 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 PetscErrorCode ierr; 7154 7155 PetscFunctionBegin; 7156 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7157 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7158 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7159 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7160 { 7161 PetscBool view = PETSC_FALSE; 7162 7163 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7164 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7165 } 7166 PetscFunctionReturn(0); 7167 } 7168 7169 #undef __FUNCT__ 7170 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7171 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) { 7172 PetscSection section; 7173 PetscErrorCode ierr; 7174 7175 PetscFunctionBegin; 7176 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7177 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 7178 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7179 PetscFunctionReturn(0); 7180 } 7181 7182 #undef __FUNCT__ 7183 #define __FUNCT__ "DMPlexGetCoordinateSection" 7184 /*@ 7185 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7186 7187 Not Collective 7188 7189 Input Parameter: 7190 . dm - The DMPlex object 7191 7192 Output Parameter: 7193 . section - The PetscSection object 7194 7195 Level: intermediate 7196 7197 .keywords: mesh, coordinates 7198 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7199 @*/ 7200 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) { 7201 DM cdm; 7202 PetscErrorCode ierr; 7203 7204 PetscFunctionBegin; 7205 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7206 PetscValidPointer(section, 2); 7207 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7208 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7209 PetscFunctionReturn(0); 7210 } 7211 7212 #undef __FUNCT__ 7213 #define __FUNCT__ "DMPlexSetCoordinateSection" 7214 /*@ 7215 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7216 7217 Not Collective 7218 7219 Input Parameters: 7220 + dm - The DMPlex object 7221 - section - The PetscSection object 7222 7223 Level: intermediate 7224 7225 .keywords: mesh, coordinates 7226 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7227 @*/ 7228 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) { 7229 DM cdm; 7230 PetscErrorCode ierr; 7231 7232 PetscFunctionBegin; 7233 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7234 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7235 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7236 PetscFunctionReturn(0); 7237 } 7238 7239 #undef __FUNCT__ 7240 #define __FUNCT__ "DMPlexGetConeSection" 7241 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) { 7242 DM_Plex *mesh = (DM_Plex *) dm->data; 7243 7244 PetscFunctionBegin; 7245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7246 if (section) *section = mesh->coneSection; 7247 PetscFunctionReturn(0); 7248 } 7249 7250 #undef __FUNCT__ 7251 #define __FUNCT__ "DMPlexGetCones" 7252 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) { 7253 DM_Plex *mesh = (DM_Plex *) dm->data; 7254 7255 PetscFunctionBegin; 7256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7257 if (cones) *cones = mesh->cones; 7258 PetscFunctionReturn(0); 7259 } 7260 7261 #undef __FUNCT__ 7262 #define __FUNCT__ "DMPlexGetConeOrientations" 7263 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) { 7264 DM_Plex *mesh = (DM_Plex *) dm->data; 7265 7266 PetscFunctionBegin; 7267 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7268 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7269 PetscFunctionReturn(0); 7270 } 7271 7272 #undef __FUNCT__ 7273 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7274 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7275 { 7276 const PetscInt embedDim = 2; 7277 PetscReal v0[2], J[4], invJ[4], detJ; 7278 PetscErrorCode ierr; 7279 7280 PetscFunctionBegin; 7281 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7282 PetscReal xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]); 7283 PetscReal eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]); 7284 7285 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 7286 *cell = c; 7287 } else { 7288 *cell = -1; 7289 } 7290 PetscFunctionReturn(0); 7291 } 7292 7293 #undef __FUNCT__ 7294 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7295 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7296 { 7297 PetscSection coordSection; 7298 Vec coordsLocal; 7299 const PetscScalar *coords; 7300 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7301 PetscInt crossings = 0, f; 7302 PetscErrorCode ierr; 7303 7304 PetscFunctionBegin; 7305 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7306 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7307 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7308 for(f = 0; f < 4; ++f) { 7309 PetscReal x_i = coords[faces[2*f+0]*2+0]; 7310 PetscReal y_i = coords[faces[2*f+0]*2+1]; 7311 PetscReal x_j = coords[faces[2*f+1]*2+0]; 7312 PetscReal y_j = coords[faces[2*f+1]*2+1]; 7313 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7314 PetscBool cond1 = (x_i <= point[0]) && (point[0] < x_j) ? PETSC_TRUE : PETSC_FALSE; 7315 PetscBool cond2 = (x_j <= point[0]) && (point[0] < x_i) ? PETSC_TRUE : PETSC_FALSE; 7316 PetscBool above = (point[1] < slope * (point[0] - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7317 if ((cond1 || cond2) && above) ++crossings; 7318 } 7319 if (crossings % 2) { 7320 *cell = c; 7321 } else { 7322 *cell = -1; 7323 } 7324 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7325 PetscFunctionReturn(0); 7326 } 7327 7328 #undef __FUNCT__ 7329 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7330 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7331 { 7332 const PetscInt embedDim = 3; 7333 PetscReal v0[3], J[9], invJ[9], detJ; 7334 PetscErrorCode ierr; 7335 7336 PetscFunctionBegin; 7337 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7338 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 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 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 7342 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 7343 *cell = c; 7344 } else { 7345 *cell = -1; 7346 } 7347 PetscFunctionReturn(0); 7348 } 7349 7350 #undef __FUNCT__ 7351 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7352 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7353 { 7354 PetscSection coordSection; 7355 Vec coordsLocal; 7356 const PetscScalar *coords; 7357 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7358 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7359 PetscBool found = PETSC_TRUE; 7360 PetscInt f; 7361 PetscErrorCode ierr; 7362 7363 PetscFunctionBegin; 7364 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7365 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7366 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7367 for(f = 0; f < 6; ++f) { 7368 /* Check the point is under plane */ 7369 /* Get face normal */ 7370 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 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 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 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 PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7375 /* Check that projected point is in face (2D location problem) */ 7376 if (dot < 0.0) { 7377 found = PETSC_FALSE; 7378 break; 7379 } 7380 } 7381 if (found) { 7382 *cell = c; 7383 } else { 7384 *cell = -1; 7385 } 7386 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7387 PetscFunctionReturn(0); 7388 } 7389 7390 #undef __FUNCT__ 7391 #define __FUNCT__ "DMLocatePoints_Plex" 7392 /* 7393 Need to implement using the guess 7394 */ 7395 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7396 { 7397 PetscInt cell = -1/*, guess = -1*/; 7398 PetscInt bs, numPoints, p; 7399 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7400 PetscInt *cells; 7401 PetscScalar *a; 7402 PetscErrorCode ierr; 7403 7404 PetscFunctionBegin; 7405 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7406 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7407 ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr); 7408 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7409 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7410 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7411 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 numPoints /= bs; 7413 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7414 for(p = 0; p < numPoints; ++p) { 7415 const PetscScalar *point = &a[p*bs]; 7416 7417 switch(dim) { 7418 case 2: 7419 for(c = cStart; c < cEnd; ++c) { 7420 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7421 switch(coneSize) { 7422 case 3: 7423 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7424 break; 7425 case 4: 7426 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7427 break; 7428 default: 7429 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7430 } 7431 if (cell >= 0) break; 7432 } 7433 break; 7434 case 3: 7435 for(c = cStart; c < cEnd; ++c) { 7436 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7437 switch(coneSize) { 7438 case 4: 7439 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7440 break; 7441 case 8: 7442 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7443 break; 7444 default: 7445 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7446 } 7447 if (cell >= 0) break; 7448 } 7449 break; 7450 default: 7451 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 7452 } 7453 cells[p] = cell; 7454 } 7455 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 7456 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 7457 PetscFunctionReturn(0); 7458 } 7459 7460 /******************************** FEM Support **********************************/ 7461 7462 #undef __FUNCT__ 7463 #define __FUNCT__ "DMPlexVecGetClosure" 7464 /*@C 7465 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 7466 7467 Not collective 7468 7469 Input Parameters: 7470 + dm - The DM 7471 . section - The section describing the layout in v, or PETSC_NULL to use the default section 7472 . v - The local vector 7473 - point - The sieve point in the DM 7474 7475 Output Parameters: 7476 + csize - The number of values in the closure, or PETSC_NULL 7477 - values - The array of values, which is a borrowed array and should not be freed 7478 7479 Level: intermediate 7480 7481 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7482 @*/ 7483 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 7484 PetscScalar *array, *vArray; 7485 PetscInt *points = PETSC_NULL; 7486 PetscInt offsets[32]; 7487 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 7488 PetscErrorCode ierr; 7489 7490 PetscFunctionBegin; 7491 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7492 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7493 if (!section) { 7494 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7495 } 7496 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7497 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7498 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7499 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7500 /* Compress out points not in the section */ 7501 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7502 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7503 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7504 points[q*2] = points[p]; 7505 points[q*2+1] = points[p+1]; 7506 ++q; 7507 } 7508 } 7509 numPoints = q; 7510 for (p = 0, size = 0; p < numPoints*2; p += 2) { 7511 PetscInt dof, fdof; 7512 7513 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7514 for (f = 0; f < numFields; ++f) { 7515 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7516 offsets[f+1] += fdof; 7517 } 7518 size += dof; 7519 } 7520 for (f = 1; f < numFields; ++f) { 7521 offsets[f+1] += offsets[f]; 7522 } 7523 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 7524 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 7525 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 7526 for (p = 0; p < numPoints*2; p += 2) { 7527 PetscInt o = points[p+1]; 7528 PetscInt dof, off, d; 7529 PetscScalar *varr; 7530 7531 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7532 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 7533 varr = &vArray[off]; 7534 if (numFields) { 7535 PetscInt fdof, foff, fcomp, f, c; 7536 7537 for (f = 0, foff = 0; f < numFields; ++f) { 7538 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7539 if (o >= 0) { 7540 for (d = 0; d < fdof; ++d, ++offsets[f]) { 7541 array[offsets[f]] = varr[foff+d]; 7542 } 7543 } else { 7544 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7545 for (d = fdof/fcomp-1; d >= 0; --d) { 7546 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 7547 array[offsets[f]] = varr[foff+d*fcomp+c]; 7548 } 7549 } 7550 } 7551 foff += fdof; 7552 } 7553 } else { 7554 if (o >= 0) { 7555 for (d = 0; d < dof; ++d, ++offsets[0]) { 7556 array[offsets[0]] = varr[d]; 7557 } 7558 } else { 7559 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 7560 array[offsets[0]] = varr[d]; 7561 } 7562 } 7563 } 7564 } 7565 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7566 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 7567 if (csize) *csize = size; 7568 *values = array; 7569 PetscFunctionReturn(0); 7570 } 7571 7572 #undef __FUNCT__ 7573 #define __FUNCT__ "DMPlexVecRestoreClosure" 7574 /*@C 7575 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 7576 7577 Not collective 7578 7579 Input Parameters: 7580 + dm - The DM 7581 . section - The section describing the layout in v, or PETSC_NULL to use the default section 7582 . v - The local vector 7583 . point - The sieve point in the DM 7584 . csize - The number of values in the closure, or PETSC_NULL 7585 - values - The array of values, which is a borrowed array and should not be freed 7586 7587 Level: intermediate 7588 7589 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7590 @*/ 7591 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 7592 PetscInt size = 0; 7593 PetscErrorCode ierr; 7594 7595 PetscFunctionBegin; 7596 /* Should work without recalculating size */ 7597 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 7598 PetscFunctionReturn(0); 7599 } 7600 7601 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 7602 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 7603 7604 #undef __FUNCT__ 7605 #define __FUNCT__ "updatePoint_private" 7606 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 7607 { 7608 PetscInt cdof; /* The number of constraints on this point */ 7609 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7610 PetscScalar *a; 7611 PetscInt off, cind = 0, k; 7612 PetscErrorCode ierr; 7613 7614 PetscFunctionBegin; 7615 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7616 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 7617 a = &array[off]; 7618 if (!cdof || setBC) { 7619 if (orientation >= 0) { 7620 for (k = 0; k < dof; ++k) { 7621 fuse(&a[k], values[k]); 7622 } 7623 } else { 7624 for (k = 0; k < dof; ++k) { 7625 fuse(&a[k], values[dof-k-1]); 7626 } 7627 } 7628 } else { 7629 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7630 if (orientation >= 0) { 7631 for (k = 0; k < dof; ++k) { 7632 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7633 fuse(&a[k], values[k]); 7634 } 7635 } else { 7636 for (k = 0; k < dof; ++k) { 7637 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7638 fuse(&a[k], values[dof-k-1]); 7639 } 7640 } 7641 } 7642 PetscFunctionReturn(0); 7643 } 7644 7645 #undef __FUNCT__ 7646 #define __FUNCT__ "updatePointFields_private" 7647 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) { 7648 PetscScalar *a; 7649 PetscInt numFields, off, foff, f; 7650 PetscErrorCode ierr; 7651 7652 PetscFunctionBegin; 7653 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7654 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 7655 a = &array[off]; 7656 for (f = 0, foff = 0; f < numFields; ++f) { 7657 PetscInt fdof, fcomp, fcdof; 7658 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7659 PetscInt cind = 0, k, c; 7660 7661 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7662 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7663 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 7664 if (!fcdof || setBC) { 7665 if (orientation >= 0) { 7666 for (k = 0; k < fdof; ++k) { 7667 fuse(&a[foff+k], values[foffs[f]+k]); 7668 } 7669 } else { 7670 for (k = fdof/fcomp-1; k >= 0; --k) { 7671 for (c = 0; c < fcomp; ++c) { 7672 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7673 } 7674 } 7675 } 7676 } else { 7677 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7678 if (orientation >= 0) { 7679 for (k = 0; k < fdof; ++k) { 7680 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 7681 fuse(&a[foff+k], values[foffs[f]+k]); 7682 } 7683 } else { 7684 for (k = fdof/fcomp-1; k >= 0; --k) { 7685 for (c = 0; c < fcomp; ++c) { 7686 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 7687 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7688 } 7689 } 7690 } 7691 } 7692 foff += fdof; 7693 foffs[f] += fdof; 7694 } 7695 PetscFunctionReturn(0); 7696 } 7697 7698 #undef __FUNCT__ 7699 #define __FUNCT__ "DMPlexVecSetClosure" 7700 /*@C 7701 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 7702 7703 Not collective 7704 7705 Input Parameters: 7706 + dm - The DM 7707 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 7708 . v - The local vector 7709 . point - The sieve point in the DM 7710 . values - The array of values, which is a borrowed array and should not be freed 7711 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7712 7713 Level: intermediate 7714 7715 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 7716 @*/ 7717 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) { 7718 PetscScalar *array; 7719 PetscInt *points = PETSC_NULL; 7720 PetscInt offsets[32]; 7721 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 7722 PetscErrorCode ierr; 7723 7724 PetscFunctionBegin; 7725 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7726 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7727 if (!section) { 7728 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7729 } 7730 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7731 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7732 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7733 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7734 /* Compress out points not in the section */ 7735 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7736 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7737 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7738 points[q*2] = points[p]; 7739 points[q*2+1] = points[p+1]; 7740 ++q; 7741 } 7742 } 7743 numPoints = q; 7744 for (p = 0; p < numPoints*2; p += 2) { 7745 PetscInt fdof; 7746 7747 for (f = 0; f < numFields; ++f) { 7748 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7749 offsets[f+1] += fdof; 7750 } 7751 } 7752 for (f = 1; f < numFields; ++f) { 7753 offsets[f+1] += offsets[f]; 7754 } 7755 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 7756 if (numFields) { 7757 switch(mode) { 7758 case INSERT_VALUES: 7759 for (p = 0; p < numPoints*2; p += 2) { 7760 PetscInt o = points[p+1]; 7761 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 7762 } break; 7763 case INSERT_ALL_VALUES: 7764 for (p = 0; p < numPoints*2; p += 2) { 7765 PetscInt o = points[p+1]; 7766 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 7767 } break; 7768 case ADD_VALUES: 7769 for (p = 0; p < numPoints*2; p += 2) { 7770 PetscInt o = points[p+1]; 7771 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 7772 } break; 7773 case ADD_ALL_VALUES: 7774 for (p = 0; p < numPoints*2; p += 2) { 7775 PetscInt o = points[p+1]; 7776 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 7777 } break; 7778 default: 7779 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7780 } 7781 } else { 7782 switch(mode) { 7783 case INSERT_VALUES: 7784 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7785 PetscInt o = points[p+1]; 7786 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7787 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 7788 } break; 7789 case INSERT_ALL_VALUES: 7790 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7791 PetscInt o = points[p+1]; 7792 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7793 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 7794 } break; 7795 case ADD_VALUES: 7796 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7797 PetscInt o = points[p+1]; 7798 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7799 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 7800 } break; 7801 case ADD_ALL_VALUES: 7802 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7803 PetscInt o = points[p+1]; 7804 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7805 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 7806 } break; 7807 default: 7808 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7809 } 7810 } 7811 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7812 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 7813 PetscFunctionReturn(0); 7814 } 7815 7816 #undef __FUNCT__ 7817 #define __FUNCT__ "DMPlexPrintMatSetValues" 7818 PetscErrorCode DMPlexPrintMatSetValues(Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 7819 { 7820 PetscMPIInt rank; 7821 PetscInt i, j; 7822 PetscErrorCode ierr; 7823 7824 PetscFunctionBegin; 7825 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 7826 ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 7827 for (i = 0; i < numIndices; i++) { 7828 ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 7829 } 7830 for (i = 0; i < numIndices; i++) { 7831 ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]", rank);CHKERRQ(ierr); 7832 for (j = 0; j < numIndices; j++) { 7833 #ifdef PETSC_USE_COMPLEX 7834 ierr = PetscPrintf(PETSC_COMM_SELF, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 7835 #else 7836 ierr = PetscPrintf(PETSC_COMM_SELF, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 7837 #endif 7838 } 7839 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7840 } 7841 PetscFunctionReturn(0); 7842 } 7843 7844 #undef __FUNCT__ 7845 #define __FUNCT__ "indicesPoint_private" 7846 /* . off - The global offset of this point */ 7847 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 7848 PetscInt cdof; /* The number of constraints on this point */ 7849 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7850 PetscInt cind = 0, k; 7851 PetscErrorCode ierr; 7852 7853 PetscFunctionBegin; 7854 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 7855 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7856 if (!cdof || setBC) { 7857 if (orientation >= 0) { 7858 for (k = 0; k < dof; ++k) { 7859 indices[k] = off+k; 7860 } 7861 } else { 7862 for (k = 0; k < dof; ++k) { 7863 indices[dof-k-1] = off+k; 7864 } 7865 } 7866 } else { 7867 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7868 if (orientation >= 0) { 7869 for (k = 0; k < dof; ++k) { 7870 if ((cind < cdof) && (k == cdofs[cind])) { 7871 /* Insert check for returning constrained indices */ 7872 indices[k] = -(off+k+1); 7873 ++cind; 7874 } else { 7875 indices[k] = off+k-cind; 7876 } 7877 } 7878 } else { 7879 for (k = 0; k < dof; ++k) { 7880 if ((cind < cdof) && (k == cdofs[cind])) { 7881 /* Insert check for returning constrained indices */ 7882 indices[dof-k-1] = -(off+k+1); 7883 ++cind; 7884 } else { 7885 indices[dof-k-1] = off+k-cind; 7886 } 7887 } 7888 } 7889 } 7890 PetscFunctionReturn(0); 7891 } 7892 7893 #undef __FUNCT__ 7894 #define __FUNCT__ "indicesPointFields_private" 7895 /* . off - The global offset of this point */ 7896 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 7897 PetscInt numFields, foff, f; 7898 PetscErrorCode ierr; 7899 7900 PetscFunctionBegin; 7901 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7902 for (f = 0, foff = 0; f < numFields; ++f) { 7903 PetscInt fdof, fcomp, cfdof; 7904 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7905 PetscInt cind = 0, k, c; 7906 7907 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7908 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7909 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 7910 if (!cfdof || setBC) { 7911 if (orientation >= 0) { 7912 for (k = 0; k < fdof; ++k) { 7913 indices[foffs[f]+k] = off+foff+k; 7914 } 7915 } else { 7916 for (k = fdof/fcomp-1; k >= 0; --k) { 7917 for (c = 0; c < fcomp; ++c) { 7918 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 7919 } 7920 } 7921 } 7922 } else { 7923 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7924 if (orientation >= 0) { 7925 for (k = 0; k < fdof; ++k) { 7926 if ((cind < cfdof) && (k == fcdofs[cind])) { 7927 indices[foffs[f]+k] = -(off+foff+k+1); 7928 ++cind; 7929 } else { 7930 indices[foffs[f]+k] = off+foff+k-cind; 7931 } 7932 } 7933 } else { 7934 for (k = fdof/fcomp-1; k >= 0; --k) { 7935 for (c = 0; c < fcomp; ++c) { 7936 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 7937 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 7938 ++cind; 7939 } else { 7940 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 7941 } 7942 } 7943 } 7944 } 7945 } 7946 foff += fdof - cfdof; 7947 foffs[f] += fdof; 7948 } 7949 PetscFunctionReturn(0); 7950 } 7951 7952 #undef __FUNCT__ 7953 #define __FUNCT__ "DMPlexMatSetClosure" 7954 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 7955 { 7956 DM_Plex *mesh = (DM_Plex *) dm->data; 7957 PetscInt *points = PETSC_NULL; 7958 PetscInt *indices; 7959 PetscInt offsets[32]; 7960 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 7961 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 7962 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 7963 PetscErrorCode ierr; 7964 7965 PetscFunctionBegin; 7966 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7967 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 7968 if (useDefault) { 7969 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7970 } 7971 if (useGlobalDefault) { 7972 if (useDefault) { 7973 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 7974 } else { 7975 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7976 } 7977 } 7978 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7979 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7980 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7981 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7982 /* Compress out points not in the section */ 7983 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7984 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7985 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7986 points[q*2] = points[p]; 7987 points[q*2+1] = points[p+1]; 7988 ++q; 7989 } 7990 } 7991 numPoints = q; 7992 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 7993 PetscInt fdof; 7994 7995 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7996 for (f = 0; f < numFields; ++f) { 7997 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7998 offsets[f+1] += fdof; 7999 } 8000 numIndices += dof; 8001 } 8002 for (f = 1; f < numFields; ++f) { 8003 offsets[f+1] += offsets[f]; 8004 } 8005 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8006 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8007 if (numFields) { 8008 for (p = 0; p < numPoints*2; p += 2) { 8009 PetscInt o = points[p+1]; 8010 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8011 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8012 } 8013 } else { 8014 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8015 PetscInt o = points[p+1]; 8016 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8017 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8018 } 8019 } 8020 if (useGlobalDefault && !useDefault) { 8021 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8022 } 8023 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(A, point, numIndices, indices, values);CHKERRQ(ierr);} 8024 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8025 if (ierr) { 8026 PetscMPIInt rank; 8027 PetscErrorCode ierr2; 8028 8029 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8030 ierr2 = PetscPrintf(PETSC_COMM_SELF, "[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8031 ierr2 = DMPlexPrintMatSetValues(A, point, numIndices, indices, values);CHKERRQ(ierr2); 8032 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8033 CHKERRQ(ierr); 8034 } 8035 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8036 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8037 PetscFunctionReturn(0); 8038 } 8039 8040 #undef __FUNCT__ 8041 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8042 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8043 { 8044 PetscSection coordSection; 8045 Vec coordinates; 8046 const PetscScalar *coords; 8047 const PetscInt dim = 2; 8048 PetscInt d, f; 8049 PetscErrorCode ierr; 8050 8051 PetscFunctionBegin; 8052 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8053 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8054 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8055 if (v0) { 8056 for (d = 0; d < dim; d++) { 8057 v0[d] = PetscRealPart(coords[d]); 8058 } 8059 } 8060 if (J) { 8061 for (d = 0; d < dim; d++) { 8062 for (f = 0; f < dim; f++) { 8063 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8064 } 8065 } 8066 *detJ = J[0]*J[3] - J[1]*J[2]; 8067 #if 0 8068 if (detJ < 0.0) { 8069 const PetscReal xLength = mesh->periodicity[0]; 8070 8071 if (xLength != 0.0) { 8072 PetscReal v0x = coords[0*dim+0]; 8073 8074 if (v0x == 0.0) { 8075 v0x = v0[0] = xLength; 8076 } 8077 for (f = 0; f < dim; f++) { 8078 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8079 8080 J[0*dim+f] = 0.5*(px - v0x); 8081 } 8082 } 8083 detJ = J[0]*J[3] - J[1]*J[2]; 8084 } 8085 #endif 8086 PetscLogFlops(8.0 + 3.0); 8087 } 8088 if (invJ) { 8089 const PetscReal invDet = 1.0/(*detJ); 8090 8091 invJ[0] = invDet*J[3]; 8092 invJ[1] = -invDet*J[1]; 8093 invJ[2] = -invDet*J[2]; 8094 invJ[3] = invDet*J[0]; 8095 PetscLogFlops(5.0); 8096 } 8097 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8098 PetscFunctionReturn(0); 8099 } 8100 8101 #undef __FUNCT__ 8102 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8103 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8104 { 8105 PetscSection coordSection; 8106 Vec coordinates; 8107 const PetscScalar *coords; 8108 const PetscInt dim = 2; 8109 PetscInt d, f; 8110 PetscErrorCode ierr; 8111 8112 PetscFunctionBegin; 8113 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8114 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8115 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8116 if (v0) { 8117 for (d = 0; d < dim; d++) { 8118 v0[d] = PetscRealPart(coords[d]); 8119 } 8120 } 8121 if (J) { 8122 for (d = 0; d < dim; d++) { 8123 for (f = 0; f < dim; f++) { 8124 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8125 } 8126 } 8127 *detJ = J[0]*J[3] - J[1]*J[2]; 8128 PetscLogFlops(8.0 + 3.0); 8129 } 8130 if (invJ) { 8131 const PetscReal invDet = 1.0/(*detJ); 8132 8133 invJ[0] = invDet*J[3]; 8134 invJ[1] = -invDet*J[1]; 8135 invJ[2] = -invDet*J[2]; 8136 invJ[3] = invDet*J[0]; 8137 PetscLogFlops(5.0); 8138 } 8139 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8140 PetscFunctionReturn(0); 8141 } 8142 8143 #undef __FUNCT__ 8144 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8145 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8146 { 8147 PetscSection coordSection; 8148 Vec coordinates; 8149 const PetscScalar *coords; 8150 const PetscInt dim = 3; 8151 PetscInt d, f; 8152 PetscErrorCode ierr; 8153 8154 PetscFunctionBegin; 8155 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8156 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8157 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8158 if (v0) { 8159 for (d = 0; d < dim; d++) { 8160 v0[d] = PetscRealPart(coords[d]); 8161 } 8162 } 8163 if (J) { 8164 for (d = 0; d < dim; d++) { 8165 for (f = 0; f < dim; f++) { 8166 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8167 } 8168 } 8169 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8170 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8171 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8172 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8173 PetscLogFlops(18.0 + 12.0); 8174 } 8175 if (invJ) { 8176 const PetscReal invDet = -1.0/(*detJ); 8177 8178 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8179 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8180 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8181 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8182 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8183 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8184 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8185 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8186 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8187 PetscLogFlops(37.0); 8188 } 8189 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8190 PetscFunctionReturn(0); 8191 } 8192 8193 #undef __FUNCT__ 8194 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8195 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8196 { 8197 PetscSection coordSection; 8198 Vec coordinates; 8199 const PetscScalar *coords; 8200 const PetscInt dim = 3; 8201 PetscInt d; 8202 PetscErrorCode ierr; 8203 8204 PetscFunctionBegin; 8205 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8206 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8207 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8208 if (v0) { 8209 for (d = 0; d < dim; d++) { 8210 v0[d] = PetscRealPart(coords[d]); 8211 } 8212 } 8213 if (J) { 8214 for (d = 0; d < dim; d++) { 8215 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8216 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8217 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8218 } 8219 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8220 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8221 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8222 PetscLogFlops(18.0 + 12.0); 8223 } 8224 if (invJ) { 8225 const PetscReal invDet = -1.0/(*detJ); 8226 8227 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8228 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8229 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8230 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8231 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8232 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8233 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8234 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8235 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8236 PetscLogFlops(37.0); 8237 } 8238 *detJ *= 8.0; 8239 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8240 PetscFunctionReturn(0); 8241 } 8242 8243 #undef __FUNCT__ 8244 #define __FUNCT__ "DMPlexComputeCellGeometry" 8245 /*@C 8246 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8247 8248 Collective on DM 8249 8250 Input Arguments: 8251 + dm - the DM 8252 - cell - the cell 8253 8254 Output Arguments: 8255 + v0 - the translation part of this affine transform 8256 . J - the Jacobian of the transform to the reference element 8257 . invJ - the inverse of the Jacobian 8258 - detJ - the Jacobian determinant 8259 8260 Level: advanced 8261 8262 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8263 @*/ 8264 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) { 8265 PetscInt dim, maxConeSize; 8266 PetscErrorCode ierr; 8267 8268 PetscFunctionBegin; 8269 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8270 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 8271 switch(dim) { 8272 case 2: 8273 switch(maxConeSize) { 8274 case 3: 8275 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8276 break; 8277 case 4: 8278 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8279 break; 8280 default: 8281 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize); 8282 } 8283 break; 8284 case 3: 8285 switch(maxConeSize) { 8286 case 4: 8287 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8288 break; 8289 case 8: 8290 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8291 break; 8292 default: 8293 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize); 8294 } 8295 break; 8296 default: 8297 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8298 } 8299 PetscFunctionReturn(0); 8300 } 8301 8302 #undef __FUNCT__ 8303 #define __FUNCT__ "DMPlexGetFaceOrientation" 8304 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) { 8305 MPI_Comm comm = ((PetscObject) dm)->comm; 8306 PetscBool posOrient = PETSC_FALSE; 8307 const PetscInt debug = 0; 8308 PetscInt cellDim, faceSize, f; 8309 PetscErrorCode ierr; 8310 8311 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 8312 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 8313 8314 if (cellDim == numCorners-1) { 8315 /* Simplices */ 8316 faceSize = numCorners-1; 8317 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 8318 } else if (cellDim == 1 && numCorners == 3) { 8319 /* Quadratic line */ 8320 faceSize = 1; 8321 posOrient = PETSC_TRUE; 8322 } else if (cellDim == 2 && numCorners == 4) { 8323 /* Quads */ 8324 faceSize = 2; 8325 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 8326 posOrient = PETSC_TRUE; 8327 } else if ((indices[0] == 3) && (indices[1] == 0)) { 8328 posOrient = PETSC_TRUE; 8329 } else { 8330 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 8331 posOrient = PETSC_FALSE; 8332 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 8333 } 8334 } else if (cellDim == 2 && numCorners == 6) { 8335 /* Quadratic triangle (I hate this) */ 8336 /* Edges are determined by the first 2 vertices (corners of edges) */ 8337 const PetscInt faceSizeTri = 3; 8338 PetscInt sortedIndices[3], i, iFace; 8339 PetscBool found = PETSC_FALSE; 8340 PetscInt faceVerticesTriSorted[9] = { 8341 0, 3, 4, /* bottom */ 8342 1, 4, 5, /* right */ 8343 2, 3, 5, /* left */ 8344 }; 8345 PetscInt faceVerticesTri[9] = { 8346 0, 3, 4, /* bottom */ 8347 1, 4, 5, /* right */ 8348 2, 5, 3, /* left */ 8349 }; 8350 8351 faceSize = faceSizeTri; 8352 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 8353 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 8354 for (iFace = 0; iFace < 3; ++iFace) { 8355 const PetscInt ii = iFace*faceSizeTri; 8356 PetscInt fVertex, cVertex; 8357 8358 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 8359 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 8360 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 8361 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 8362 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 8363 faceVertices[fVertex] = origVertices[cVertex]; 8364 break; 8365 } 8366 } 8367 } 8368 found = PETSC_TRUE; 8369 break; 8370 } 8371 } 8372 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 8373 if (posOriented) {*posOriented = PETSC_TRUE;} 8374 PetscFunctionReturn(0); 8375 } else if (cellDim == 2 && numCorners == 9) { 8376 /* Quadratic quad (I hate this) */ 8377 /* Edges are determined by the first 2 vertices (corners of edges) */ 8378 const PetscInt faceSizeQuad = 3; 8379 PetscInt sortedIndices[3], i, iFace; 8380 PetscBool found = PETSC_FALSE; 8381 PetscInt faceVerticesQuadSorted[12] = { 8382 0, 1, 4, /* bottom */ 8383 1, 2, 5, /* right */ 8384 2, 3, 6, /* top */ 8385 0, 3, 7, /* left */ 8386 }; 8387 PetscInt faceVerticesQuad[12] = { 8388 0, 1, 4, /* bottom */ 8389 1, 2, 5, /* right */ 8390 2, 3, 6, /* top */ 8391 3, 0, 7, /* left */ 8392 }; 8393 8394 faceSize = faceSizeQuad; 8395 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 8396 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 8397 for (iFace = 0; iFace < 4; ++iFace) { 8398 const PetscInt ii = iFace*faceSizeQuad; 8399 PetscInt fVertex, cVertex; 8400 8401 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 8402 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 8403 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 8404 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 8405 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 8406 faceVertices[fVertex] = origVertices[cVertex]; 8407 break; 8408 } 8409 } 8410 } 8411 found = PETSC_TRUE; 8412 break; 8413 } 8414 } 8415 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 8416 if (posOriented) {*posOriented = PETSC_TRUE;} 8417 PetscFunctionReturn(0); 8418 } else if (cellDim == 3 && numCorners == 8) { 8419 /* Hexes 8420 A hex is two oriented quads with the normal of the first 8421 pointing up at the second. 8422 8423 7---6 8424 /| /| 8425 4---5 | 8426 | 3-|-2 8427 |/ |/ 8428 0---1 8429 8430 Faces are determined by the first 4 vertices (corners of faces) */ 8431 const PetscInt faceSizeHex = 4; 8432 PetscInt sortedIndices[4], i, iFace; 8433 PetscBool found = PETSC_FALSE; 8434 PetscInt faceVerticesHexSorted[24] = { 8435 0, 1, 2, 3, /* bottom */ 8436 4, 5, 6, 7, /* top */ 8437 0, 1, 4, 5, /* front */ 8438 1, 2, 5, 6, /* right */ 8439 2, 3, 6, 7, /* back */ 8440 0, 3, 4, 7, /* left */ 8441 }; 8442 PetscInt faceVerticesHex[24] = { 8443 3, 2, 1, 0, /* bottom */ 8444 4, 5, 6, 7, /* top */ 8445 0, 1, 5, 4, /* front */ 8446 1, 2, 6, 5, /* right */ 8447 2, 3, 7, 6, /* back */ 8448 3, 0, 4, 7, /* left */ 8449 }; 8450 8451 faceSize = faceSizeHex; 8452 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 8453 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 8454 for (iFace = 0; iFace < 6; ++iFace) { 8455 const PetscInt ii = iFace*faceSizeHex; 8456 PetscInt fVertex, cVertex; 8457 8458 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 8459 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 8460 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 8461 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 8462 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 8463 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 8464 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 8465 faceVertices[fVertex] = origVertices[cVertex]; 8466 break; 8467 } 8468 } 8469 } 8470 found = PETSC_TRUE; 8471 break; 8472 } 8473 } 8474 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 8475 if (posOriented) {*posOriented = PETSC_TRUE;} 8476 PetscFunctionReturn(0); 8477 } else if (cellDim == 3 && numCorners == 10) { 8478 /* Quadratic tet */ 8479 /* Faces are determined by the first 3 vertices (corners of faces) */ 8480 const PetscInt faceSizeTet = 6; 8481 PetscInt sortedIndices[6], i, iFace; 8482 PetscBool found = PETSC_FALSE; 8483 PetscInt faceVerticesTetSorted[24] = { 8484 0, 1, 2, 6, 7, 8, /* bottom */ 8485 0, 3, 4, 6, 7, 9, /* front */ 8486 1, 4, 5, 7, 8, 9, /* right */ 8487 2, 3, 5, 6, 8, 9, /* left */ 8488 }; 8489 PetscInt faceVerticesTet[24] = { 8490 0, 1, 2, 6, 7, 8, /* bottom */ 8491 0, 4, 3, 6, 7, 9, /* front */ 8492 1, 5, 4, 7, 8, 9, /* right */ 8493 2, 3, 5, 8, 6, 9, /* left */ 8494 }; 8495 8496 faceSize = faceSizeTet; 8497 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 8498 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 8499 for (iFace=0; iFace < 4; ++iFace) { 8500 const PetscInt ii = iFace*faceSizeTet; 8501 PetscInt fVertex, cVertex; 8502 8503 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 8504 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 8505 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 8506 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 8507 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 8508 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 8509 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 8510 faceVertices[fVertex] = origVertices[cVertex]; 8511 break; 8512 } 8513 } 8514 } 8515 found = PETSC_TRUE; 8516 break; 8517 } 8518 } 8519 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 8520 if (posOriented) {*posOriented = PETSC_TRUE;} 8521 PetscFunctionReturn(0); 8522 } else if (cellDim == 3 && numCorners == 27) { 8523 /* Quadratic hexes (I hate this) 8524 A hex is two oriented quads with the normal of the first 8525 pointing up at the second. 8526 8527 7---6 8528 /| /| 8529 4---5 | 8530 | 3-|-2 8531 |/ |/ 8532 0---1 8533 8534 Faces are determined by the first 4 vertices (corners of faces) */ 8535 const PetscInt faceSizeQuadHex = 9; 8536 PetscInt sortedIndices[9], i, iFace; 8537 PetscBool found = PETSC_FALSE; 8538 PetscInt faceVerticesQuadHexSorted[54] = { 8539 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 8540 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 8541 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 8542 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 8543 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 8544 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 8545 }; 8546 PetscInt faceVerticesQuadHex[54] = { 8547 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 8548 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 8549 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 8550 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 8551 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 8552 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 8553 }; 8554 8555 faceSize = faceSizeQuadHex; 8556 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 8557 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 8558 for (iFace = 0; iFace < 6; ++iFace) { 8559 const PetscInt ii = iFace*faceSizeQuadHex; 8560 PetscInt fVertex, cVertex; 8561 8562 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 8563 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 8564 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 8565 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 8566 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 8567 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 8568 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 8569 faceVertices[fVertex] = origVertices[cVertex]; 8570 break; 8571 } 8572 } 8573 } 8574 found = PETSC_TRUE; 8575 break; 8576 } 8577 } 8578 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 8579 if (posOriented) {*posOriented = PETSC_TRUE;} 8580 PetscFunctionReturn(0); 8581 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 8582 if (!posOrient) { 8583 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 8584 for (f = 0; f < faceSize; ++f) { 8585 faceVertices[f] = origVertices[faceSize-1 - f]; 8586 } 8587 } else { 8588 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 8589 for (f = 0; f < faceSize; ++f) { 8590 faceVertices[f] = origVertices[f]; 8591 } 8592 } 8593 if (posOriented) {*posOriented = posOrient;} 8594 PetscFunctionReturn(0); 8595 } 8596 8597 #undef __FUNCT__ 8598 #define __FUNCT__ "DMPlexGetOrientedFace" 8599 /* 8600 Given a cell and a face, as a set of vertices, 8601 return the oriented face, as a set of vertices, in faceVertices 8602 The orientation is such that the face normal points out of the cell 8603 */ 8604 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 8605 { 8606 const PetscInt *cone = PETSC_NULL; 8607 PetscInt coneSize, v, f, v2; 8608 PetscInt oppositeVertex = -1; 8609 PetscErrorCode ierr; 8610 8611 PetscFunctionBegin; 8612 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8613 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 8614 for (v = 0, v2 = 0; v < coneSize; ++v) { 8615 PetscBool found = PETSC_FALSE; 8616 8617 for (f = 0; f < faceSize; ++f) { 8618 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 8619 } 8620 if (found) { 8621 indices[v2] = v; 8622 origVertices[v2] = cone[v]; 8623 ++v2; 8624 } else { 8625 oppositeVertex = v; 8626 } 8627 } 8628 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 8629 PetscFunctionReturn(0); 8630 } 8631 8632 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8633 { 8634 switch(i) { 8635 case 0: 8636 switch(j) { 8637 case 0: return 0; 8638 case 1: 8639 switch(k) { 8640 case 0: return 0; 8641 case 1: return 0; 8642 case 2: return 1; 8643 } 8644 case 2: 8645 switch(k) { 8646 case 0: return 0; 8647 case 1: return -1; 8648 case 2: return 0; 8649 } 8650 } 8651 case 1: 8652 switch(j) { 8653 case 0: 8654 switch(k) { 8655 case 0: return 0; 8656 case 1: return 0; 8657 case 2: return -1; 8658 } 8659 case 1: return 0; 8660 case 2: 8661 switch(k) { 8662 case 0: return 1; 8663 case 1: return 0; 8664 case 2: return 0; 8665 } 8666 } 8667 case 2: 8668 switch(j) { 8669 case 0: 8670 switch(k) { 8671 case 0: return 0; 8672 case 1: return 1; 8673 case 2: return 0; 8674 } 8675 case 1: 8676 switch(k) { 8677 case 0: return -1; 8678 case 1: return 0; 8679 case 2: return 0; 8680 } 8681 case 2: return 0; 8682 } 8683 } 8684 return 0; 8685 } 8686 8687 #undef __FUNCT__ 8688 #define __FUNCT__ "DMPlexCreateRigidBody" 8689 /*@C 8690 DMPlexCreateRigidBody - create rigid body modes from coordinates 8691 8692 Collective on DM 8693 8694 Input Arguments: 8695 + dm - the DM 8696 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 8697 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 8698 8699 Output Argument: 8700 . sp - the null space 8701 8702 Note: This is necessary to take account of Dirichlet conditions on the displacements 8703 8704 Level: advanced 8705 8706 .seealso: MatNullSpaceCreate() 8707 @*/ 8708 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8709 { 8710 MPI_Comm comm = ((PetscObject) dm)->comm; 8711 Vec coordinates, localMode, mode[6]; 8712 PetscSection coordSection; 8713 PetscScalar *coords; 8714 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8715 PetscErrorCode ierr; 8716 8717 PetscFunctionBegin; 8718 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8719 if (dim == 1) { 8720 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 8721 PetscFunctionReturn(0); 8722 } 8723 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8724 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8725 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8726 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8727 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8728 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8729 m = (dim*(dim+1))/2; 8730 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8731 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8732 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8733 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8734 /* Assume P1 */ 8735 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8736 for (d = 0; d < dim; ++d) { 8737 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8738 8739 values[d] = 1.0; 8740 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8741 for (v = vStart; v < vEnd; ++v) { 8742 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8743 } 8744 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8745 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8746 } 8747 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8748 for (d = dim; d < dim*(dim+1)/2; ++d) { 8749 PetscInt i, j, k = dim > 2 ? d - dim : d; 8750 8751 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8752 for (v = vStart; v < vEnd; ++v) { 8753 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8754 PetscInt off; 8755 8756 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8757 for (i = 0; i < dim; ++i) { 8758 for (j = 0; j < dim; ++j) { 8759 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8760 } 8761 } 8762 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8763 } 8764 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8765 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8766 } 8767 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8768 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8769 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 8770 /* Orthonormalize system */ 8771 for (i = dim; i < m; ++i) { 8772 PetscScalar dots[6]; 8773 8774 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8775 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8776 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8777 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 8778 } 8779 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8780 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8781 PetscFunctionReturn(0); 8782 } 8783 8784 #undef __FUNCT__ 8785 #define __FUNCT__ "DMPlexGetVTKBounds" 8786 PetscErrorCode DMPlexGetVTKBounds(DM dm, PetscInt *cMax, PetscInt *vMax) 8787 { 8788 DM_Plex *mesh = (DM_Plex *) dm->data; 8789 8790 PetscFunctionBegin; 8791 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8792 if (cMax) *cMax = mesh->vtkCellMax; 8793 if (vMax) *vMax = mesh->vtkVertexMax; 8794 PetscFunctionReturn(0); 8795 } 8796 8797 #undef __FUNCT__ 8798 #define __FUNCT__ "DMPlexSetVTKBounds" 8799 PetscErrorCode DMPlexSetVTKBounds(DM dm, PetscInt cMax, PetscInt vMax) 8800 { 8801 DM_Plex *mesh = (DM_Plex *) dm->data; 8802 8803 PetscFunctionBegin; 8804 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8805 if (cMax >= 0) mesh->vtkCellMax = cMax; 8806 if (vMax >= 0) mesh->vtkVertexMax = vMax; 8807 PetscFunctionReturn(0); 8808 } 8809 8810 #undef __FUNCT__ 8811 #define __FUNCT__ "DMPlexGetVTKCellHeight" 8812 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8813 { 8814 DM_Plex *mesh = (DM_Plex *) dm->data; 8815 8816 PetscFunctionBegin; 8817 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8818 PetscValidPointer(cellHeight, 2); 8819 *cellHeight = mesh->vtkCellHeight; 8820 PetscFunctionReturn(0); 8821 } 8822 8823 #undef __FUNCT__ 8824 #define __FUNCT__ "DMPlexSetVTKCellHeight" 8825 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8826 { 8827 DM_Plex *mesh = (DM_Plex *) dm->data; 8828 8829 PetscFunctionBegin; 8830 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8831 mesh->vtkCellHeight = cellHeight; 8832 PetscFunctionReturn(0); 8833 } 8834 8835 #undef __FUNCT__ 8836 #define __FUNCT__ "DMPlexInsertFace_Private" 8837 /* 8838 DMPlexInsertFace_Private - Puts a face into the mesh 8839 8840 Not collective 8841 8842 Input Parameters: 8843 + dm - The DMPlex 8844 . numFaceVertex - The number of vertices in the face 8845 . faceVertices - The vertices in the face for dm 8846 . subfaceVertices - The vertices in the face for subdm 8847 . numCorners - The number of vertices in the cell 8848 . cell - A cell in dm containing the face 8849 . subcell - A cell in subdm containing the face 8850 . firstFace - First face in the mesh 8851 - newFacePoint - Next face in the mesh 8852 8853 Output Parameters: 8854 . newFacePoint - Contains next face point number on input, updated on output 8855 8856 Level: developer 8857 */ 8858 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 { 8860 MPI_Comm comm = ((PetscObject) dm)->comm; 8861 DM_Plex *submesh = (DM_Plex *) subdm->data; 8862 const PetscInt *faces; 8863 PetscInt numFaces, coneSize; 8864 PetscErrorCode ierr; 8865 8866 PetscFunctionBegin; 8867 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 8868 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 8869 #if 0 8870 /* Cannot use this because support() has not been constructed yet */ 8871 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 8872 #else 8873 { 8874 PetscInt f; 8875 8876 numFaces = 0; 8877 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 8878 for(f = firstFace; f < *newFacePoint; ++f) { 8879 PetscInt dof, off, d; 8880 8881 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 8882 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 8883 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 8884 for(d = 0; d < dof; ++d) { 8885 const PetscInt p = submesh->cones[off+d]; 8886 PetscInt v; 8887 8888 for(v = 0; v < numFaceVertices; ++v) { 8889 if (subfaceVertices[v] == p) break; 8890 } 8891 if (v == numFaceVertices) break; 8892 } 8893 if (d == dof) { 8894 numFaces = 1; 8895 ((PetscInt *) faces)[0] = f; 8896 } 8897 } 8898 } 8899 #endif 8900 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 8901 else if (numFaces == 1) { 8902 /* Add the other cell neighbor for this face */ 8903 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 8904 } else { 8905 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 8906 PetscBool posOriented; 8907 8908 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 8909 origVertices = &orientedVertices[numFaceVertices]; 8910 indices = &orientedVertices[numFaceVertices*2]; 8911 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 8912 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 8913 /* TODO: I know that routine should return a permutation, not the indices */ 8914 for(v = 0; v < numFaceVertices; ++v) { 8915 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 8916 for(ov = 0; ov < numFaceVertices; ++ov) { 8917 if (orientedVertices[ov] == vertex) { 8918 orientedSubVertices[ov] = subvertex; 8919 break; 8920 } 8921 } 8922 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 8923 } 8924 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 8925 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 8926 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 8927 ++(*newFacePoint); 8928 } 8929 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 8930 PetscFunctionReturn(0); 8931 } 8932 8933 #undef __FUNCT__ 8934 #define __FUNCT__ "DMPlexCreateSubmesh" 8935 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 8936 { 8937 MPI_Comm comm = ((PetscObject) dm)->comm; 8938 DM_Plex *submesh; 8939 PetscBool boundaryFaces = PETSC_FALSE; 8940 PetscSection coordSection, subCoordSection; 8941 Vec coordinates, subCoordinates; 8942 PetscScalar *coords, *subCoords; 8943 IS labelIS; 8944 const PetscInt *subVertices; 8945 PetscInt *subVerticesActive, *tmpPoints; 8946 PetscInt *subCells = PETSC_NULL; 8947 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 8948 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 8949 PetscInt dim; /* Right now, do not specify dimension */ 8950 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 8951 PetscErrorCode ierr; 8952 8953 PetscFunctionBegin; 8954 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8955 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8956 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8957 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 8958 ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr); 8959 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 8960 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 8961 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 8962 subface = &face[maxConeSize]; 8963 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 8964 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 8965 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 8966 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 8967 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 8968 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 8969 maxSubCells = numSubVertices; 8970 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 8971 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 8972 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 8973 for(v = 0; v < numSubVertices; ++v) { 8974 const PetscInt vertex = subVertices[v]; 8975 PetscInt *star = PETSC_NULL; 8976 PetscInt starSize, numCells = 0; 8977 8978 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 8979 for(p = 0; p < starSize*2; p += 2) { 8980 const PetscInt point = star[p]; 8981 if ((point >= cStart) && (point < cEnd)) { 8982 star[numCells++] = point; 8983 } 8984 } 8985 numOldSubCells = numSubCells; 8986 for(c = 0; c < numCells; ++c) { 8987 const PetscInt cell = star[c]; 8988 PetscInt *closure = PETSC_NULL; 8989 PetscInt closureSize, numCorners = 0, faceSize = 0; 8990 PetscInt cellLoc; 8991 8992 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 8993 if (cellLoc >= 0) continue; 8994 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8995 for(p = 0; p < closureSize*2; p += 2) { 8996 const PetscInt point = closure[p]; 8997 if ((point >= vStart) && (point < vEnd)) { 8998 closure[numCorners++] = point; 8999 } 9000 } 9001 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9002 for(corner = 0; corner < numCorners; ++corner) { 9003 const PetscInt cellVertex = closure[corner]; 9004 PetscInt subVertex; 9005 9006 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9007 if (subVertex >= 0) { /* contains submesh vertex */ 9008 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9009 if (i == faceSize) { 9010 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9011 face[faceSize] = cellVertex; 9012 subface[faceSize] = subVertex; 9013 ++faceSize; 9014 } 9015 } 9016 } 9017 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9018 if (faceSize >= nFV) { 9019 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9020 if (numSubCells >= maxSubCells) { 9021 PetscInt *tmpCells; 9022 maxSubCells *= 2; 9023 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9024 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9025 ierr = PetscFree(subCells);CHKERRQ(ierr); 9026 subCells = tmpCells; 9027 } 9028 /* TOOD: Maybe overestimate then squeeze out empty faces */ 9029 if (faceSize > nFV) { 9030 /* TODO: This is tricky. Maybe just add all faces */ 9031 numSubFaces++; 9032 } else { 9033 numSubFaces++; 9034 } 9035 for(f = 0; f < faceSize; ++f) { 9036 subVerticesActive[subface[f]] = 1; 9037 } 9038 subCells[numSubCells++] = cell; 9039 } 9040 } 9041 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9042 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9043 } 9044 /* Pick out active subvertices */ 9045 for(v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9046 if (subVerticesActive[v]) { 9047 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9048 } 9049 } 9050 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9051 /* Set cone sizes */ 9052 firstSubVertex = numSubCells; 9053 firstSubFace = numSubCells+numSubVerticesActive; 9054 newFacePoint = firstSubFace; 9055 for(c = 0; c < numSubCells; ++c) { 9056 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 9057 } 9058 for(f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9059 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 9060 } 9061 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 9062 /* Create face cones */ 9063 for(c = 0; c < numSubCells; ++c) { 9064 const PetscInt cell = subCells[c]; 9065 PetscInt *closure = PETSC_NULL; 9066 PetscInt closureSize, numCorners = 0, faceSize = 0; 9067 9068 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9069 for(p = 0; p < closureSize*2; p += 2) { 9070 const PetscInt point = closure[p]; 9071 if ((point >= vStart) && (point < vEnd)) { 9072 closure[numCorners++] = point; 9073 } 9074 } 9075 for(corner = 0; corner < numCorners; ++corner) { 9076 const PetscInt cellVertex = closure[corner]; 9077 PetscInt subVertex; 9078 9079 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9080 if (subVertex >= 0) { /* contains submesh vertex */ 9081 for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9082 if (i == faceSize) { 9083 face[faceSize] = cellVertex; 9084 subface[faceSize] = numSubCells+subVertex; 9085 ++faceSize; 9086 } 9087 } 9088 } 9089 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9090 if (faceSize >= nFV) { 9091 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9092 // Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) 9093 // We have to take all the faces, and discard those in the interior 9094 // We check the join of the face vertices, which produces 2 cells if in the interior 9095 #if 0 9096 // This object just calls insert on each face that comes from subsets() 9097 // In fact, we can just always acll subsets(), since when we pass a single face it is a single call 9098 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9099 PointArray faceVec(face->begin(), face->end()); 9100 9101 subsets(faceVec, nFV, inserter); 9102 #endif 9103 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 9104 } 9105 } 9106 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 9107 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 9108 /* Build coordinates */ 9109 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9110 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9111 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 9112 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 9113 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 9114 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 9115 } 9116 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 9117 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 9118 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 9119 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 9120 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 9121 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9122 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9123 for(v = 0; v < numSubVerticesActive; ++v) { 9124 const PetscInt vertex = subVerticesActive[v]; 9125 const PetscInt subVertex = firstSubVertex+v; 9126 PetscInt dof, off, sdof, soff; 9127 9128 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 9129 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 9130 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 9131 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 9132 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 9133 for(d = 0; d < dof; ++d) { 9134 subCoords[soff+d] = coords[off+d]; 9135 } 9136 } 9137 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9138 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9139 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 9140 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 9141 9142 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 9143 /* Create map from submesh points to original mesh points */ 9144 submesh = (DM_Plex *) (*subdm)->data; 9145 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 9146 for(c = 0; c < numSubCells; ++c) { 9147 tmpPoints[c] = subCells[c]; 9148 } 9149 for(v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 9150 tmpPoints[v] = subVerticesActive[v-numSubCells]; 9151 } 9152 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 9153 9154 ierr = PetscFree(subCells);CHKERRQ(ierr); 9155 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 9156 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 9157 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 9158 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9159 PetscFunctionReturn(0); 9160 } 9161 9162 #undef __FUNCT__ 9163 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9164 /* We can easily have a form that takes an IS instead */ 9165 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9166 { 9167 PetscSection section, globalSection; 9168 PetscInt *numbers, p; 9169 PetscErrorCode ierr; 9170 9171 PetscFunctionBegin; 9172 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9173 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9174 for(p = pStart; p < pEnd; ++p) { 9175 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9176 } 9177 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9178 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9179 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9180 for(p = pStart; p < pEnd; ++p) { 9181 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9182 } 9183 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9184 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9185 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9186 PetscFunctionReturn(0); 9187 } 9188 9189 #undef __FUNCT__ 9190 #define __FUNCT__ "DMPlexGetCellNumbering" 9191 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9192 { 9193 DM_Plex *mesh = (DM_Plex *) dm->data; 9194 PetscInt cellHeight, cStart, cEnd, cMax; 9195 PetscErrorCode ierr; 9196 9197 PetscFunctionBegin; 9198 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9199 if (!mesh->globalCellNumbers) { 9200 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9201 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9202 ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr); 9203 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9204 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9205 } 9206 *globalCellNumbers = mesh->globalCellNumbers; 9207 PetscFunctionReturn(0); 9208 } 9209 9210 #undef __FUNCT__ 9211 #define __FUNCT__ "DMPlexGetVertexNumbering" 9212 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9213 { 9214 DM_Plex *mesh = (DM_Plex *) dm->data; 9215 PetscInt vStart, vEnd, vMax; 9216 PetscErrorCode ierr; 9217 9218 PetscFunctionBegin; 9219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9220 if (!mesh->globalVertexNumbers) { 9221 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9222 ierr = DMPlexGetVTKBounds(dm, PETSC_NULL, &vMax);CHKERRQ(ierr); 9223 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9224 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9225 } 9226 *globalVertexNumbers = mesh->globalVertexNumbers; 9227 PetscFunctionReturn(0); 9228 } 9229 9230 #undef __FUNCT__ 9231 #define __FUNCT__ "DMPlexGetSubpointMap" 9232 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 9233 { 9234 DM_Plex *mesh = (DM_Plex *) dm->data; 9235 9236 PetscFunctionBegin; 9237 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9238 PetscValidPointer(subpointMap, 2); 9239 *subpointMap = mesh->subpointMap; 9240 PetscFunctionReturn(0); 9241 } 9242 9243 #undef __FUNCT__ 9244 #define __FUNCT__ "DMPlexSetSubpointMap" 9245 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 9246 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 9247 { 9248 DM_Plex *mesh = (DM_Plex *) dm->data; 9249 9250 PetscFunctionBegin; 9251 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9252 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 9253 mesh->subpointMap = subpointMap; 9254 PetscFunctionReturn(0); 9255 } 9256 9257 #undef __FUNCT__ 9258 #define __FUNCT__ "DMPlexGetScale" 9259 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9260 { 9261 DM_Plex *mesh = (DM_Plex *) dm->data; 9262 9263 PetscFunctionBegin; 9264 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9265 PetscValidPointer(scale, 3); 9266 *scale = mesh->scale[unit]; 9267 PetscFunctionReturn(0); 9268 } 9269 9270 #undef __FUNCT__ 9271 #define __FUNCT__ "DMPlexSetScale" 9272 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9273 { 9274 DM_Plex *mesh = (DM_Plex *) dm->data; 9275 9276 PetscFunctionBegin; 9277 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9278 mesh->scale[unit] = scale; 9279 PetscFunctionReturn(0); 9280 } 9281 9282 9283 /******************************************************************************* 9284 This should be in a separate Discretization object, but I am not sure how to lay 9285 it out yet, so I am stuffing things here while I experiment. 9286 *******************************************************************************/ 9287 #undef __FUNCT__ 9288 #define __FUNCT__ "DMPlexSetFEMIntegration" 9289 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9290 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9291 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9292 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9293 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9294 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9295 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9296 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9297 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9298 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9299 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9300 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9301 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9302 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9303 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9304 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9305 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9306 { 9307 DM_Plex *mesh = (DM_Plex *) dm->data; 9308 9309 PetscFunctionBegin; 9310 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9311 mesh->integrateResidualFEM = integrateResidualFEM; 9312 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9313 mesh->integrateJacobianFEM = integrateJacobianFEM; 9314 PetscFunctionReturn(0); 9315 } 9316 9317 #undef __FUNCT__ 9318 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9319 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9320 { 9321 Vec coordinates; 9322 PetscSection section, cSection; 9323 PetscInt dim, vStart, vEnd, v, c, d; 9324 PetscScalar *values, *cArray; 9325 PetscReal *coords; 9326 PetscErrorCode ierr; 9327 9328 PetscFunctionBegin; 9329 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9330 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9331 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9332 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9333 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9334 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9335 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9336 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9337 for (v = vStart; v < vEnd; ++v) { 9338 PetscInt dof, off; 9339 9340 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9341 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9342 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9343 for(d = 0; d < dof; ++d) { 9344 coords[d] = PetscRealPart(cArray[off+d]); 9345 } 9346 for(c = 0; c < numComp; ++c) { 9347 values[c] = (*funcs[c])(coords); 9348 } 9349 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9350 } 9351 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9352 /* Temporary, must be replaced by a projection on the finite element basis */ 9353 { 9354 PetscInt eStart = 0, eEnd = 0, e, depth; 9355 9356 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9357 --depth; 9358 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9359 for (e = eStart; e < eEnd; ++e) { 9360 const PetscInt *cone = PETSC_NULL; 9361 PetscInt coneSize, d; 9362 PetscScalar *coordsA, *coordsB; 9363 9364 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9365 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9366 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9367 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9368 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9369 for (d = 0; d < dim; ++d) { 9370 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9371 } 9372 for (c = 0; c < numComp; ++c) { 9373 values[c] = (*funcs[c])(coords); 9374 } 9375 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9376 } 9377 } 9378 9379 ierr = PetscFree(coords);CHKERRQ(ierr); 9380 ierr = PetscFree(values);CHKERRQ(ierr); 9381 #if 0 9382 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9383 PetscReal detJ; 9384 9385 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9386 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9387 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV((int) pow(this->_mesh->getSieve()->getMaxConeSize(), dim+1)+1, true); 9388 9389 for (PetscInt c = cStart; c < cEnd; ++c) { 9390 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9391 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9392 const int oSize = pV.getSize(); 9393 int v = 0; 9394 9395 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 9396 for (PetscInt cl = 0; cl < oSize; ++cl) { 9397 const PetscInt fDim; 9398 9399 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9400 if (pointDim) { 9401 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9402 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9403 } 9404 } 9405 } 9406 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 9407 pV.clear(); 9408 } 9409 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9410 ierr = PetscFree(values);CHKERRQ(ierr); 9411 #endif 9412 PetscFunctionReturn(0); 9413 } 9414 9415 #undef __FUNCT__ 9416 #define __FUNCT__ "DMPlexProjectFunction" 9417 /*@C 9418 DMPlexProjectFunction - This projects the given function into the function space provided. 9419 9420 Input Parameters: 9421 + dm - The DM 9422 . numComp - The number of components (functions) 9423 . funcs - The coordinate functions to evaluate 9424 - mode - The insertion mode for values 9425 9426 Output Parameter: 9427 . X - vector 9428 9429 Level: developer 9430 9431 Note: 9432 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9433 We will eventually fix it. 9434 9435 ,seealso: DMPlexComputeL2Diff() 9436 */ 9437 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9438 { 9439 Vec localX; 9440 PetscErrorCode ierr; 9441 9442 PetscFunctionBegin; 9443 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9444 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9445 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9446 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9447 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9448 PetscFunctionReturn(0); 9449 } 9450 9451 #undef __FUNCT__ 9452 #define __FUNCT__ "DMPlexComputeL2Diff" 9453 /*@C 9454 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9455 9456 Input Parameters: 9457 + dm - The DM 9458 . quad - The PetscQuadrature object for each field 9459 . funcs - The functions to evaluate for each field component 9460 - X - The coefficient vector u_h 9461 9462 Output Parameter: 9463 . diff - The diff ||u - u_h||_2 9464 9465 Level: developer 9466 9467 .seealso: DMPlexProjectFunction() 9468 */ 9469 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) { 9470 const PetscInt debug = 0; 9471 PetscSection section; 9472 Vec localX; 9473 PetscReal *coords, *v0, *J, *invJ, detJ; 9474 PetscReal localDiff = 0.0; 9475 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9476 PetscErrorCode ierr; 9477 9478 PetscFunctionBegin; 9479 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9480 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9481 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9482 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9483 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9484 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9485 for (field = 0; field < numFields; ++field) { 9486 numComponents += quad[field].numComponents; 9487 } 9488 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9489 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9490 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9491 for (c = cStart; c < cEnd; ++c) { 9492 const PetscScalar *x; 9493 PetscReal elemDiff = 0.0; 9494 9495 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9496 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9497 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9498 9499 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9500 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9501 const PetscReal *quadPoints = quad[field].quadPoints; 9502 const PetscReal *quadWeights = quad[field].quadWeights; 9503 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9504 const PetscInt numBasisComps = quad[field].numComponents; 9505 const PetscReal *basis = quad[field].basis; 9506 PetscInt q, d, e, fc, f; 9507 9508 if (debug) { 9509 char title[1024]; 9510 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9511 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9512 } 9513 for (q = 0; q < numQuadPoints; ++q) { 9514 for (d = 0; d < dim; d++) { 9515 coords[d] = v0[d]; 9516 for (e = 0; e < dim; e++) { 9517 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9518 } 9519 } 9520 for (fc = 0; fc < numBasisComps; ++fc) { 9521 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9522 PetscReal interpolant = 0.0; 9523 for (f = 0; f < numBasisFuncs; ++f) { 9524 const PetscInt fidx = f*numBasisComps+fc; 9525 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9526 } 9527 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 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9529 } 9530 } 9531 comp += numBasisComps; 9532 fieldOffset += numBasisFuncs*numBasisComps; 9533 } 9534 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9535 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9536 localDiff += elemDiff; 9537 } 9538 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9539 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9540 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9541 *diff = PetscSqrtReal(*diff); 9542 PetscFunctionReturn(0); 9543 } 9544 9545 #undef __FUNCT__ 9546 #define __FUNCT__ "DMPlexComputeResidualFEM" 9547 /*@ 9548 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9549 9550 Input Parameters: 9551 + dm - The mesh 9552 . X - Local input vector 9553 - user - The user context 9554 9555 Output Parameter: 9556 . F - Local output vector 9557 9558 Note: 9559 The second member of the user context must be an FEMContext. 9560 9561 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9562 like a GPU, or vectorize on a multicore machine. 9563 9564 .seealso: DMPlexComputeJacobianActionFEM() 9565 */ 9566 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9567 { 9568 DM_Plex *mesh = (DM_Plex *) dm->data; 9569 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9570 PetscQuadrature *quad = fem->quad; 9571 PetscSection section; 9572 PetscReal *v0, *J, *invJ, *detJ; 9573 PetscScalar *elemVec, *u; 9574 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9575 PetscInt cellDof = 0, numComponents = 0; 9576 PetscErrorCode ierr; 9577 9578 PetscFunctionBegin; 9579 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9580 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9581 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9582 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9583 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9584 numCells = cEnd - cStart; 9585 for (field = 0; field < numFields; ++field) { 9586 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9587 numComponents += quad[field].numComponents; 9588 } 9589 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9590 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9591 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 for (c = cStart; c < cEnd; ++c) { 9593 const PetscScalar *x; 9594 PetscInt i; 9595 9596 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9597 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9598 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9599 9600 for (i = 0; i < cellDof; ++i) { 9601 u[c*cellDof+i] = x[i]; 9602 } 9603 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9604 } 9605 for (field = 0; field < numFields; ++field) { 9606 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9607 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9608 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9609 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9610 /* Conforming batches */ 9611 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9612 PetscInt numBlocks = 1; 9613 PetscInt batchSize = numBlocks * blockSize; 9614 PetscInt numBatches = numBatchesTmp; 9615 PetscInt numChunks = numCells / (numBatches*batchSize); 9616 /* Remainder */ 9617 PetscInt numRemainder = numCells % (numBatches * batchSize); 9618 PetscInt offset = numCells - numRemainder; 9619 9620 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9621 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9622 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9623 } 9624 for (c = cStart; c < cEnd; ++c) { 9625 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9626 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9627 } 9628 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9629 if (mesh->printFEM) { 9630 PetscMPIInt rank, numProcs; 9631 PetscInt p; 9632 9633 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9634 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9635 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9636 for (p = 0; p < numProcs; ++p) { 9637 if (p == rank) { 9638 Vec f; 9639 9640 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9641 ierr = VecCopy(F, f);CHKERRQ(ierr); 9642 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9643 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9644 ierr = VecDestroy(&f);CHKERRQ(ierr); 9645 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9646 } 9647 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9648 } 9649 } 9650 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9651 PetscFunctionReturn(0); 9652 } 9653 9654 #undef __FUNCT__ 9655 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9656 /*@C 9657 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9658 9659 Input Parameters: 9660 + dm - The mesh 9661 . J - The Jacobian shell matrix 9662 . X - Local input vector 9663 - user - The user context 9664 9665 Output Parameter: 9666 . F - Local output vector 9667 9668 Note: 9669 The second member of the user context must be an FEMContext. 9670 9671 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9672 like a GPU, or vectorize on a multicore machine. 9673 9674 .seealso: DMPlexComputeResidualFEM() 9675 */ 9676 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9677 { 9678 DM_Plex *mesh = (DM_Plex *) dm->data; 9679 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9680 PetscQuadrature *quad = fem->quad; 9681 PetscSection section; 9682 JacActionCtx *jctx; 9683 PetscReal *v0, *J, *invJ, *detJ; 9684 PetscScalar *elemVec, *u, *a; 9685 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9686 PetscInt cellDof = 0; 9687 PetscErrorCode ierr; 9688 9689 PetscFunctionBegin; 9690 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9691 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9692 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9693 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9694 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9695 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9696 numCells = cEnd - cStart; 9697 for (field = 0; field < numFields; ++field) { 9698 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9699 } 9700 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9701 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 for (c = cStart; c < cEnd; ++c) { 9703 const PetscScalar *x; 9704 PetscInt i; 9705 9706 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9707 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9708 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9709 for (i = 0; i < cellDof; ++i) { 9710 u[c*cellDof+i] = x[i]; 9711 } 9712 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9713 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9714 for (i = 0; i < cellDof; ++i) { 9715 a[c*cellDof+i] = x[i]; 9716 } 9717 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9718 } 9719 for (field = 0; field < numFields; ++field) { 9720 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9721 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9722 /* Conforming batches */ 9723 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9724 PetscInt numBlocks = 1; 9725 PetscInt batchSize = numBlocks * blockSize; 9726 PetscInt numBatches = numBatchesTmp; 9727 PetscInt numChunks = numCells / (numBatches*batchSize); 9728 /* Remainder */ 9729 PetscInt numRemainder = numCells % (numBatches * batchSize); 9730 PetscInt offset = numCells - numRemainder; 9731 9732 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 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 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9735 } 9736 for (c = cStart; c < cEnd; ++c) { 9737 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9738 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9739 } 9740 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9741 if (mesh->printFEM) { 9742 PetscMPIInt rank, numProcs; 9743 PetscInt p; 9744 9745 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9746 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9747 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9748 for (p = 0; p < numProcs; ++p) { 9749 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9750 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9751 } 9752 } 9753 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9754 PetscFunctionReturn(0); 9755 } 9756 9757 #undef __FUNCT__ 9758 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9759 /*@ 9760 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9761 9762 Input Parameters: 9763 + dm - The mesh 9764 . X - Local input vector 9765 - user - The user context 9766 9767 Output Parameter: 9768 . Jac - Jacobian matrix 9769 9770 Note: 9771 The second member of the user context must be an FEMContext. 9772 9773 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9774 like a GPU, or vectorize on a multicore machine. 9775 9776 .seealso: FormFunctionLocal() 9777 */ 9778 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9779 { 9780 DM_Plex *mesh = (DM_Plex *) dm->data; 9781 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9782 PetscQuadrature *quad = fem->quad; 9783 PetscSection section; 9784 PetscReal *v0, *J, *invJ, *detJ; 9785 PetscScalar *elemMat, *u; 9786 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9787 PetscInt cellDof = 0, numComponents = 0; 9788 PetscBool isShell; 9789 PetscErrorCode ierr; 9790 9791 PetscFunctionBegin; 9792 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9793 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9794 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9795 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9796 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9797 numCells = cEnd - cStart; 9798 for (field = 0; field < numFields; ++field) { 9799 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9800 numComponents += quad[field].numComponents; 9801 } 9802 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9803 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9804 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 for (c = cStart; c < cEnd; ++c) { 9806 const PetscScalar *x; 9807 PetscInt i; 9808 9809 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9810 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9811 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9812 9813 for (i = 0; i < cellDof; ++i) { 9814 u[c*cellDof+i] = x[i]; 9815 } 9816 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9817 } 9818 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9819 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9820 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9821 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9822 PetscInt fieldJ; 9823 9824 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9825 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9826 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9827 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9828 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9829 /* Conforming batches */ 9830 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9831 PetscInt numBlocks = 1; 9832 PetscInt batchSize = numBlocks * blockSize; 9833 PetscInt numBatches = numBatchesTmp; 9834 PetscInt numChunks = numCells / (numBatches*batchSize); 9835 /* Remainder */ 9836 PetscInt numRemainder = numCells % (numBatches * batchSize); 9837 PetscInt offset = numCells - numRemainder; 9838 9839 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9840 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 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9842 } 9843 } 9844 for (c = cStart; c < cEnd; ++c) { 9845 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9846 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9847 } 9848 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9849 9850 /* Assemble matrix, using the 2-step process: 9851 MatAssemblyBegin(), MatAssemblyEnd(). */ 9852 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9853 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9854 9855 if (mesh->printFEM) { 9856 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9857 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9858 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9859 } 9860 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9861 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9862 if (isShell) { 9863 JacActionCtx *jctx; 9864 9865 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9866 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9867 } 9868 *str = SAME_NONZERO_PATTERN; 9869 PetscFunctionReturn(0); 9870 } 9871 9872 9873 #undef __FUNCT__ 9874 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9875 /*@C 9876 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9877 the local section and an SF describing the section point overlap. 9878 9879 Input Parameters: 9880 + s - The PetscSection for the local field layout 9881 . sf - The SF describing parallel layout of the section points 9882 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9883 . label - The label specifying the points 9884 - labelValue - The label stratum specifying the points 9885 9886 Output Parameter: 9887 . gsection - The PetscSection for the global field layout 9888 9889 Note: This gives negative sizes and offsets to points not owned by this process 9890 9891 Level: developer 9892 9893 .seealso: PetscSectionCreate() 9894 @*/ 9895 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9896 { 9897 PetscInt *neg; 9898 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9899 PetscErrorCode ierr; 9900 9901 PetscFunctionBegin; 9902 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9903 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9904 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9905 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9906 /* Mark ghost points with negative dof */ 9907 for (p = pStart; p < pEnd; ++p) { 9908 PetscInt value; 9909 9910 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9911 if (value != labelValue) continue; 9912 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9913 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9914 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9915 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9916 neg[p-pStart] = -(dof+1); 9917 } 9918 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9919 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 9920 if (nroots >= 0) { 9921 if (nroots > pEnd - pStart) { 9922 PetscInt *tmpDof; 9923 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9924 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9925 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9926 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9927 for (p = pStart; p < pEnd; ++p) { 9928 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 9929 } 9930 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9931 } else { 9932 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9933 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9934 } 9935 } 9936 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9937 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9938 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9939 (*gsection)->atlasOff[p] = off; 9940 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9941 } 9942 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9943 globalOff -= off; 9944 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9945 (*gsection)->atlasOff[p] += globalOff; 9946 neg[p] = -((*gsection)->atlasOff[p]+1); 9947 } 9948 /* Put in negative offsets for ghost points */ 9949 if (nroots >= 0) { 9950 if (nroots > pEnd - pStart) { 9951 PetscInt *tmpOff; 9952 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9953 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9954 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9955 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9956 for (p = pStart; p < pEnd; ++p) { 9957 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 9958 } 9959 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9960 } else { 9961 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9962 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9963 } 9964 } 9965 ierr = PetscFree(neg);CHKERRQ(ierr); 9966 PetscFunctionReturn(0); 9967 } 9968