1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/vecimpl.h> 4 #include <petsc-private/isimpl.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 8 9 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "VecView_Plex_Local" 14 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 15 { 16 DM dm; 17 PetscBool isvtk; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 22 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 23 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 24 if (isvtk) { 25 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 26 PetscSection section; 27 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 28 29 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 30 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 33 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 34 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 35 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 36 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 37 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 38 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 39 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 40 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 41 } else if (cdof && vdof) { 42 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 43 } else if (cdof) { 44 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 45 * vector or just happens to have the same number of dofs as the dimension. */ 46 if (cdof == dim) { 47 ft = PETSC_VTK_CELL_VECTOR_FIELD; 48 } else { 49 ft = PETSC_VTK_CELL_FIELD; 50 } 51 } else if (vdof) { 52 if (vdof == dim) { 53 ft = PETSC_VTK_POINT_VECTOR_FIELD; 54 } else { 55 ft = PETSC_VTK_POINT_FIELD; 56 } 57 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 58 59 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 61 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 62 } else { 63 PetscBool isseq; 64 65 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 66 if (isseq) { 67 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 68 } else { 69 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "VecView_Plex" 77 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 78 { 79 DM dm; 80 PetscBool isvtk; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 85 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 86 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 87 if (isvtk) { 88 Vec locv; 89 const char *name; 90 91 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 92 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 93 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 96 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 97 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 98 } else { 99 PetscBool isseq; 100 101 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 102 if (isseq) { 103 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 104 } else { 105 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexView_Ascii" 113 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 114 { 115 DM_Plex *mesh = (DM_Plex*) dm->data; 116 DM cdm; 117 DMLabel markers; 118 PetscSection coordSection; 119 Vec coordinates; 120 PetscViewerFormat format; 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 125 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 126 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 127 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 128 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 129 const char *name; 130 PetscInt maxConeSize, maxSupportSize; 131 PetscInt pStart, pEnd, p; 132 PetscMPIInt rank, size; 133 134 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 135 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 136 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 137 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 138 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 143 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 144 for (p = pStart; p < pEnd; ++p) { 145 PetscInt dof, off, s; 146 147 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 148 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 149 for (s = off; s < off+dof; ++s) { 150 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 151 } 152 } 153 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 154 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 155 for (p = pStart; p < pEnd; ++p) { 156 PetscInt dof, off, c; 157 158 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 159 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 160 for (c = off; c < off+dof; ++c) { 161 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 162 } 163 } 164 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 165 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 166 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 167 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 168 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 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(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");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(PetscObjectComm((PetscObject)dm), 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 = 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, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 284 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 285 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 286 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 287 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 288 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 289 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 290 if (depth == 1) { 291 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 292 pEnd = pEnd - pStart; 293 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 294 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 295 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 296 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 297 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 298 pEnd = pEnd - pStart; 299 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 300 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 301 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 302 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 303 } else { 304 for (d = 0; d <= dim; d++) { 305 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 306 pEnd = pEnd - pStart; 307 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 308 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 309 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 310 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 311 } 312 } 313 ierr = PetscFree(sizes);CHKERRQ(ierr); 314 } 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "DMView_Plex" 320 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 321 { 322 PetscBool iascii, isbinary; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 327 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 330 if (iascii) { 331 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 332 #if 0 333 } else if (isbinary) { 334 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 335 #endif 336 } 337 PetscFunctionReturn(0); 338 } 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "DMDestroy_Plex" 342 PetscErrorCode DMDestroy_Plex(DM dm) 343 { 344 DM_Plex *mesh = (DM_Plex*) dm->data; 345 DMLabel next = mesh->labels; 346 PetscErrorCode ierr; 347 348 PetscFunctionBegin; 349 if (--mesh->refct > 0) PetscFunctionReturn(0); 350 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 353 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 355 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 356 while (next) { 357 DMLabel tmp = next->next; 358 359 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 360 next = tmp; 361 } 362 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 364 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 365 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 366 ierr = PetscFree(mesh);CHKERRQ(ierr); 367 PetscFunctionReturn(0); 368 } 369 370 #undef __FUNCT__ 371 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 372 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 373 { 374 const PetscInt *support = NULL; 375 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 376 PetscErrorCode ierr; 377 378 PetscFunctionBegin; 379 if (useClosure) { 380 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 381 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 382 for (s = 0; s < supportSize; ++s) { 383 const PetscInt *cone = NULL; 384 PetscInt coneSize, c, q; 385 386 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 387 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 388 for (c = 0; c < coneSize; ++c) { 389 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 390 if (cone[c] == adj[q]) break; 391 } 392 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 393 } 394 } 395 } else { 396 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 397 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 398 for (s = 0; s < supportSize; ++s) { 399 const PetscInt *cone = NULL; 400 PetscInt coneSize, c, q; 401 402 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 403 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 404 for (c = 0; c < coneSize; ++c) { 405 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 406 if (cone[c] == adj[q]) break; 407 } 408 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 409 } 410 } 411 } 412 *adjSize = numAdj; 413 PetscFunctionReturn(0); 414 } 415 416 #undef __FUNCT__ 417 #define __FUNCT__ "DMPlexGetAdjacency_Private" 418 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 419 { 420 const PetscInt *star = tmpClosure; 421 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 422 PetscErrorCode ierr; 423 424 PetscFunctionBegin; 425 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 426 for (s = 2; s < starSize*2; s += 2) { 427 const PetscInt *closure = NULL; 428 PetscInt closureSize, c, q; 429 430 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 431 for (c = 0; c < closureSize*2; c += 2) { 432 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 433 if (closure[c] == adj[q]) break; 434 } 435 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 436 } 437 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 438 } 439 *adjSize = numAdj; 440 PetscFunctionReturn(0); 441 } 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 445 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 446 { 447 DM_Plex *mesh = (DM_Plex*) dm->data; 448 449 PetscFunctionBegin; 450 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 451 mesh->preallocCenterDim = preallocCenterDim; 452 PetscFunctionReturn(0); 453 } 454 455 #undef __FUNCT__ 456 #define __FUNCT__ "DMPlexPreallocateOperator" 457 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 458 { 459 DM_Plex *mesh = (DM_Plex*) dm->data; 460 MPI_Comm comm; 461 PetscSF sf, sfDof, sfAdj; 462 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 463 PetscInt nleaves, l, p; 464 const PetscInt *leaves; 465 const PetscSFNode *remotes; 466 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 467 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 468 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 469 PetscLayout rLayout; 470 PetscInt locRows, rStart, rEnd, r; 471 PetscMPIInt size; 472 PetscBool useClosure, debug = PETSC_FALSE; 473 PetscErrorCode ierr; 474 475 PetscFunctionBegin; 476 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 477 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 478 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 479 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 480 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 481 /* Create dof SF based on point SF */ 482 if (debug) { 483 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 487 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 488 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 489 } 490 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 491 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 492 if (debug) { 493 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 494 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 495 } 496 /* Create section for dof adjacency (dof ==> # adj dof) */ 497 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 498 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 499 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 500 if (mesh->preallocCenterDim == dim) { 501 useClosure = PETSC_FALSE; 502 } else if (mesh->preallocCenterDim == 0) { 503 useClosure = PETSC_TRUE; 504 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 505 506 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 507 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 510 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 511 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 512 /* Fill in the ghost dofs on the interface */ 513 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 514 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 515 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 516 517 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 518 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 519 520 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 521 522 /* 523 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 524 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 525 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 526 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 527 Create sfAdj connecting rootSectionAdj and leafSectionAdj 528 3. Visit unowned points on interface, write adjacencies to adj 529 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 530 4. Visit owned points on interface, write adjacencies to rootAdj 531 Remove redundancy in rootAdj 532 ** The last two traversals use transitive closure 533 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 534 Allocate memory addressed by sectionAdj (cols) 535 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 536 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 537 */ 538 539 for (l = 0; l < nleaves; ++l) { 540 PetscInt dof, off, d, q; 541 PetscInt p = leaves[l], numAdj = maxAdjSize; 542 543 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 544 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 545 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 546 for (q = 0; q < numAdj; ++q) { 547 PetscInt ndof, ncdof; 548 549 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 550 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 551 for (d = off; d < off+dof; ++d) { 552 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 553 } 554 } 555 } 556 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 557 if (debug) { 558 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 559 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 560 } 561 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 562 if (size > 1) { 563 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 564 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 565 } 566 if (debug) { 567 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 568 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 569 } 570 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 571 for (p = pStart; p < pEnd; ++p) { 572 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 573 574 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 575 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 576 if (!dof) continue; 577 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 578 if (adof <= 0) continue; 579 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 580 for (q = 0; q < numAdj; ++q) { 581 PetscInt ndof, ncdof; 582 583 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 584 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 585 for (d = off; d < off+dof; ++d) { 586 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 587 } 588 } 589 } 590 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 591 if (debug) { 592 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 593 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 594 } 595 /* Create adj SF based on dof SF */ 596 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 597 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 598 if (debug) { 599 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 600 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 601 } 602 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 603 /* Create leaf adjacency */ 604 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 605 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 606 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 607 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 608 for (l = 0; l < nleaves; ++l) { 609 PetscInt dof, off, d, q; 610 PetscInt p = leaves[l], numAdj = maxAdjSize; 611 612 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 613 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 614 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 615 for (d = off; d < off+dof; ++d) { 616 PetscInt aoff, i = 0; 617 618 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 619 for (q = 0; q < numAdj; ++q) { 620 PetscInt ndof, ncdof, ngoff, nd; 621 622 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 623 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 624 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 625 for (nd = 0; nd < ndof-ncdof; ++nd) { 626 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 627 ++i; 628 } 629 } 630 } 631 } 632 /* Debugging */ 633 if (debug) { 634 IS tmp; 635 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 636 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 637 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 638 } 639 /* Gather adjacenct indices to root */ 640 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 641 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 642 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 643 if (size > 1) { 644 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 645 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 646 } 647 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 648 ierr = PetscFree(adj);CHKERRQ(ierr); 649 /* Debugging */ 650 if (debug) { 651 IS tmp; 652 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 653 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 654 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 655 } 656 /* Add in local adjacency indices for owned dofs on interface (roots) */ 657 for (p = pStart; p < pEnd; ++p) { 658 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 659 660 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 661 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 662 if (!dof) continue; 663 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 664 if (adof <= 0) continue; 665 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 666 for (d = off; d < off+dof; ++d) { 667 PetscInt adof, aoff, i; 668 669 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 670 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 671 i = adof-1; 672 for (q = 0; q < numAdj; ++q) { 673 PetscInt ndof, ncdof, ngoff, nd; 674 675 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 676 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 677 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 678 for (nd = 0; nd < ndof-ncdof; ++nd) { 679 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 680 --i; 681 } 682 } 683 } 684 } 685 /* Debugging */ 686 if (debug) { 687 IS tmp; 688 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 689 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 690 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 691 } 692 /* Compress indices */ 693 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 694 for (p = pStart; p < pEnd; ++p) { 695 PetscInt dof, cdof, off, d; 696 PetscInt adof, aoff; 697 698 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 699 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 700 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 701 if (!dof) continue; 702 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 703 if (adof <= 0) continue; 704 for (d = off; d < off+dof-cdof; ++d) { 705 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 706 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 707 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 708 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 709 } 710 } 711 /* Debugging */ 712 if (debug) { 713 IS tmp; 714 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 715 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 716 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 717 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 718 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 719 } 720 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 721 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 722 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 723 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 724 for (p = pStart; p < pEnd; ++p) { 725 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 726 PetscBool found = PETSC_TRUE; 727 728 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 729 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 730 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 731 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 732 for (d = 0; d < dof-cdof; ++d) { 733 PetscInt ldof, rdof; 734 735 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 736 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 737 if (ldof > 0) { 738 /* We do not own this point */ 739 } else if (rdof > 0) { 740 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 741 } else { 742 found = PETSC_FALSE; 743 } 744 } 745 if (found) continue; 746 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 747 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 748 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 749 for (q = 0; q < numAdj; ++q) { 750 PetscInt ndof, ncdof, noff; 751 752 /* Adjacent points may not be in the section chart */ 753 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 754 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 755 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 756 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 757 for (d = goff; d < goff+dof-cdof; ++d) { 758 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 759 } 760 } 761 } 762 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 763 if (debug) { 764 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 765 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 766 } 767 /* Get adjacent indices */ 768 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 769 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 770 for (p = pStart; p < pEnd; ++p) { 771 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 772 PetscBool found = PETSC_TRUE; 773 774 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 775 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 776 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 777 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 778 for (d = 0; d < dof-cdof; ++d) { 779 PetscInt ldof, rdof; 780 781 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 782 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 783 if (ldof > 0) { 784 /* We do not own this point */ 785 } else if (rdof > 0) { 786 PetscInt aoff, roff; 787 788 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 789 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 790 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 791 } else { 792 found = PETSC_FALSE; 793 } 794 } 795 if (found) continue; 796 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 797 for (d = goff; d < goff+dof-cdof; ++d) { 798 PetscInt adof, aoff, i = 0; 799 800 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 801 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 802 for (q = 0; q < numAdj; ++q) { 803 PetscInt ndof, ncdof, ngoff, nd; 804 const PetscInt *ncind; 805 806 /* Adjacent points may not be in the section chart */ 807 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 808 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 809 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 810 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 811 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 812 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 813 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 814 } 815 } 816 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); 817 } 818 } 819 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 820 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 821 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 822 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 823 /* Debugging */ 824 if (debug) { 825 IS tmp; 826 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 827 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 828 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 829 } 830 /* Create allocation vectors from adjacency graph */ 831 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 832 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr); 833 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 834 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 835 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 836 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 837 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 838 /* Only loop over blocks of rows */ 839 if (rStart%bs || rEnd%bs) SETERRQ3(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 840 for (r = rStart/bs; r < rEnd/bs; ++r) { 841 const PetscInt row = r*bs; 842 PetscInt numCols, cStart, c; 843 844 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 845 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 846 for (c = cStart; c < cStart+numCols; ++c) { 847 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 848 ++dnz[r-rStart]; 849 if (cols[c] >= row) ++dnzu[r-rStart]; 850 } else { 851 ++onz[r-rStart]; 852 if (cols[c] >= row) ++onzu[r-rStart]; 853 } 854 } 855 } 856 if (bs > 1) { 857 for (r = 0; r < locRows/bs; ++r) { 858 dnz[r] /= bs; 859 onz[r] /= bs; 860 dnzu[r] /= bs; 861 onzu[r] /= bs; 862 } 863 } 864 /* Set matrix pattern */ 865 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 866 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 867 /* Fill matrix with zeros */ 868 if (fillMatrix) { 869 PetscScalar *values; 870 PetscInt maxRowLen = 0; 871 872 for (r = rStart; r < rEnd; ++r) { 873 PetscInt len; 874 875 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 876 maxRowLen = PetscMax(maxRowLen, len); 877 } 878 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 879 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 880 for (r = rStart; r < rEnd; ++r) { 881 PetscInt numCols, cStart; 882 883 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 884 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 885 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 886 } 887 ierr = PetscFree(values);CHKERRQ(ierr); 888 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 889 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 890 } 891 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 892 ierr = PetscFree(cols);CHKERRQ(ierr); 893 PetscFunctionReturn(0); 894 } 895 896 #if 0 897 #undef __FUNCT__ 898 #define __FUNCT__ "DMPlexPreallocateOperator_2" 899 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 900 { 901 PetscInt *tmpClosure,*tmpAdj,*visits; 902 PetscInt c,cStart,cEnd,pStart,pEnd; 903 PetscErrorCode ierr; 904 905 PetscFunctionBegin; 906 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 907 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 908 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 909 910 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 911 912 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 913 npoints = pEnd - pStart; 914 915 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 916 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 917 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 918 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 919 for (c=cStart; c<cEnd; c++) { 920 PetscInt *support = tmpClosure; 921 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 922 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 923 } 924 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 925 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 926 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 927 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 928 929 ierr = PetscSFGetRanks();CHKERRQ(ierr); 930 931 932 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 933 for (c=cStart; c<cEnd; c++) { 934 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 935 /* 936 Depth-first walk of transitive closure. 937 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. 938 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 939 */ 940 } 941 942 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 943 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 944 PetscFunctionReturn(0); 945 } 946 #endif 947 948 #undef __FUNCT__ 949 #define __FUNCT__ "DMCreateMatrix_Plex" 950 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 951 { 952 PetscSection section, sectionGlobal; 953 PetscInt bs = -1; 954 PetscInt localSize; 955 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 956 PetscErrorCode ierr; 957 958 PetscFunctionBegin; 959 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 960 ierr = MatInitializePackage(NULL);CHKERRQ(ierr); 961 #endif 962 if (!mtype) mtype = MATAIJ; 963 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 964 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 965 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 966 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 967 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 968 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 969 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 970 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 974 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 975 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 976 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 977 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 978 /* Check for symmetric storage */ 979 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 980 if (isSymmetric) { 981 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 982 } 983 if (!isShell) { 984 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 985 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 986 987 if (bs < 0) { 988 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 989 PetscInt pStart, pEnd, p, dof, cdof; 990 991 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 992 for (p = pStart; p < pEnd; ++p) { 993 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 994 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 995 if (dof-cdof) { 996 if (bs < 0) { 997 bs = dof-cdof; 998 } else if (bs != dof-cdof) { 999 /* Layout does not admit a pointwise block size */ 1000 bs = 1; 1001 break; 1002 } 1003 } 1004 } 1005 /* Must have same blocksize on all procs (some might have no points) */ 1006 bsLocal = bs; 1007 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1008 bsLocal = bs < 0 ? bsMax : bs; 1009 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1010 if (bsMin != bsMax) { 1011 bs = 1; 1012 } else { 1013 bs = bsMax; 1014 } 1015 } else { 1016 bs = 1; 1017 } 1018 } 1019 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1020 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1021 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1022 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1023 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1024 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1025 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1026 } 1027 PetscFunctionReturn(0); 1028 } 1029 1030 #undef __FUNCT__ 1031 #define __FUNCT__ "DMPlexGetDimension" 1032 /*@ 1033 DMPlexGetDimension - Return the topological mesh dimension 1034 1035 Not collective 1036 1037 Input Parameter: 1038 . mesh - The DMPlex 1039 1040 Output Parameter: 1041 . dim - The topological mesh dimension 1042 1043 Level: beginner 1044 1045 .seealso: DMPlexCreate() 1046 @*/ 1047 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1048 { 1049 DM_Plex *mesh = (DM_Plex*) dm->data; 1050 1051 PetscFunctionBegin; 1052 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1053 PetscValidPointer(dim, 2); 1054 *dim = mesh->dim; 1055 PetscFunctionReturn(0); 1056 } 1057 1058 #undef __FUNCT__ 1059 #define __FUNCT__ "DMPlexSetDimension" 1060 /*@ 1061 DMPlexSetDimension - Set the topological mesh dimension 1062 1063 Collective on mesh 1064 1065 Input Parameters: 1066 + mesh - The DMPlex 1067 - dim - The topological mesh dimension 1068 1069 Level: beginner 1070 1071 .seealso: DMPlexCreate() 1072 @*/ 1073 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1074 { 1075 DM_Plex *mesh = (DM_Plex*) dm->data; 1076 1077 PetscFunctionBegin; 1078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1079 PetscValidLogicalCollectiveInt(dm, dim, 2); 1080 mesh->dim = dim; 1081 mesh->preallocCenterDim = dim; 1082 PetscFunctionReturn(0); 1083 } 1084 1085 #undef __FUNCT__ 1086 #define __FUNCT__ "DMPlexGetChart" 1087 /*@ 1088 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1089 1090 Not collective 1091 1092 Input Parameter: 1093 . mesh - The DMPlex 1094 1095 Output Parameters: 1096 + pStart - The first mesh point 1097 - pEnd - The upper bound for mesh points 1098 1099 Level: beginner 1100 1101 .seealso: DMPlexCreate(), DMPlexSetChart() 1102 @*/ 1103 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1104 { 1105 DM_Plex *mesh = (DM_Plex*) dm->data; 1106 PetscErrorCode ierr; 1107 1108 PetscFunctionBegin; 1109 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1110 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1111 PetscFunctionReturn(0); 1112 } 1113 1114 #undef __FUNCT__ 1115 #define __FUNCT__ "DMPlexSetChart" 1116 /*@ 1117 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1118 1119 Not collective 1120 1121 Input Parameters: 1122 + mesh - The DMPlex 1123 . pStart - The first mesh point 1124 - pEnd - The upper bound for mesh points 1125 1126 Output Parameters: 1127 1128 Level: beginner 1129 1130 .seealso: DMPlexCreate(), DMPlexGetChart() 1131 @*/ 1132 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1133 { 1134 DM_Plex *mesh = (DM_Plex*) dm->data; 1135 PetscErrorCode ierr; 1136 1137 PetscFunctionBegin; 1138 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1139 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1140 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1141 PetscFunctionReturn(0); 1142 } 1143 1144 #undef __FUNCT__ 1145 #define __FUNCT__ "DMPlexGetConeSize" 1146 /*@ 1147 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1148 1149 Not collective 1150 1151 Input Parameters: 1152 + mesh - The DMPlex 1153 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1154 1155 Output Parameter: 1156 . size - The cone size for point p 1157 1158 Level: beginner 1159 1160 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1161 @*/ 1162 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1163 { 1164 DM_Plex *mesh = (DM_Plex*) dm->data; 1165 PetscErrorCode ierr; 1166 1167 PetscFunctionBegin; 1168 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1169 PetscValidPointer(size, 3); 1170 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1171 PetscFunctionReturn(0); 1172 } 1173 1174 #undef __FUNCT__ 1175 #define __FUNCT__ "DMPlexSetConeSize" 1176 /*@ 1177 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1178 1179 Not collective 1180 1181 Input Parameters: 1182 + mesh - The DMPlex 1183 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1184 - size - The cone size for point p 1185 1186 Output Parameter: 1187 1188 Note: 1189 This should be called after DMPlexSetChart(). 1190 1191 Level: beginner 1192 1193 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1194 @*/ 1195 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1196 { 1197 DM_Plex *mesh = (DM_Plex*) dm->data; 1198 PetscErrorCode ierr; 1199 1200 PetscFunctionBegin; 1201 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1202 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1203 1204 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1205 PetscFunctionReturn(0); 1206 } 1207 1208 #undef __FUNCT__ 1209 #define __FUNCT__ "DMPlexGetCone" 1210 /*@C 1211 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1212 1213 Not collective 1214 1215 Input Parameters: 1216 + mesh - The DMPlex 1217 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1218 1219 Output Parameter: 1220 . cone - An array of points which are on the in-edges for point p 1221 1222 Level: beginner 1223 1224 Note: 1225 This routine is not available in Fortran. 1226 1227 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1228 @*/ 1229 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1230 { 1231 DM_Plex *mesh = (DM_Plex*) dm->data; 1232 PetscInt off; 1233 PetscErrorCode ierr; 1234 1235 PetscFunctionBegin; 1236 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1237 PetscValidPointer(cone, 3); 1238 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1239 *cone = &mesh->cones[off]; 1240 PetscFunctionReturn(0); 1241 } 1242 1243 #undef __FUNCT__ 1244 #define __FUNCT__ "DMPlexSetCone" 1245 /*@ 1246 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1247 1248 Not collective 1249 1250 Input Parameters: 1251 + mesh - The DMPlex 1252 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1253 - cone - An array of points which are on the in-edges for point p 1254 1255 Output Parameter: 1256 1257 Note: 1258 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1259 1260 Level: beginner 1261 1262 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1263 @*/ 1264 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1265 { 1266 DM_Plex *mesh = (DM_Plex*) dm->data; 1267 PetscInt pStart, pEnd; 1268 PetscInt dof, off, c; 1269 PetscErrorCode ierr; 1270 1271 PetscFunctionBegin; 1272 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1273 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1274 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1275 if (dof) PetscValidPointer(cone, 3); 1276 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1277 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1278 for (c = 0; c < dof; ++c) { 1279 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1280 mesh->cones[off+c] = cone[c]; 1281 } 1282 PetscFunctionReturn(0); 1283 } 1284 1285 #undef __FUNCT__ 1286 #define __FUNCT__ "DMPlexGetConeOrientation" 1287 /*@C 1288 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1289 1290 Not collective 1291 1292 Input Parameters: 1293 + mesh - The DMPlex 1294 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1295 1296 Output Parameter: 1297 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1298 integer giving the prescription for cone traversal. If it is negative, the cone is 1299 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1300 the index of the cone point on which to start. 1301 1302 Level: beginner 1303 1304 Note: 1305 This routine is not available in Fortran. 1306 1307 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1308 @*/ 1309 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1310 { 1311 DM_Plex *mesh = (DM_Plex*) dm->data; 1312 PetscInt off; 1313 PetscErrorCode ierr; 1314 1315 PetscFunctionBegin; 1316 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1317 #if defined(PETSC_USE_DEBUG) 1318 { 1319 PetscInt dof; 1320 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1321 if (dof) PetscValidPointer(coneOrientation, 3); 1322 } 1323 #endif 1324 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1325 1326 *coneOrientation = &mesh->coneOrientations[off]; 1327 PetscFunctionReturn(0); 1328 } 1329 1330 #undef __FUNCT__ 1331 #define __FUNCT__ "DMPlexSetConeOrientation" 1332 /*@ 1333 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1334 1335 Not collective 1336 1337 Input Parameters: 1338 + mesh - The DMPlex 1339 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1340 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1341 integer giving the prescription for cone traversal. If it is negative, the cone is 1342 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1343 the index of the cone point on which to start. 1344 1345 Output Parameter: 1346 1347 Note: 1348 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1349 1350 Level: beginner 1351 1352 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1353 @*/ 1354 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1355 { 1356 DM_Plex *mesh = (DM_Plex*) dm->data; 1357 PetscInt pStart, pEnd; 1358 PetscInt dof, off, c; 1359 PetscErrorCode ierr; 1360 1361 PetscFunctionBegin; 1362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1363 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1364 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1365 if (dof) PetscValidPointer(coneOrientation, 3); 1366 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1367 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1368 for (c = 0; c < dof; ++c) { 1369 PetscInt cdof, o = coneOrientation[c]; 1370 1371 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1372 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1373 mesh->coneOrientations[off+c] = o; 1374 } 1375 PetscFunctionReturn(0); 1376 } 1377 1378 #undef __FUNCT__ 1379 #define __FUNCT__ "DMPlexInsertCone" 1380 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1381 { 1382 DM_Plex *mesh = (DM_Plex*) dm->data; 1383 PetscInt pStart, pEnd; 1384 PetscInt dof, off; 1385 PetscErrorCode ierr; 1386 1387 PetscFunctionBegin; 1388 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1389 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1390 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1391 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1392 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1393 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1394 if (conePos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1395 mesh->cones[off+conePos] = conePoint; 1396 PetscFunctionReturn(0); 1397 } 1398 1399 #undef __FUNCT__ 1400 #define __FUNCT__ "DMPlexGetSupportSize" 1401 /*@ 1402 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1403 1404 Not collective 1405 1406 Input Parameters: 1407 + mesh - The DMPlex 1408 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1409 1410 Output Parameter: 1411 . size - The support size for point p 1412 1413 Level: beginner 1414 1415 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1416 @*/ 1417 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1418 { 1419 DM_Plex *mesh = (DM_Plex*) dm->data; 1420 PetscErrorCode ierr; 1421 1422 PetscFunctionBegin; 1423 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1424 PetscValidPointer(size, 3); 1425 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1426 PetscFunctionReturn(0); 1427 } 1428 1429 #undef __FUNCT__ 1430 #define __FUNCT__ "DMPlexSetSupportSize" 1431 /*@ 1432 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1433 1434 Not collective 1435 1436 Input Parameters: 1437 + mesh - The DMPlex 1438 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1439 - size - The support size for point p 1440 1441 Output Parameter: 1442 1443 Note: 1444 This should be called after DMPlexSetChart(). 1445 1446 Level: beginner 1447 1448 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1449 @*/ 1450 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1451 { 1452 DM_Plex *mesh = (DM_Plex*) dm->data; 1453 PetscErrorCode ierr; 1454 1455 PetscFunctionBegin; 1456 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1457 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1458 1459 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1460 PetscFunctionReturn(0); 1461 } 1462 1463 #undef __FUNCT__ 1464 #define __FUNCT__ "DMPlexGetSupport" 1465 /*@C 1466 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1467 1468 Not collective 1469 1470 Input Parameters: 1471 + mesh - The DMPlex 1472 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1473 1474 Output Parameter: 1475 . support - An array of points which are on the out-edges for point p 1476 1477 Level: beginner 1478 1479 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1480 @*/ 1481 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1482 { 1483 DM_Plex *mesh = (DM_Plex*) dm->data; 1484 PetscInt off; 1485 PetscErrorCode ierr; 1486 1487 PetscFunctionBegin; 1488 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1489 PetscValidPointer(support, 3); 1490 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1491 *support = &mesh->supports[off]; 1492 PetscFunctionReturn(0); 1493 } 1494 1495 #undef __FUNCT__ 1496 #define __FUNCT__ "DMPlexSetSupport" 1497 /*@ 1498 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1499 1500 Not collective 1501 1502 Input Parameters: 1503 + mesh - The DMPlex 1504 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1505 - support - An array of points which are on the in-edges for point p 1506 1507 Output Parameter: 1508 1509 Note: 1510 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1511 1512 Level: beginner 1513 1514 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1515 @*/ 1516 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1517 { 1518 DM_Plex *mesh = (DM_Plex*) dm->data; 1519 PetscInt pStart, pEnd; 1520 PetscInt dof, off, c; 1521 PetscErrorCode ierr; 1522 1523 PetscFunctionBegin; 1524 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1525 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1526 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1527 if (dof) PetscValidPointer(support, 3); 1528 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1529 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1530 for (c = 0; c < dof; ++c) { 1531 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1532 mesh->supports[off+c] = support[c]; 1533 } 1534 PetscFunctionReturn(0); 1535 } 1536 1537 #undef __FUNCT__ 1538 #define __FUNCT__ "DMPlexInsertSupport" 1539 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1540 { 1541 DM_Plex *mesh = (DM_Plex*) dm->data; 1542 PetscInt pStart, pEnd; 1543 PetscInt dof, off; 1544 PetscErrorCode ierr; 1545 1546 PetscFunctionBegin; 1547 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1548 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1549 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1550 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1551 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1552 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1553 if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1554 mesh->supports[off+supportPos] = supportPoint; 1555 PetscFunctionReturn(0); 1556 } 1557 1558 #undef __FUNCT__ 1559 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1560 /*@C 1561 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1562 1563 Not collective 1564 1565 Input Parameters: 1566 + mesh - The DMPlex 1567 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1568 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1569 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1570 1571 Output Parameters: 1572 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1573 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1574 1575 Note: 1576 If using internal storage (points is NULL on input), each call overwrites the last output. 1577 1578 Level: beginner 1579 1580 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1581 @*/ 1582 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1583 { 1584 DM_Plex *mesh = (DM_Plex*) dm->data; 1585 PetscInt *closure, *fifo; 1586 const PetscInt *tmp = NULL, *tmpO = NULL; 1587 PetscInt tmpSize, t; 1588 PetscInt depth = 0, maxSize; 1589 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1590 PetscErrorCode ierr; 1591 1592 PetscFunctionBegin; 1593 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1594 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1595 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1596 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1597 if (*points) { 1598 closure = *points; 1599 } else { 1600 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1601 } 1602 closure[0] = p; closure[1] = 0; 1603 /* This is only 1-level */ 1604 if (useCone) { 1605 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1606 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1607 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1608 } else { 1609 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1610 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1611 } 1612 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1613 const PetscInt cp = tmp[t]; 1614 const PetscInt co = tmpO ? tmpO[t] : 0; 1615 1616 closure[closureSize] = cp; 1617 closure[closureSize+1] = co; 1618 fifo[fifoSize] = cp; 1619 fifo[fifoSize+1] = co; 1620 } 1621 while (fifoSize - fifoStart) { 1622 const PetscInt q = fifo[fifoStart]; 1623 const PetscInt o = fifo[fifoStart+1]; 1624 const PetscInt rev = o >= 0 ? 0 : 1; 1625 const PetscInt off = rev ? -(o+1) : o; 1626 1627 if (useCone) { 1628 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1629 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1630 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1631 } else { 1632 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1633 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1634 tmpO = NULL; 1635 } 1636 for (t = 0; t < tmpSize; ++t) { 1637 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1638 const PetscInt cp = tmp[i]; 1639 /* Must propogate orientation */ 1640 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1641 PetscInt c; 1642 1643 /* Check for duplicate */ 1644 for (c = 0; c < closureSize; c += 2) { 1645 if (closure[c] == cp) break; 1646 } 1647 if (c == closureSize) { 1648 closure[closureSize] = cp; 1649 closure[closureSize+1] = co; 1650 fifo[fifoSize] = cp; 1651 fifo[fifoSize+1] = co; 1652 closureSize += 2; 1653 fifoSize += 2; 1654 } 1655 } 1656 fifoStart += 2; 1657 } 1658 if (numPoints) *numPoints = closureSize/2; 1659 if (points) *points = closure; 1660 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1661 PetscFunctionReturn(0); 1662 } 1663 1664 #undef __FUNCT__ 1665 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1666 /*@C 1667 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1668 1669 Not collective 1670 1671 Input Parameters: 1672 + mesh - The DMPlex 1673 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1674 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1675 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1676 1677 Output Parameters: 1678 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1679 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1680 1681 Note: 1682 If not using internal storage (points is not NULL on input), this call is unnecessary 1683 1684 Level: beginner 1685 1686 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1687 @*/ 1688 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1689 { 1690 PetscErrorCode ierr; 1691 1692 PetscFunctionBegin; 1693 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1694 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1695 PetscFunctionReturn(0); 1696 } 1697 1698 #undef __FUNCT__ 1699 #define __FUNCT__ "DMPlexGetMaxSizes" 1700 /*@ 1701 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1702 1703 Not collective 1704 1705 Input Parameter: 1706 . mesh - The DMPlex 1707 1708 Output Parameters: 1709 + maxConeSize - The maximum number of in-edges 1710 - maxSupportSize - The maximum number of out-edges 1711 1712 Level: beginner 1713 1714 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1715 @*/ 1716 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1717 { 1718 DM_Plex *mesh = (DM_Plex*) dm->data; 1719 1720 PetscFunctionBegin; 1721 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1722 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1723 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1724 PetscFunctionReturn(0); 1725 } 1726 1727 #undef __FUNCT__ 1728 #define __FUNCT__ "DMSetUp_Plex" 1729 PetscErrorCode DMSetUp_Plex(DM dm) 1730 { 1731 DM_Plex *mesh = (DM_Plex*) dm->data; 1732 PetscInt size; 1733 PetscErrorCode ierr; 1734 1735 PetscFunctionBegin; 1736 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1737 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1738 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1739 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1740 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1741 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1742 if (mesh->maxSupportSize) { 1743 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1744 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1745 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1746 } 1747 PetscFunctionReturn(0); 1748 } 1749 1750 #undef __FUNCT__ 1751 #define __FUNCT__ "DMCreateSubDM_Plex" 1752 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1753 { 1754 PetscSection section, sectionGlobal; 1755 PetscInt *subIndices; 1756 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1757 PetscErrorCode ierr; 1758 1759 PetscFunctionBegin; 1760 if (!numFields) PetscFunctionReturn(0); 1761 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1762 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1763 if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1764 if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1765 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1766 if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1767 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1768 for (p = pStart; p < pEnd; ++p) { 1769 PetscInt gdof; 1770 1771 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1772 if (gdof > 0) { 1773 for (f = 0; f < numFields; ++f) { 1774 PetscInt fdof, fcdof; 1775 1776 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1777 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1778 subSize += fdof-fcdof; 1779 } 1780 } 1781 } 1782 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1783 for (p = pStart; p < pEnd; ++p) { 1784 PetscInt gdof, goff; 1785 1786 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1787 if (gdof > 0) { 1788 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1789 for (f = 0; f < numFields; ++f) { 1790 PetscInt fdof, fcdof, fc, f2, poff = 0; 1791 1792 /* Can get rid of this loop by storing field information in the global section */ 1793 for (f2 = 0; f2 < fields[f]; ++f2) { 1794 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1795 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1796 poff += fdof-fcdof; 1797 } 1798 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1799 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1800 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1801 subIndices[subOff] = goff+poff+fc; 1802 } 1803 } 1804 } 1805 } 1806 if (is) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1807 if (subdm) { 1808 PetscSection subsection; 1809 PetscBool haveNull = PETSC_FALSE; 1810 PetscInt f, nf = 0; 1811 1812 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1813 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1814 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1815 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 1816 for (f = 0; f < numFields; ++f) { 1817 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1818 if ((*subdm)->nullspaceConstructors[f]) { 1819 haveNull = PETSC_TRUE; 1820 nf = f; 1821 } 1822 } 1823 if (haveNull) { 1824 MatNullSpace nullSpace; 1825 1826 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1827 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1828 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1829 } 1830 if (dm->fields) { 1831 if (nF != dm->numFields) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1832 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1833 for (f = 0; f < numFields; ++f) { 1834 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1835 } 1836 if (numFields == 1) { 1837 MatNullSpace space; 1838 Mat pmat; 1839 1840 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1841 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1842 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1843 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1844 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1845 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1846 } 1847 } 1848 } 1849 PetscFunctionReturn(0); 1850 } 1851 1852 #undef __FUNCT__ 1853 #define __FUNCT__ "DMPlexSymmetrize" 1854 /*@ 1855 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1856 1857 Not collective 1858 1859 Input Parameter: 1860 . mesh - The DMPlex 1861 1862 Output Parameter: 1863 1864 Note: 1865 This should be called after all calls to DMPlexSetCone() 1866 1867 Level: beginner 1868 1869 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1870 @*/ 1871 PetscErrorCode DMPlexSymmetrize(DM dm) 1872 { 1873 DM_Plex *mesh = (DM_Plex*) dm->data; 1874 PetscInt *offsets; 1875 PetscInt supportSize; 1876 PetscInt pStart, pEnd, p; 1877 PetscErrorCode ierr; 1878 1879 PetscFunctionBegin; 1880 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1881 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1882 /* Calculate support sizes */ 1883 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1884 for (p = pStart; p < pEnd; ++p) { 1885 PetscInt dof, off, c; 1886 1887 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1888 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1889 for (c = off; c < off+dof; ++c) { 1890 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1891 } 1892 } 1893 for (p = pStart; p < pEnd; ++p) { 1894 PetscInt dof; 1895 1896 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1897 1898 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1899 } 1900 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1901 /* Calculate supports */ 1902 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1903 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1904 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1905 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1906 for (p = pStart; p < pEnd; ++p) { 1907 PetscInt dof, off, c; 1908 1909 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1910 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1911 for (c = off; c < off+dof; ++c) { 1912 const PetscInt q = mesh->cones[c]; 1913 PetscInt offS; 1914 1915 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1916 1917 mesh->supports[offS+offsets[q]] = p; 1918 ++offsets[q]; 1919 } 1920 } 1921 ierr = PetscFree(offsets);CHKERRQ(ierr); 1922 PetscFunctionReturn(0); 1923 } 1924 1925 #undef __FUNCT__ 1926 #define __FUNCT__ "DMPlexSetDepth_Private" 1927 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1928 { 1929 PetscInt d; 1930 PetscErrorCode ierr; 1931 1932 PetscFunctionBegin; 1933 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1934 if (d < 0) { 1935 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1936 const PetscInt *cone = NULL; 1937 PetscInt dCone; 1938 1939 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1940 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1941 d = dCone+1; 1942 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1943 } 1944 *depth = d; 1945 PetscFunctionReturn(0); 1946 } 1947 1948 #undef __FUNCT__ 1949 #define __FUNCT__ "DMPlexStratify" 1950 /*@ 1951 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 1952 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 1953 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 1954 the DAG. 1955 1956 Not collective 1957 1958 Input Parameter: 1959 . mesh - The DMPlex 1960 1961 Output Parameter: 1962 1963 Notes: 1964 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 1965 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 1966 1967 This should be called after all calls to DMPlexSymmetrize() 1968 1969 Level: beginner 1970 1971 .seealso: DMPlexCreate(), DMPlexSymmetrize() 1972 @*/ 1973 PetscErrorCode DMPlexStratify(DM dm) 1974 { 1975 DM_Plex *mesh = (DM_Plex*) dm->data; 1976 PetscInt pStart, pEnd, p; 1977 PetscInt numRoots = 0, numLeaves = 0; 1978 PetscErrorCode ierr; 1979 1980 PetscFunctionBegin; 1981 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1982 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1983 /* Calculate depth */ 1984 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1985 /* Initialize roots and count leaves */ 1986 for (p = pStart; p < pEnd; ++p) { 1987 PetscInt coneSize, supportSize; 1988 1989 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1990 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1991 if (!coneSize && supportSize) { 1992 ++numRoots; 1993 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 1994 } else if (!supportSize && coneSize) { 1995 ++numLeaves; 1996 } else if (!supportSize && !coneSize) { 1997 /* Isolated points */ 1998 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 1999 } 2000 } 2001 if (numRoots + numLeaves == (pEnd - pStart)) { 2002 for (p = pStart; p < pEnd; ++p) { 2003 PetscInt coneSize, supportSize; 2004 2005 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2006 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2007 if (!supportSize && coneSize) { 2008 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2009 } 2010 } 2011 } else { 2012 /* This might be slow since lookup is not fast */ 2013 for (p = pStart; p < pEnd; ++p) { 2014 PetscInt depth; 2015 2016 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2017 } 2018 } 2019 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2020 PetscFunctionReturn(0); 2021 } 2022 2023 #undef __FUNCT__ 2024 #define __FUNCT__ "DMPlexGetJoin" 2025 /*@C 2026 DMPlexGetJoin - Get an array for the join of the set of points 2027 2028 Not Collective 2029 2030 Input Parameters: 2031 + dm - The DMPlex object 2032 . numPoints - The number of input points for the join 2033 - points - The input points 2034 2035 Output Parameters: 2036 + numCoveredPoints - The number of points in the join 2037 - coveredPoints - The points in the join 2038 2039 Level: intermediate 2040 2041 Note: Currently, this is restricted to a single level join 2042 2043 .keywords: mesh 2044 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2045 @*/ 2046 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2047 { 2048 DM_Plex *mesh = (DM_Plex*) dm->data; 2049 PetscInt *join[2]; 2050 PetscInt joinSize, i = 0; 2051 PetscInt dof, off, p, c, m; 2052 PetscErrorCode ierr; 2053 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2056 PetscValidPointer(points, 2); 2057 PetscValidPointer(numCoveredPoints, 3); 2058 PetscValidPointer(coveredPoints, 4); 2059 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2060 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2061 /* Copy in support of first point */ 2062 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2063 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2064 for (joinSize = 0; joinSize < dof; ++joinSize) { 2065 join[i][joinSize] = mesh->supports[off+joinSize]; 2066 } 2067 /* Check each successive support */ 2068 for (p = 1; p < numPoints; ++p) { 2069 PetscInt newJoinSize = 0; 2070 2071 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2072 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2073 for (c = 0; c < dof; ++c) { 2074 const PetscInt point = mesh->supports[off+c]; 2075 2076 for (m = 0; m < joinSize; ++m) { 2077 if (point == join[i][m]) { 2078 join[1-i][newJoinSize++] = point; 2079 break; 2080 } 2081 } 2082 } 2083 joinSize = newJoinSize; 2084 i = 1-i; 2085 } 2086 *numCoveredPoints = joinSize; 2087 *coveredPoints = join[i]; 2088 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2089 PetscFunctionReturn(0); 2090 } 2091 2092 #undef __FUNCT__ 2093 #define __FUNCT__ "DMPlexRestoreJoin" 2094 /*@C 2095 DMPlexRestoreJoin - Restore an array for the join of the set of points 2096 2097 Not Collective 2098 2099 Input Parameters: 2100 + dm - The DMPlex object 2101 . numPoints - The number of input points for the join 2102 - points - The input points 2103 2104 Output Parameters: 2105 + numCoveredPoints - The number of points in the join 2106 - coveredPoints - The points in the join 2107 2108 Level: intermediate 2109 2110 .keywords: mesh 2111 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2112 @*/ 2113 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2114 { 2115 PetscErrorCode ierr; 2116 2117 PetscFunctionBegin; 2118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2119 PetscValidPointer(coveredPoints, 4); 2120 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2121 PetscFunctionReturn(0); 2122 } 2123 2124 #undef __FUNCT__ 2125 #define __FUNCT__ "DMPlexGetFullJoin" 2126 /*@C 2127 DMPlexGetFullJoin - Get an array for the join of the set of points 2128 2129 Not Collective 2130 2131 Input Parameters: 2132 + dm - The DMPlex object 2133 . numPoints - The number of input points for the join 2134 - points - The input points 2135 2136 Output Parameters: 2137 + numCoveredPoints - The number of points in the join 2138 - coveredPoints - The points in the join 2139 2140 Level: intermediate 2141 2142 .keywords: mesh 2143 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2144 @*/ 2145 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2146 { 2147 DM_Plex *mesh = (DM_Plex*) dm->data; 2148 PetscInt *offsets, **closures; 2149 PetscInt *join[2]; 2150 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2151 PetscInt p, d, c, m; 2152 PetscErrorCode ierr; 2153 2154 PetscFunctionBegin; 2155 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2156 PetscValidPointer(points, 2); 2157 PetscValidPointer(numCoveredPoints, 3); 2158 PetscValidPointer(coveredPoints, 4); 2159 2160 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2161 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2162 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2163 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2164 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2165 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2166 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2167 2168 for (p = 0; p < numPoints; ++p) { 2169 PetscInt closureSize; 2170 2171 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2172 2173 offsets[p*(depth+2)+0] = 0; 2174 for (d = 0; d < depth+1; ++d) { 2175 PetscInt pStart, pEnd, i; 2176 2177 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2178 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2179 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2180 offsets[p*(depth+2)+d+1] = i; 2181 break; 2182 } 2183 } 2184 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2185 } 2186 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2187 } 2188 for (d = 0; d < depth+1; ++d) { 2189 PetscInt dof; 2190 2191 /* Copy in support of first point */ 2192 dof = offsets[d+1] - offsets[d]; 2193 for (joinSize = 0; joinSize < dof; ++joinSize) { 2194 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2195 } 2196 /* Check each successive cone */ 2197 for (p = 1; p < numPoints && joinSize; ++p) { 2198 PetscInt newJoinSize = 0; 2199 2200 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2201 for (c = 0; c < dof; ++c) { 2202 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2203 2204 for (m = 0; m < joinSize; ++m) { 2205 if (point == join[i][m]) { 2206 join[1-i][newJoinSize++] = point; 2207 break; 2208 } 2209 } 2210 } 2211 joinSize = newJoinSize; 2212 i = 1-i; 2213 } 2214 if (joinSize) break; 2215 } 2216 *numCoveredPoints = joinSize; 2217 *coveredPoints = join[i]; 2218 for (p = 0; p < numPoints; ++p) { 2219 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2220 } 2221 ierr = PetscFree(closures);CHKERRQ(ierr); 2222 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2223 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2224 PetscFunctionReturn(0); 2225 } 2226 2227 #undef __FUNCT__ 2228 #define __FUNCT__ "DMPlexGetMeet" 2229 /*@C 2230 DMPlexGetMeet - Get an array for the meet of the set of points 2231 2232 Not Collective 2233 2234 Input Parameters: 2235 + dm - The DMPlex object 2236 . numPoints - The number of input points for the meet 2237 - points - The input points 2238 2239 Output Parameters: 2240 + numCoveredPoints - The number of points in the meet 2241 - coveredPoints - The points in the meet 2242 2243 Level: intermediate 2244 2245 Note: Currently, this is restricted to a single level meet 2246 2247 .keywords: mesh 2248 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2249 @*/ 2250 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2251 { 2252 DM_Plex *mesh = (DM_Plex*) dm->data; 2253 PetscInt *meet[2]; 2254 PetscInt meetSize, i = 0; 2255 PetscInt dof, off, p, c, m; 2256 PetscErrorCode ierr; 2257 2258 PetscFunctionBegin; 2259 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2260 PetscValidPointer(points, 2); 2261 PetscValidPointer(numCoveringPoints, 3); 2262 PetscValidPointer(coveringPoints, 4); 2263 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2264 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2265 /* Copy in cone of first point */ 2266 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2267 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2268 for (meetSize = 0; meetSize < dof; ++meetSize) { 2269 meet[i][meetSize] = mesh->cones[off+meetSize]; 2270 } 2271 /* Check each successive cone */ 2272 for (p = 1; p < numPoints; ++p) { 2273 PetscInt newMeetSize = 0; 2274 2275 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2276 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2277 for (c = 0; c < dof; ++c) { 2278 const PetscInt point = mesh->cones[off+c]; 2279 2280 for (m = 0; m < meetSize; ++m) { 2281 if (point == meet[i][m]) { 2282 meet[1-i][newMeetSize++] = point; 2283 break; 2284 } 2285 } 2286 } 2287 meetSize = newMeetSize; 2288 i = 1-i; 2289 } 2290 *numCoveringPoints = meetSize; 2291 *coveringPoints = meet[i]; 2292 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2293 PetscFunctionReturn(0); 2294 } 2295 2296 #undef __FUNCT__ 2297 #define __FUNCT__ "DMPlexRestoreMeet" 2298 /*@C 2299 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2300 2301 Not Collective 2302 2303 Input Parameters: 2304 + dm - The DMPlex object 2305 . numPoints - The number of input points for the meet 2306 - points - The input points 2307 2308 Output Parameters: 2309 + numCoveredPoints - The number of points in the meet 2310 - coveredPoints - The points in the meet 2311 2312 Level: intermediate 2313 2314 .keywords: mesh 2315 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2316 @*/ 2317 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2318 { 2319 PetscErrorCode ierr; 2320 2321 PetscFunctionBegin; 2322 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2323 PetscValidPointer(coveredPoints, 4); 2324 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2325 PetscFunctionReturn(0); 2326 } 2327 2328 #undef __FUNCT__ 2329 #define __FUNCT__ "DMPlexGetFullMeet" 2330 /*@C 2331 DMPlexGetFullMeet - Get an array for the meet of the set of points 2332 2333 Not Collective 2334 2335 Input Parameters: 2336 + dm - The DMPlex object 2337 . numPoints - The number of input points for the meet 2338 - points - The input points 2339 2340 Output Parameters: 2341 + numCoveredPoints - The number of points in the meet 2342 - coveredPoints - The points in the meet 2343 2344 Level: intermediate 2345 2346 .keywords: mesh 2347 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2348 @*/ 2349 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2350 { 2351 DM_Plex *mesh = (DM_Plex*) dm->data; 2352 PetscInt *offsets, **closures; 2353 PetscInt *meet[2]; 2354 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2355 PetscInt p, h, c, m; 2356 PetscErrorCode ierr; 2357 2358 PetscFunctionBegin; 2359 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2360 PetscValidPointer(points, 2); 2361 PetscValidPointer(numCoveredPoints, 3); 2362 PetscValidPointer(coveredPoints, 4); 2363 2364 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2365 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2366 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2367 maxSize = PetscPowInt(mesh->maxConeSize,height); 2368 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2369 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2370 2371 for (p = 0; p < numPoints; ++p) { 2372 PetscInt closureSize; 2373 2374 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2375 2376 offsets[p*(height+2)+0] = 0; 2377 for (h = 0; h < height+1; ++h) { 2378 PetscInt pStart, pEnd, i; 2379 2380 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2381 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2382 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2383 offsets[p*(height+2)+h+1] = i; 2384 break; 2385 } 2386 } 2387 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2388 } 2389 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2390 } 2391 for (h = 0; h < height+1; ++h) { 2392 PetscInt dof; 2393 2394 /* Copy in cone of first point */ 2395 dof = offsets[h+1] - offsets[h]; 2396 for (meetSize = 0; meetSize < dof; ++meetSize) { 2397 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2398 } 2399 /* Check each successive cone */ 2400 for (p = 1; p < numPoints && meetSize; ++p) { 2401 PetscInt newMeetSize = 0; 2402 2403 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2404 for (c = 0; c < dof; ++c) { 2405 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2406 2407 for (m = 0; m < meetSize; ++m) { 2408 if (point == meet[i][m]) { 2409 meet[1-i][newMeetSize++] = point; 2410 break; 2411 } 2412 } 2413 } 2414 meetSize = newMeetSize; 2415 i = 1-i; 2416 } 2417 if (meetSize) break; 2418 } 2419 *numCoveredPoints = meetSize; 2420 *coveredPoints = meet[i]; 2421 for (p = 0; p < numPoints; ++p) { 2422 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2423 } 2424 ierr = PetscFree(closures);CHKERRQ(ierr); 2425 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2426 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2427 PetscFunctionReturn(0); 2428 } 2429 2430 #undef __FUNCT__ 2431 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2432 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2433 { 2434 MPI_Comm comm; 2435 PetscInt cellDim; 2436 PetscErrorCode ierr; 2437 2438 PetscFunctionBegin; 2439 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2440 PetscValidPointer(numFaceVertices,3); 2441 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2442 switch (cellDim) { 2443 case 0: 2444 *numFaceVertices = 0; 2445 break; 2446 case 1: 2447 *numFaceVertices = 1; 2448 break; 2449 case 2: 2450 switch (numCorners) { 2451 case 3: /* triangle */ 2452 *numFaceVertices = 2; /* Edge has 2 vertices */ 2453 break; 2454 case 4: /* quadrilateral */ 2455 *numFaceVertices = 2; /* Edge has 2 vertices */ 2456 break; 2457 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2458 *numFaceVertices = 3; /* Edge has 3 vertices */ 2459 break; 2460 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2461 *numFaceVertices = 3; /* Edge has 3 vertices */ 2462 break; 2463 default: 2464 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2465 } 2466 break; 2467 case 3: 2468 switch (numCorners) { 2469 case 4: /* tetradehdron */ 2470 *numFaceVertices = 3; /* Face has 3 vertices */ 2471 break; 2472 case 6: /* tet cohesive cells */ 2473 *numFaceVertices = 4; /* Face has 4 vertices */ 2474 break; 2475 case 8: /* hexahedron */ 2476 *numFaceVertices = 4; /* Face has 4 vertices */ 2477 break; 2478 case 9: /* tet cohesive Lagrange cells */ 2479 *numFaceVertices = 6; /* Face has 6 vertices */ 2480 break; 2481 case 10: /* quadratic tetrahedron */ 2482 *numFaceVertices = 6; /* Face has 6 vertices */ 2483 break; 2484 case 12: /* hex cohesive Lagrange cells */ 2485 *numFaceVertices = 6; /* Face has 6 vertices */ 2486 break; 2487 case 18: /* quadratic tet cohesive Lagrange cells */ 2488 *numFaceVertices = 6; /* Face has 6 vertices */ 2489 break; 2490 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2491 *numFaceVertices = 9; /* Face has 9 vertices */ 2492 break; 2493 default: 2494 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2495 } 2496 break; 2497 default: 2498 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2499 } 2500 PetscFunctionReturn(0); 2501 } 2502 2503 #undef __FUNCT__ 2504 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2505 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2506 { 2507 const PetscInt maxFaceCases = 30; 2508 PetscInt numFaceCases = 0; 2509 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2510 PetscInt *off, *adj; 2511 PetscInt *neighborCells, *tmpClosure; 2512 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2513 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2514 PetscErrorCode ierr; 2515 2516 PetscFunctionBegin; 2517 /* For parallel partitioning, I think you have to communicate supports */ 2518 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2519 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2520 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2521 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2522 if (cEnd - cStart == 0) { 2523 if (numVertices) *numVertices = 0; 2524 if (offsets) *offsets = NULL; 2525 if (adjacency) *adjacency = NULL; 2526 PetscFunctionReturn(0); 2527 } 2528 numCells = cEnd - cStart; 2529 /* Setup face recognition */ 2530 if (depth == 1) { 2531 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 */ 2532 2533 for (c = cStart; c < cEnd; ++c) { 2534 PetscInt corners; 2535 2536 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2537 if (!cornersSeen[corners]) { 2538 PetscInt nFV; 2539 2540 if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2541 cornersSeen[corners] = 1; 2542 2543 ierr = DMPlexGetNumFaceVertices_Internal(dm, corners, &nFV);CHKERRQ(ierr); 2544 2545 numFaceVertices[numFaceCases++] = nFV; 2546 } 2547 } 2548 } 2549 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2550 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2551 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2552 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2553 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2554 /* Count neighboring cells */ 2555 for (cell = cStart; cell < cEnd; ++cell) { 2556 PetscInt numNeighbors = maxNeighbors, n; 2557 2558 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2559 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2560 for (n = 0; n < numNeighbors; ++n) { 2561 PetscInt cellPair[2]; 2562 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2563 PetscInt meetSize = 0; 2564 const PetscInt *meet = NULL; 2565 2566 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2567 if (cellPair[0] == cellPair[1]) continue; 2568 if (!found) { 2569 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2570 if (meetSize) { 2571 PetscInt f; 2572 2573 for (f = 0; f < numFaceCases; ++f) { 2574 if (numFaceVertices[f] == meetSize) { 2575 found = PETSC_TRUE; 2576 break; 2577 } 2578 } 2579 } 2580 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2581 } 2582 if (found) ++off[cell-cStart+1]; 2583 } 2584 } 2585 /* Prefix sum */ 2586 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2587 2588 if (adjacency) { 2589 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2590 /* Get neighboring cells */ 2591 for (cell = cStart; cell < cEnd; ++cell) { 2592 PetscInt numNeighbors = maxNeighbors, n; 2593 PetscInt cellOffset = 0; 2594 2595 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2596 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2597 for (n = 0; n < numNeighbors; ++n) { 2598 PetscInt cellPair[2]; 2599 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2600 PetscInt meetSize = 0; 2601 const PetscInt *meet = NULL; 2602 2603 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2604 if (cellPair[0] == cellPair[1]) continue; 2605 if (!found) { 2606 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2607 if (meetSize) { 2608 PetscInt f; 2609 2610 for (f = 0; f < numFaceCases; ++f) { 2611 if (numFaceVertices[f] == meetSize) { 2612 found = PETSC_TRUE; 2613 break; 2614 } 2615 } 2616 } 2617 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2618 } 2619 if (found) { 2620 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2621 ++cellOffset; 2622 } 2623 } 2624 } 2625 } 2626 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2627 if (numVertices) *numVertices = numCells; 2628 if (offsets) *offsets = off; 2629 if (adjacency) *adjacency = adj; 2630 PetscFunctionReturn(0); 2631 } 2632 2633 #if defined(PETSC_HAVE_CHACO) 2634 #if defined(PETSC_HAVE_UNISTD_H) 2635 #include <unistd.h> 2636 #endif 2637 /* Chaco does not have an include file */ 2638 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2639 float *ewgts, float *x, float *y, float *z, char *outassignname, 2640 char *outfilename, short *assignment, int architecture, int ndims_tot, 2641 int mesh_dims[3], double *goal, int global_method, int local_method, 2642 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2643 2644 extern int FREE_GRAPH; 2645 2646 #undef __FUNCT__ 2647 #define __FUNCT__ "DMPlexPartition_Chaco" 2648 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2649 { 2650 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2651 MPI_Comm comm; 2652 int nvtxs = numVertices; /* number of vertices in full graph */ 2653 int *vwgts = NULL; /* weights for all vertices */ 2654 float *ewgts = NULL; /* weights for all edges */ 2655 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2656 char *outassignname = NULL; /* name of assignment output file */ 2657 char *outfilename = NULL; /* output file name */ 2658 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2659 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2660 int mesh_dims[3]; /* dimensions of mesh of processors */ 2661 double *goal = NULL; /* desired set sizes for each set */ 2662 int global_method = 1; /* global partitioning algorithm */ 2663 int local_method = 1; /* local partitioning algorithm */ 2664 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2665 int vmax = 200; /* how many vertices to coarsen down to? */ 2666 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2667 double eigtol = 0.001; /* tolerance on eigenvectors */ 2668 long seed = 123636512; /* for random graph mutations */ 2669 short int *assignment; /* Output partition */ 2670 int fd_stdout, fd_pipe[2]; 2671 PetscInt *points; 2672 PetscMPIInt commSize; 2673 int i, v, p; 2674 PetscErrorCode ierr; 2675 2676 PetscFunctionBegin; 2677 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2678 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2679 if (!numVertices) { 2680 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2681 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2682 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2683 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2684 PetscFunctionReturn(0); 2685 } 2686 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2687 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2688 2689 if (global_method == INERTIAL_METHOD) { 2690 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2691 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2692 } 2693 mesh_dims[0] = commSize; 2694 mesh_dims[1] = 1; 2695 mesh_dims[2] = 1; 2696 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2697 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2698 /* TODO: check error codes for UNIX calls */ 2699 #if defined(PETSC_HAVE_UNISTD_H) 2700 { 2701 int piperet; 2702 piperet = pipe(fd_pipe); 2703 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2704 fd_stdout = dup(1); 2705 close(1); 2706 dup2(fd_pipe[1], 1); 2707 } 2708 #endif 2709 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2710 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2711 vmax, ndims, eigtol, seed); 2712 #if defined(PETSC_HAVE_UNISTD_H) 2713 { 2714 char msgLog[10000]; 2715 int count; 2716 2717 fflush(stdout); 2718 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2719 if (count < 0) count = 0; 2720 msgLog[count] = 0; 2721 close(1); 2722 dup2(fd_stdout, 1); 2723 close(fd_stdout); 2724 close(fd_pipe[0]); 2725 close(fd_pipe[1]); 2726 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2727 } 2728 #endif 2729 /* Convert to PetscSection+IS */ 2730 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2731 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2732 for (v = 0; v < nvtxs; ++v) { 2733 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2734 } 2735 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2736 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2737 for (p = 0, i = 0; p < commSize; ++p) { 2738 for (v = 0; v < nvtxs; ++v) { 2739 if (assignment[v] == p) points[i++] = v; 2740 } 2741 } 2742 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2743 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2744 if (global_method == INERTIAL_METHOD) { 2745 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2746 } 2747 ierr = PetscFree(assignment);CHKERRQ(ierr); 2748 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2749 PetscFunctionReturn(0); 2750 } 2751 #endif 2752 2753 #if defined(PETSC_HAVE_PARMETIS) 2754 #undef __FUNCT__ 2755 #define __FUNCT__ "DMPlexPartition_ParMetis" 2756 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2757 { 2758 PetscFunctionBegin; 2759 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ParMetis not yet supported"); 2760 PetscFunctionReturn(0); 2761 } 2762 #endif 2763 2764 #undef __FUNCT__ 2765 #define __FUNCT__ "DMPlexEnlargePartition" 2766 /* Expand the partition by BFS on the adjacency graph */ 2767 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2768 { 2769 PetscHashI h; 2770 const PetscInt *points; 2771 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2772 PetscInt pStart, pEnd, part, q; 2773 PetscErrorCode ierr; 2774 2775 PetscFunctionBegin; 2776 PetscHashICreate(h); 2777 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2778 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2779 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2780 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2781 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2782 for (part = pStart; part < pEnd; ++part) { 2783 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2784 2785 PetscHashIClear(h); 2786 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2787 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2788 /* Add all existing points to h */ 2789 for (p = 0; p < numPoints; ++p) { 2790 const PetscInt point = points[off+p]; 2791 PetscHashIAdd(h, point, 1); 2792 } 2793 PetscHashISize(h, nP); 2794 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2795 /* Add all points in next BFS level */ 2796 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2797 for (p = 0; p < numPoints; ++p) { 2798 const PetscInt point = points[off+p]; 2799 PetscInt s = start[point], e = start[point+1], a; 2800 2801 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2802 } 2803 PetscHashISize(h, numNewPoints); 2804 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2805 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2806 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2807 totPoints += numNewPoints; 2808 } 2809 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2810 PetscHashIDestroy(h); 2811 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2812 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2813 for (part = pStart, q = 0; part < pEnd; ++part) { 2814 PetscInt numPoints, p; 2815 2816 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2817 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2818 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2819 } 2820 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2821 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2822 PetscFunctionReturn(0); 2823 } 2824 2825 #undef __FUNCT__ 2826 #define __FUNCT__ "DMPlexCreatePartition" 2827 /* 2828 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2829 2830 Collective on DM 2831 2832 Input Parameters: 2833 + dm - The DM 2834 . height - The height for points in the partition 2835 - enlarge - Expand each partition with neighbors 2836 2837 Output Parameters: 2838 + partSection - The PetscSection giving the division of points by partition 2839 . partition - The list of points by partition 2840 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2841 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2842 2843 Level: developer 2844 2845 .seealso DMPlexDistribute() 2846 */ 2847 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2848 { 2849 PetscMPIInt size; 2850 PetscErrorCode ierr; 2851 2852 PetscFunctionBegin; 2853 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2854 2855 *origPartSection = NULL; 2856 *origPartition = NULL; 2857 if (size == 1) { 2858 PetscInt *points; 2859 PetscInt cStart, cEnd, c; 2860 2861 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2862 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2863 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2864 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2865 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2866 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2867 for (c = cStart; c < cEnd; ++c) points[c] = c; 2868 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2869 PetscFunctionReturn(0); 2870 } 2871 if (height == 0) { 2872 PetscInt numVertices; 2873 PetscInt *start = NULL; 2874 PetscInt *adjacency = NULL; 2875 2876 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2877 if (1) { 2878 #if defined(PETSC_HAVE_CHACO) 2879 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2880 #endif 2881 } else { 2882 #if defined(PETSC_HAVE_PARMETIS) 2883 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2884 #endif 2885 } 2886 if (enlarge) { 2887 *origPartSection = *partSection; 2888 *origPartition = *partition; 2889 2890 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2891 } 2892 ierr = PetscFree(start);CHKERRQ(ierr); 2893 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2894 # if 0 2895 } else if (height == 1) { 2896 /* Build the dual graph for faces and partition the hypergraph */ 2897 PetscInt numEdges; 2898 2899 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2900 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2901 destroyCSR(numEdges, start, adjacency); 2902 #endif 2903 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2904 PetscFunctionReturn(0); 2905 } 2906 2907 #undef __FUNCT__ 2908 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2909 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2910 { 2911 /* const PetscInt height = 0; */ 2912 const PetscInt *partArray; 2913 PetscInt *allPoints, *partPoints = NULL; 2914 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2915 PetscErrorCode ierr; 2916 2917 PetscFunctionBegin; 2918 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2919 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2920 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2921 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2922 for (rank = rStart; rank < rEnd; ++rank) { 2923 PetscInt partSize = 0; 2924 PetscInt numPoints, offset, p; 2925 2926 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2927 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2928 for (p = 0; p < numPoints; ++p) { 2929 PetscInt point = partArray[offset+p], closureSize, c; 2930 PetscInt *closure = NULL; 2931 2932 /* TODO Include support for height > 0 case */ 2933 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2934 /* Merge into existing points */ 2935 if (partSize+closureSize > maxPartSize) { 2936 PetscInt *tmpPoints; 2937 2938 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2939 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2940 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2941 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2942 2943 partPoints = tmpPoints; 2944 } 2945 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 2946 partSize += closureSize; 2947 2948 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 2949 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2950 } 2951 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 2952 } 2953 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2954 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 2955 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 2956 2957 for (rank = rStart; rank < rEnd; ++rank) { 2958 PetscInt partSize = 0, newOffset; 2959 PetscInt numPoints, offset, p; 2960 2961 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2962 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2963 for (p = 0; p < numPoints; ++p) { 2964 PetscInt point = partArray[offset+p], closureSize, c; 2965 PetscInt *closure = NULL; 2966 2967 /* TODO Include support for height > 0 case */ 2968 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2969 /* Merge into existing points */ 2970 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 2971 partSize += closureSize; 2972 2973 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 2974 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2975 } 2976 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 2977 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2978 } 2979 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 2980 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2981 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2982 PetscFunctionReturn(0); 2983 } 2984 2985 #undef __FUNCT__ 2986 #define __FUNCT__ "DMPlexDistributeField" 2987 /* 2988 Input Parameters: 2989 . originalSection 2990 , originalVec 2991 2992 Output Parameters: 2993 . newSection 2994 . newVec 2995 */ 2996 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 2997 { 2998 PetscSF fieldSF; 2999 PetscInt *remoteOffsets, fieldSize; 3000 PetscScalar *originalValues, *newValues; 3001 PetscErrorCode ierr; 3002 3003 PetscFunctionBegin; 3004 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3005 3006 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3007 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3008 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3009 3010 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3011 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3012 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3013 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3014 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3015 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3016 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3017 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3018 PetscFunctionReturn(0); 3019 } 3020 3021 #undef __FUNCT__ 3022 #define __FUNCT__ "DMPlexDistribute" 3023 /*@C 3024 DMPlexDistribute - Distributes the mesh and any associated sections. 3025 3026 Not Collective 3027 3028 Input Parameter: 3029 + dm - The original DMPlex object 3030 . partitioner - The partitioning package, or NULL for the default 3031 - overlap - The overlap of partitions, 0 is the default 3032 3033 Output Parameter: 3034 . parallelMesh - The distributed DMPlex object, or NULL 3035 3036 Note: If the mesh was not distributed, the return value is NULL 3037 3038 Level: intermediate 3039 3040 .keywords: mesh, elements 3041 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3042 @*/ 3043 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3044 { 3045 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3046 MPI_Comm comm; 3047 const PetscInt height = 0; 3048 PetscInt dim, numRemoteRanks; 3049 IS origCellPart, cellPart, part; 3050 PetscSection origCellPartSection, cellPartSection, partSection; 3051 PetscSFNode *remoteRanks; 3052 PetscSF partSF, pointSF, coneSF; 3053 ISLocalToGlobalMapping renumbering; 3054 PetscSection originalConeSection, newConeSection; 3055 PetscInt *remoteOffsets; 3056 PetscInt *cones, *newCones, newConesSize; 3057 PetscBool flg; 3058 PetscMPIInt rank, numProcs, p; 3059 PetscErrorCode ierr; 3060 3061 PetscFunctionBegin; 3062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3063 PetscValidPointer(dmParallel,4); 3064 3065 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3066 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3067 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3068 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3069 3070 *dmParallel = NULL; 3071 if (numProcs == 1) PetscFunctionReturn(0); 3072 3073 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3074 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3075 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3076 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3077 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3078 if (!rank) numRemoteRanks = numProcs; 3079 else numRemoteRanks = 0; 3080 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3081 for (p = 0; p < numRemoteRanks; ++p) { 3082 remoteRanks[p].rank = p; 3083 remoteRanks[p].index = 0; 3084 } 3085 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3086 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3087 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3088 if (flg) { 3089 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3090 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3091 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3092 if (origCellPart) { 3093 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3094 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3095 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3096 } 3097 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3098 } 3099 /* Close the partition over the mesh */ 3100 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3101 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3102 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3103 /* Create new mesh */ 3104 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3105 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3106 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3107 pmesh = (DM_Plex*) (*dmParallel)->data; 3108 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3109 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3110 if (flg) { 3111 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3112 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3113 ierr = ISView(part, NULL);CHKERRQ(ierr); 3114 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3115 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3116 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3117 } 3118 /* Distribute cone section */ 3119 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3120 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3121 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3122 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3123 { 3124 PetscInt pStart, pEnd, p; 3125 3126 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3127 for (p = pStart; p < pEnd; ++p) { 3128 PetscInt coneSize; 3129 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3130 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3131 } 3132 } 3133 /* Communicate and renumber cones */ 3134 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3135 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3136 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3137 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3138 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3139 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3140 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3141 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3142 if (flg) { 3143 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3144 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3145 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3146 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3147 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3148 } 3149 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3150 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3151 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3152 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3153 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3154 /* Create supports and stratify sieve */ 3155 { 3156 PetscInt pStart, pEnd; 3157 3158 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3159 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3160 } 3161 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3162 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3163 /* Distribute Coordinates */ 3164 { 3165 PetscSection originalCoordSection, newCoordSection; 3166 Vec originalCoordinates, newCoordinates; 3167 const char *name; 3168 3169 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3170 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3171 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3172 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3173 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3174 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3175 3176 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3177 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3178 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3179 } 3180 /* Distribute labels */ 3181 { 3182 DMLabel next = mesh->labels, newNext = pmesh->labels; 3183 PetscInt numLabels = 0, l; 3184 3185 /* Bcast number of labels */ 3186 while (next) { 3187 ++numLabels; next = next->next; 3188 } 3189 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3190 next = mesh->labels; 3191 for (l = 0; l < numLabels; ++l) { 3192 DMLabel newLabel; 3193 const PetscInt *partArray; 3194 char *name; 3195 PetscInt *stratumSizes = NULL, *points = NULL; 3196 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3197 PetscInt nameSize, s, p; 3198 PetscBool isdepth; 3199 size_t len = 0; 3200 3201 /* Bcast name (could filter for no points) */ 3202 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3203 nameSize = len; 3204 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3205 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3206 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3207 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3208 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3209 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3210 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3211 newLabel->name = name; 3212 /* Bcast numStrata (could filter for no points in stratum) */ 3213 if (!rank) newLabel->numStrata = next->numStrata; 3214 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3215 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3216 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3217 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3218 /* Bcast stratumValues (could filter for no points in stratum) */ 3219 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3220 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3221 /* Find size on each process and Scatter */ 3222 if (!rank) { 3223 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3224 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3225 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3226 for (s = 0; s < next->numStrata; ++s) { 3227 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3228 const PetscInt point = next->points[p]; 3229 PetscInt proc; 3230 3231 for (proc = 0; proc < numProcs; ++proc) { 3232 PetscInt dof, off, pPart; 3233 3234 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3235 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3236 for (pPart = off; pPart < off+dof; ++pPart) { 3237 if (partArray[pPart] == point) { 3238 ++stratumSizes[proc*next->numStrata+s]; 3239 break; 3240 } 3241 } 3242 } 3243 } 3244 } 3245 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3246 } 3247 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3248 /* Calculate stratumOffsets */ 3249 newLabel->stratumOffsets[0] = 0; 3250 for (s = 0; s < newLabel->numStrata; ++s) { 3251 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3252 } 3253 /* Pack points and Scatter */ 3254 if (!rank) { 3255 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3256 displs[0] = 0; 3257 for (p = 0; p < numProcs; ++p) { 3258 sendcnts[p] = 0; 3259 for (s = 0; s < next->numStrata; ++s) { 3260 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3261 } 3262 offsets[p] = displs[p]; 3263 displs[p+1] = displs[p] + sendcnts[p]; 3264 } 3265 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3266 for (s = 0; s < next->numStrata; ++s) { 3267 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3268 const PetscInt point = next->points[p]; 3269 PetscInt proc; 3270 3271 for (proc = 0; proc < numProcs; ++proc) { 3272 PetscInt dof, off, pPart; 3273 3274 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3275 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3276 for (pPart = off; pPart < off+dof; ++pPart) { 3277 if (partArray[pPart] == point) { 3278 points[offsets[proc]++] = point; 3279 break; 3280 } 3281 } 3282 } 3283 } 3284 } 3285 } 3286 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3287 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3288 ierr = PetscFree(points);CHKERRQ(ierr); 3289 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3290 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3291 /* Renumber points */ 3292 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3293 /* Sort points */ 3294 for (s = 0; s < newLabel->numStrata; ++s) { 3295 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3296 } 3297 /* Insert into list */ 3298 if (newNext) newNext->next = newLabel; 3299 else pmesh->labels = newLabel; 3300 newNext = newLabel; 3301 if (!rank) next = next->next; 3302 } 3303 } 3304 /* Cleanup Partition */ 3305 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3306 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3307 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3308 ierr = ISDestroy(&part);CHKERRQ(ierr); 3309 /* Create point SF for parallel mesh */ 3310 { 3311 const PetscInt *leaves; 3312 PetscSFNode *remotePoints, *rowners, *lowners; 3313 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3314 PetscInt pStart, pEnd; 3315 3316 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3317 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3318 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3319 for (p=0; p<numRoots; p++) { 3320 rowners[p].rank = -1; 3321 rowners[p].index = -1; 3322 } 3323 if (origCellPart) { 3324 /* Make sure cells in the original partition are not assigned to other procs */ 3325 const PetscInt *origCells; 3326 3327 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3328 for (p = 0; p < numProcs; ++p) { 3329 PetscInt dof, off, d; 3330 3331 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3332 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3333 for (d = off; d < off+dof; ++d) { 3334 rowners[origCells[d]].rank = p; 3335 } 3336 } 3337 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3338 } 3339 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3340 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3341 3342 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3343 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3344 for (p = 0; p < numLeaves; ++p) { 3345 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3346 lowners[p].rank = rank; 3347 lowners[p].index = leaves ? leaves[p] : p; 3348 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3349 lowners[p].rank = -2; 3350 lowners[p].index = -2; 3351 } 3352 } 3353 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3354 rowners[p].rank = -3; 3355 rowners[p].index = -3; 3356 } 3357 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3358 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3359 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3360 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3361 for (p = 0; p < numLeaves; ++p) { 3362 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3363 if (lowners[p].rank != rank) ++numGhostPoints; 3364 } 3365 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3366 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3367 for (p = 0, gp = 0; p < numLeaves; ++p) { 3368 if (lowners[p].rank != rank) { 3369 ghostPoints[gp] = leaves ? leaves[p] : p; 3370 remotePoints[gp].rank = lowners[p].rank; 3371 remotePoints[gp].index = lowners[p].index; 3372 ++gp; 3373 } 3374 } 3375 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3376 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3377 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3378 } 3379 /* Cleanup */ 3380 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3381 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3382 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3383 PetscFunctionReturn(0); 3384 } 3385 3386 #undef __FUNCT__ 3387 #define __FUNCT__ "DMPlexRenumber_Private" 3388 /* 3389 Reasons to renumber: 3390 3391 1) Permute points, e.g. bandwidth reduction (Renumber) 3392 3393 a) Must not mix strata 3394 3395 2) Shift numbers for point insertion (Shift) 3396 3397 a) Want operation brken into parts so that insertion can be interleaved 3398 3399 renumbering - An IS which provides the new numbering 3400 */ 3401 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3402 { 3403 PetscFunctionBegin; 3404 PetscFunctionReturn(0); 3405 } 3406 3407 #undef __FUNCT__ 3408 #define __FUNCT__ "DMPlexShiftPoint_Private" 3409 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3410 { 3411 if (depth < 0) return p; 3412 /* Cells */ if (p < depthEnd[depth]) return p; 3413 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3414 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3415 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3416 } 3417 3418 #undef __FUNCT__ 3419 #define __FUNCT__ "DMPlexShiftSizes_Private" 3420 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3421 { 3422 PetscInt *depthEnd; 3423 PetscInt depth = 0, d, pStart, pEnd, p; 3424 PetscErrorCode ierr; 3425 3426 PetscFunctionBegin; 3427 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3428 if (depth < 0) PetscFunctionReturn(0); 3429 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3430 /* Step 1: Expand chart */ 3431 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3432 for (d = 0; d <= depth; ++d) { 3433 pEnd += depthShift[d]; 3434 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3435 } 3436 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3437 /* Step 2: Set cone and support sizes */ 3438 for (d = 0; d <= depth; ++d) { 3439 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3440 for (p = pStart; p < pEnd; ++p) { 3441 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3442 PetscInt size; 3443 3444 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3445 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3446 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3447 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3448 } 3449 } 3450 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3451 PetscFunctionReturn(0); 3452 } 3453 3454 #undef __FUNCT__ 3455 #define __FUNCT__ "DMPlexShiftPoints_Private" 3456 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3457 { 3458 PetscInt *depthEnd, *newpoints; 3459 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3460 PetscErrorCode ierr; 3461 3462 PetscFunctionBegin; 3463 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3464 if (depth < 0) PetscFunctionReturn(0); 3465 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3466 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3467 for (d = 0; d <= depth; ++d) { 3468 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3469 } 3470 /* Step 5: Set cones and supports */ 3471 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3472 for (p = pStart; p < pEnd; ++p) { 3473 const PetscInt *points = NULL, *orientations = NULL; 3474 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3475 3476 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3477 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3478 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3479 for (i = 0; i < size; ++i) { 3480 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3481 } 3482 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3483 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3484 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3485 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3486 for (i = 0; i < size; ++i) { 3487 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3488 } 3489 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3490 } 3491 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3492 PetscFunctionReturn(0); 3493 } 3494 3495 #undef __FUNCT__ 3496 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3497 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3498 { 3499 PetscSection coordSection, newCoordSection; 3500 Vec coordinates, newCoordinates; 3501 PetscScalar *coords, *newCoords; 3502 PetscInt *depthEnd, coordSize; 3503 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3504 PetscErrorCode ierr; 3505 3506 PetscFunctionBegin; 3507 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3508 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3509 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3510 for (d = 0; d <= depth; ++d) { 3511 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3512 } 3513 /* Step 8: Convert coordinates */ 3514 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3515 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3516 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3517 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);CHKERRQ(ierr); 3518 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3519 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3520 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3521 for (v = vStartNew; v < vEndNew; ++v) { 3522 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3523 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3524 } 3525 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3526 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3527 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3528 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &newCoordinates);CHKERRQ(ierr); 3529 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3530 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3531 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3532 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3533 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3534 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3535 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3536 for (v = vStart; v < vEnd; ++v) { 3537 PetscInt dof, off, noff, d; 3538 3539 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3540 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3541 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3542 for (d = 0; d < dof; ++d) { 3543 newCoords[noff+d] = coords[off+d]; 3544 } 3545 } 3546 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3547 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3548 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3549 ierr = PetscSectionDestroy(&newCoordSection);CHKERRQ(ierr); 3550 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3551 PetscFunctionReturn(0); 3552 } 3553 3554 #undef __FUNCT__ 3555 #define __FUNCT__ "DMPlexShiftSF_Private" 3556 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3557 { 3558 PetscInt *depthEnd; 3559 PetscInt depth = 0, d; 3560 PetscSF sfPoint, sfPointNew; 3561 const PetscSFNode *remotePoints; 3562 PetscSFNode *gremotePoints; 3563 const PetscInt *localPoints; 3564 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3565 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3566 PetscMPIInt numProcs; 3567 PetscErrorCode ierr; 3568 3569 PetscFunctionBegin; 3570 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3571 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3572 for (d = 0; d <= depth; ++d) { 3573 totShift += depthShift[d]; 3574 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3575 } 3576 /* Step 9: Convert pointSF */ 3577 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 3578 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3579 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3580 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3581 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3582 if (numRoots >= 0) { 3583 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3584 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3585 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3586 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3587 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3588 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3589 for (l = 0; l < numLeaves; ++l) { 3590 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3591 gremotePoints[l].rank = remotePoints[l].rank; 3592 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3593 } 3594 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3595 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3596 } 3597 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3598 PetscFunctionReturn(0); 3599 } 3600 3601 #undef __FUNCT__ 3602 #define __FUNCT__ "DMPlexShiftLabels_Private" 3603 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3604 { 3605 PetscSF sfPoint; 3606 DMLabel vtkLabel, ghostLabel; 3607 PetscInt *depthEnd; 3608 const PetscSFNode *leafRemote; 3609 const PetscInt *leafLocal; 3610 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3611 PetscMPIInt rank; 3612 PetscErrorCode ierr; 3613 3614 PetscFunctionBegin; 3615 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3616 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3617 for (d = 0; d <= depth; ++d) { 3618 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3619 } 3620 /* Step 10: Convert labels */ 3621 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3622 for (l = 0; l < numLabels; ++l) { 3623 DMLabel label, newlabel; 3624 const char *lname; 3625 PetscBool isDepth; 3626 IS valueIS; 3627 const PetscInt *values; 3628 PetscInt numValues, val; 3629 3630 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3631 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3632 if (isDepth) continue; 3633 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3634 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3635 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3636 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3637 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3638 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3639 for (val = 0; val < numValues; ++val) { 3640 IS pointIS; 3641 const PetscInt *points; 3642 PetscInt numPoints, p; 3643 3644 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3645 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3646 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3647 for (p = 0; p < numPoints; ++p) { 3648 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3649 3650 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3651 } 3652 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3653 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3654 } 3655 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3656 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3657 } 3658 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3659 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3660 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 3661 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3662 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3663 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3664 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3665 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3666 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3667 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3668 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3669 for (; c < leafLocal[l] && c < cEnd; ++c) { 3670 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3671 } 3672 if (leafLocal[l] >= cEnd) break; 3673 if (leafRemote[l].rank == rank) { 3674 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3675 } else { 3676 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3677 } 3678 } 3679 for (; c < cEnd; ++c) { 3680 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3681 } 3682 if (0) { 3683 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3684 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3685 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3686 } 3687 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3688 for (f = fStart; f < fEnd; ++f) { 3689 PetscInt numCells; 3690 3691 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3692 if (numCells < 2) { 3693 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3694 } else { 3695 const PetscInt *cells = NULL; 3696 PetscInt vA, vB; 3697 3698 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3699 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3700 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3701 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3702 } 3703 } 3704 if (0) { 3705 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3706 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3707 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3708 } 3709 PetscFunctionReturn(0); 3710 } 3711 3712 #undef __FUNCT__ 3713 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3714 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3715 { 3716 DMLabel label; 3717 IS valueIS; 3718 const PetscInt *values; 3719 PetscInt *depthShift; 3720 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3721 PetscErrorCode ierr; 3722 3723 PetscFunctionBegin; 3724 /* Count ghost cells */ 3725 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3726 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3727 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3728 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3729 3730 *numGhostCells = 0; 3731 for (fs = 0; fs < numFS; ++fs) { 3732 PetscInt numBdFaces; 3733 3734 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3735 3736 *numGhostCells += numBdFaces; 3737 } 3738 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3739 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3740 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3741 if (depth >= 0) depthShift[depth] = *numGhostCells; 3742 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3743 /* Step 3: Set cone/support sizes for new points */ 3744 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3745 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3746 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3747 } 3748 for (fs = 0; fs < numFS; ++fs) { 3749 IS faceIS; 3750 const PetscInt *faces; 3751 PetscInt numFaces, f; 3752 3753 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3754 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3755 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3756 for (f = 0; f < numFaces; ++f) { 3757 PetscInt size; 3758 3759 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3760 if (size != 1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3761 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3762 } 3763 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3764 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3765 } 3766 /* Step 4: Setup ghosted DM */ 3767 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3768 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3769 /* Step 6: Set cones and supports for new points */ 3770 ghostCell = cEnd; 3771 for (fs = 0; fs < numFS; ++fs) { 3772 IS faceIS; 3773 const PetscInt *faces; 3774 PetscInt numFaces, f; 3775 3776 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3777 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3778 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3779 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3780 PetscInt newFace = faces[f] + *numGhostCells; 3781 3782 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3783 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3784 } 3785 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3786 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3787 } 3788 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3789 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3790 /* Step 7: Stratify */ 3791 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3792 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3793 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3794 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3795 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3796 PetscFunctionReturn(0); 3797 } 3798 3799 #undef __FUNCT__ 3800 #define __FUNCT__ "DMPlexConstructGhostCells" 3801 /*@C 3802 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3803 3804 Collective on dm 3805 3806 Input Parameters: 3807 + dm - The original DM 3808 - labelName - The label specifying the boundary faces (this could be auto-generated) 3809 3810 Output Parameters: 3811 + numGhostCells - The number of ghost cells added to the DM 3812 - dmGhosted - The new DM 3813 3814 Level: developer 3815 3816 .seealso: DMCreate() 3817 */ 3818 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3819 { 3820 DM gdm; 3821 PetscInt dim; 3822 PetscErrorCode ierr; 3823 3824 PetscFunctionBegin; 3825 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3826 PetscValidPointer(numGhostCells, 3); 3827 PetscValidPointer(dmGhosted, 4); 3828 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &gdm);CHKERRQ(ierr); 3829 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3830 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3831 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3832 switch (dim) { 3833 case 2: 3834 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3835 break; 3836 default: 3837 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3838 } 3839 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3840 *dmGhosted = gdm; 3841 PetscFunctionReturn(0); 3842 } 3843 3844 #undef __FUNCT__ 3845 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3846 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3847 { 3848 MPI_Comm comm; 3849 IS valueIS, *pointIS; 3850 const PetscInt *values, **splitPoints; 3851 PetscSection coordSection; 3852 Vec coordinates; 3853 PetscScalar *coords; 3854 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3855 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3856 PetscErrorCode ierr; 3857 3858 PetscFunctionBegin; 3859 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3860 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3861 /* Count split points and add cohesive cells */ 3862 if (label) { 3863 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3864 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3865 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3866 } 3867 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3868 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3869 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3870 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3871 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3872 for (d = 0; d <= depth; ++d) { 3873 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3874 numSplitPoints[d] = 0; 3875 splitPoints[d] = NULL; 3876 pointIS[d] = NULL; 3877 } 3878 for (sp = 0; sp < numSP; ++sp) { 3879 const PetscInt dep = values[sp]; 3880 3881 if ((dep < 0) || (dep > depth)) continue; 3882 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3883 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3884 if (pointIS[dep]) { 3885 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3886 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3887 } 3888 } 3889 if (depth >= 0) { 3890 /* Calculate number of additional points */ 3891 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3892 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3893 /* Calculate hybrid bound for each dimension */ 3894 pMaxNew[0] += depthShift[depth]; 3895 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3896 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3897 3898 /* Calculate point offset for each dimension */ 3899 depthOffset[depth] = 0; 3900 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3901 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3902 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3903 } 3904 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3905 /* Step 3: Set cone/support sizes for new points */ 3906 for (dep = 0; dep <= depth; ++dep) { 3907 for (p = 0; p < numSplitPoints[dep]; ++p) { 3908 const PetscInt oldp = splitPoints[dep][p]; 3909 const PetscInt newp = depthOffset[dep] + oldp; 3910 const PetscInt splitp = pMaxNew[dep] + p; 3911 const PetscInt *support; 3912 PetscInt coneSize, supportSize, q, e; 3913 3914 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3915 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3916 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3917 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3918 if (dep == depth-1) { 3919 const PetscInt ccell = pMaxNew[depth] + p; 3920 /* Add cohesive cells, they are prisms */ 3921 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3922 } else if (dep == 0) { 3923 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3924 3925 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3926 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3927 for (e = 0, q = 0; e < supportSize; ++e) { 3928 PetscInt val; 3929 3930 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3931 if ((val == 1) || (val == (shift + 1))) ++q; 3932 } 3933 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3934 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3935 for (e = 0, q = 0; e < supportSize; ++e) { 3936 PetscInt val; 3937 3938 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3939 if ((val == 1) || (val == -(shift + 1))) ++q; 3940 } 3941 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3942 /* Add cohesive edges */ 3943 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3944 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3945 } else if (dep == dim-2) { 3946 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3947 /* Split old edge: Faces in positive side cells and old split faces */ 3948 for (e = 0, q = 0; e < supportSize; ++e) { 3949 PetscInt val; 3950 3951 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3952 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 3953 } 3954 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 3955 /* Split new edge: Faces in negative side cells and new split faces */ 3956 for (e = 0, q = 0; e < supportSize; ++e) { 3957 PetscInt val; 3958 3959 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3960 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 3961 } 3962 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 3963 } 3964 } 3965 } 3966 /* Step 4: Setup split DM */ 3967 ierr = DMSetUp(sdm);CHKERRQ(ierr); 3968 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3969 /* Step 6: Set cones and supports for new points */ 3970 for (dep = 0; dep <= depth; ++dep) { 3971 for (p = 0; p < numSplitPoints[dep]; ++p) { 3972 const PetscInt oldp = splitPoints[dep][p]; 3973 const PetscInt newp = depthOffset[dep] + oldp; 3974 const PetscInt splitp = pMaxNew[dep] + p; 3975 const PetscInt *cone, *support, *ornt; 3976 PetscInt coneSize, supportSize, q, v, e, s; 3977 3978 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3979 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 3980 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 3981 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3982 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3983 if (dep == depth-1) { 3984 const PetscInt ccell = pMaxNew[depth] + p; 3985 const PetscInt *supportF; 3986 3987 /* Split face: copy in old face to new face to start */ 3988 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 3989 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 3990 /* Split old face: old vertices/edges in cone so no change */ 3991 /* Split new face: new vertices/edges in cone */ 3992 for (q = 0; q < coneSize; ++q) { 3993 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 3994 3995 coneNew[2+q] = pMaxNew[dim-2] + v; 3996 } 3997 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 3998 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 3999 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4000 coneNew[0] = newp; 4001 coneNew[1] = splitp; 4002 for (q = 0; q < coneSize; ++q) { 4003 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4004 } 4005 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4006 4007 4008 for (s = 0; s < supportSize; ++s) { 4009 PetscInt val; 4010 4011 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4012 if (val < 0) { 4013 /* Split old face: Replace negative side cell with cohesive cell */ 4014 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4015 } else { 4016 /* Split new face: Replace positive side cell with cohesive cell */ 4017 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4018 } 4019 } 4020 } else if (dep == 0) { 4021 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4022 4023 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4024 for (e = 0, q = 0; e < supportSize; ++e) { 4025 PetscInt val; 4026 4027 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4028 if ((val == 1) || (val == (shift + 1))) { 4029 supportNew[q++] = depthOffset[1] + support[e]; 4030 } 4031 } 4032 supportNew[q] = cedge; 4033 4034 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4035 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4036 for (e = 0, q = 0; e < supportSize; ++e) { 4037 PetscInt val, edge; 4038 4039 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4040 if (val == 1) { 4041 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4042 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4043 supportNew[q++] = pMaxNew[1] + edge; 4044 } else if (val == -(shift + 1)) { 4045 supportNew[q++] = depthOffset[1] + support[e]; 4046 } 4047 } 4048 supportNew[q] = cedge; 4049 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4050 /* Cohesive edge: Old and new split vertex, punting on support */ 4051 coneNew[0] = newp; 4052 coneNew[1] = splitp; 4053 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4054 } else if (dep == dim-2) { 4055 /* Split old edge: old vertices in cone so no change */ 4056 /* Split new edge: new vertices in cone */ 4057 for (q = 0; q < coneSize; ++q) { 4058 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4059 4060 coneNew[q] = pMaxNew[dim-3] + v; 4061 } 4062 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4063 /* Split old edge: Faces in positive side cells and old split faces */ 4064 for (e = 0, q = 0; e < supportSize; ++e) { 4065 PetscInt val; 4066 4067 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4068 if ((val == dim-1) || (val == (shift + dim-1))) { 4069 supportNew[q++] = depthOffset[dim-1] + support[e]; 4070 } 4071 } 4072 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4073 /* Split new edge: Faces in negative side cells and new split faces */ 4074 for (e = 0, q = 0; e < supportSize; ++e) { 4075 PetscInt val, face; 4076 4077 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4078 if (val == dim-1) { 4079 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4080 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4081 supportNew[q++] = pMaxNew[dim-1] + face; 4082 } else if (val == -(shift + dim-1)) { 4083 supportNew[q++] = depthOffset[dim-1] + support[e]; 4084 } 4085 } 4086 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4087 } 4088 } 4089 } 4090 /* Step 6b: Replace split points in negative side cones */ 4091 for (sp = 0; sp < numSP; ++sp) { 4092 PetscInt dep = values[sp]; 4093 IS pIS; 4094 PetscInt numPoints; 4095 const PetscInt *points; 4096 4097 if (dep >= 0) continue; 4098 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4099 if (!pIS) continue; 4100 dep = -dep - shift; 4101 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4102 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4103 for (p = 0; p < numPoints; ++p) { 4104 const PetscInt oldp = points[p]; 4105 const PetscInt newp = depthOffset[dep] + oldp; 4106 const PetscInt *cone; 4107 PetscInt coneSize, c; 4108 PetscBool replaced = PETSC_FALSE; 4109 4110 /* Negative edge: replace split vertex */ 4111 /* Negative cell: replace split face */ 4112 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4113 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4114 for (c = 0; c < coneSize; ++c) { 4115 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4116 PetscInt csplitp, cp, val; 4117 4118 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4119 if (val == dep-1) { 4120 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4121 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4122 csplitp = pMaxNew[dep-1] + cp; 4123 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4124 replaced = PETSC_TRUE; 4125 } 4126 } 4127 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4128 } 4129 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4130 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4131 } 4132 /* Step 7: Stratify */ 4133 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4134 /* Step 8: Coordinates */ 4135 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4136 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4137 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4138 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4139 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4140 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4141 const PetscInt splitp = pMaxNew[0] + v; 4142 PetscInt dof, off, soff, d; 4143 4144 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4145 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4146 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4147 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4148 } 4149 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4150 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4151 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4152 /* Step 10: Labels */ 4153 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4154 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4155 for (dep = 0; dep <= depth; ++dep) { 4156 for (p = 0; p < numSplitPoints[dep]; ++p) { 4157 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4158 const PetscInt splitp = pMaxNew[dep] + p; 4159 PetscInt l; 4160 4161 for (l = 0; l < numLabels; ++l) { 4162 DMLabel mlabel; 4163 const char *lname; 4164 PetscInt val; 4165 4166 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4167 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4168 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4169 if (val >= 0) { 4170 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4171 if (dep == 0) { 4172 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4173 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4174 } 4175 } 4176 } 4177 } 4178 } 4179 for (sp = 0; sp < numSP; ++sp) { 4180 const PetscInt dep = values[sp]; 4181 4182 if ((dep < 0) || (dep > depth)) continue; 4183 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4184 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4185 } 4186 if (label) { 4187 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4188 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4189 } 4190 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4191 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4192 PetscFunctionReturn(0); 4193 } 4194 4195 #undef __FUNCT__ 4196 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4197 /*@C 4198 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4199 4200 Collective on dm 4201 4202 Input Parameters: 4203 + dm - The original DM 4204 - labelName - The label specifying the boundary faces (this could be auto-generated) 4205 4206 Output Parameters: 4207 - dmSplit - The new DM 4208 4209 Level: developer 4210 4211 .seealso: DMCreate() 4212 */ 4213 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4214 { 4215 DM sdm; 4216 PetscInt dim; 4217 PetscErrorCode ierr; 4218 4219 PetscFunctionBegin; 4220 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4221 PetscValidPointer(dmSplit, 4); 4222 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 4223 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4224 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4225 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4226 switch (dim) { 4227 case 2: 4228 case 3: 4229 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4230 break; 4231 default: 4232 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4233 } 4234 *dmSplit = sdm; 4235 PetscFunctionReturn(0); 4236 } 4237 4238 #undef __FUNCT__ 4239 #define __FUNCT__ "DMLabelCohesiveComplete" 4240 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4241 { 4242 IS dimIS; 4243 const PetscInt *points; 4244 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4245 PetscErrorCode ierr; 4246 4247 PetscFunctionBegin; 4248 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4249 /* Cell orientation for face gives the side of the fault */ 4250 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4251 if (!dimIS) PetscFunctionReturn(0); 4252 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4253 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4254 for (p = 0; p < numPoints; ++p) { 4255 const PetscInt *support; 4256 PetscInt supportSize, s; 4257 4258 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4259 if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4260 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4261 for (s = 0; s < supportSize; ++s) { 4262 const PetscInt *cone, *ornt; 4263 PetscInt coneSize, c; 4264 PetscBool pos = PETSC_TRUE; 4265 4266 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4267 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4268 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4269 for (c = 0; c < coneSize; ++c) { 4270 if (cone[c] == points[p]) { 4271 if (ornt[c] >= 0) { 4272 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4273 } else { 4274 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4275 pos = PETSC_FALSE; 4276 } 4277 break; 4278 } 4279 } 4280 if (c == coneSize) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]); 4281 /* Put faces touching the fault in the label */ 4282 for (c = 0; c < coneSize; ++c) { 4283 const PetscInt point = cone[c]; 4284 4285 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4286 if (val == -1) { 4287 PetscInt *closure = NULL; 4288 PetscInt closureSize, cl; 4289 4290 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4291 for (cl = 0; cl < closureSize*2; cl += 2) { 4292 const PetscInt clp = closure[cl]; 4293 4294 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4295 if ((val >= 0) && (val < dim-1)) { 4296 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4297 break; 4298 } 4299 } 4300 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4301 } 4302 } 4303 } 4304 } 4305 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4306 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4307 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4308 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4309 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4310 if (!dimIS) PetscFunctionReturn(0); 4311 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4312 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4313 for (p = 0; p < numPoints; ++p) { 4314 PetscInt *star = NULL; 4315 PetscInt starSize, s; 4316 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4317 4318 /* First mark cells connected to the fault */ 4319 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4320 while (again) { 4321 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4322 again = 0; 4323 for (s = 0; s < starSize*2; s += 2) { 4324 const PetscInt point = star[s]; 4325 const PetscInt *cone; 4326 PetscInt coneSize, c; 4327 4328 if ((point < cStart) || (point >= cEnd)) continue; 4329 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4330 if (val != -1) continue; 4331 again = 2; 4332 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4333 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4334 for (c = 0; c < coneSize; ++c) { 4335 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4336 if (val != -1) { 4337 if (abs(val) < shift) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 4338 if (val > 0) { 4339 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4340 } else { 4341 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4342 } 4343 again = 1; 4344 break; 4345 } 4346 } 4347 } 4348 } 4349 /* Classify the rest by cell membership */ 4350 for (s = 0; s < starSize*2; s += 2) { 4351 const PetscInt point = star[s]; 4352 4353 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4354 if (val == -1) { 4355 PetscInt *sstar = NULL; 4356 PetscInt sstarSize, ss; 4357 PetscBool marked = PETSC_FALSE; 4358 4359 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4360 for (ss = 0; ss < sstarSize*2; ss += 2) { 4361 const PetscInt spoint = sstar[ss]; 4362 4363 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4364 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4365 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4366 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4367 if (val > 0) { 4368 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4369 } else { 4370 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4371 } 4372 marked = PETSC_TRUE; 4373 break; 4374 } 4375 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4376 if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 4377 } 4378 } 4379 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4380 } 4381 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4382 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4383 PetscFunctionReturn(0); 4384 } 4385 4386 #undef __FUNCT__ 4387 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4388 /* 4389 This takes as input the common mesh generator output, a list of the vertices for each cell 4390 */ 4391 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4392 { 4393 PetscInt *cone, c, p; 4394 PetscErrorCode ierr; 4395 4396 PetscFunctionBegin; 4397 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4398 for (c = 0; c < numCells; ++c) { 4399 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4400 } 4401 ierr = DMSetUp(dm);CHKERRQ(ierr); 4402 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4403 for (c = 0; c < numCells; ++c) { 4404 for (p = 0; p < numCorners; ++p) { 4405 cone[p] = cells[c*numCorners+p]+numCells; 4406 } 4407 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4408 } 4409 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4410 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4411 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4412 PetscFunctionReturn(0); 4413 } 4414 4415 #undef __FUNCT__ 4416 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4417 /* 4418 This takes as input the coordinates for each vertex 4419 */ 4420 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4421 { 4422 PetscSection coordSection; 4423 Vec coordinates; 4424 PetscScalar *coords; 4425 PetscInt coordSize, v, d; 4426 PetscErrorCode ierr; 4427 4428 PetscFunctionBegin; 4429 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4430 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4431 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4432 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4433 for (v = numCells; v < numCells+numVertices; ++v) { 4434 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4435 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4436 } 4437 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4438 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4439 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4440 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4441 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4442 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4443 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4444 for (v = 0; v < numVertices; ++v) { 4445 for (d = 0; d < spaceDim; ++d) { 4446 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4447 } 4448 } 4449 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4450 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4451 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4452 PetscFunctionReturn(0); 4453 } 4454 4455 #undef __FUNCT__ 4456 #define __FUNCT__ "DMPlexCreateFromCellList" 4457 /* 4458 This takes as input the common mesh generator output, a list of the vertices for each cell 4459 */ 4460 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4461 { 4462 PetscErrorCode ierr; 4463 4464 PetscFunctionBegin; 4465 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4466 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4467 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4468 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4469 if (interpolate) { 4470 DM idm; 4471 4472 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 4473 ierr = DMDestroy(dm);CHKERRQ(ierr); 4474 *dm = idm; 4475 } 4476 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4477 PetscFunctionReturn(0); 4478 } 4479 4480 #undef __FUNCT__ 4481 #define __FUNCT__ "DMPlexCreateFromDAG" 4482 /* 4483 This takes as input the raw Hasse Diagram data 4484 */ 4485 PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 4486 { 4487 Vec coordinates; 4488 PetscSection coordSection; 4489 PetscScalar *coords; 4490 PetscInt coordSize, firstVertex = numPoints[depth], pStart = 0, pEnd = 0, p, v, dim, d, off; 4491 PetscErrorCode ierr; 4492 4493 PetscFunctionBegin; 4494 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4495 for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 4496 ierr = DMPlexSetChart(dm, pStart, pEnd);CHKERRQ(ierr); 4497 for (p = pStart; p < pEnd; ++p) { 4498 ierr = DMPlexSetConeSize(dm, p, coneSize[p-pStart]);CHKERRQ(ierr); 4499 } 4500 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 4501 for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) { 4502 ierr = DMPlexSetCone(dm, p, &cones[off]);CHKERRQ(ierr); 4503 ierr = DMPlexSetConeOrientation(dm, p, &coneOrientations[off]);CHKERRQ(ierr); 4504 } 4505 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4506 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4507 /* Build coordinates */ 4508 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4509 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);CHKERRQ(ierr); 4510 for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 4511 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 4512 } 4513 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4514 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4515 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4516 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4517 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4518 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4519 for (v = 0; v < numPoints[0]; ++v) { 4520 PetscInt off; 4521 4522 ierr = PetscSectionGetOffset(coordSection, v+firstVertex, &off);CHKERRQ(ierr); 4523 for (d = 0; d < dim; ++d) { 4524 coords[off+d] = vertexCoords[v*dim+d]; 4525 } 4526 } 4527 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4528 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4529 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4530 PetscFunctionReturn(0); 4531 } 4532 4533 #if defined(PETSC_HAVE_TRIANGLE) 4534 #include <triangle.h> 4535 4536 #undef __FUNCT__ 4537 #define __FUNCT__ "InitInput_Triangle" 4538 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4539 { 4540 PetscFunctionBegin; 4541 inputCtx->numberofpoints = 0; 4542 inputCtx->numberofpointattributes = 0; 4543 inputCtx->pointlist = NULL; 4544 inputCtx->pointattributelist = NULL; 4545 inputCtx->pointmarkerlist = NULL; 4546 inputCtx->numberofsegments = 0; 4547 inputCtx->segmentlist = NULL; 4548 inputCtx->segmentmarkerlist = NULL; 4549 inputCtx->numberoftriangleattributes = 0; 4550 inputCtx->trianglelist = NULL; 4551 inputCtx->numberofholes = 0; 4552 inputCtx->holelist = NULL; 4553 inputCtx->numberofregions = 0; 4554 inputCtx->regionlist = NULL; 4555 PetscFunctionReturn(0); 4556 } 4557 4558 #undef __FUNCT__ 4559 #define __FUNCT__ "InitOutput_Triangle" 4560 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4561 { 4562 PetscFunctionBegin; 4563 outputCtx->numberofpoints = 0; 4564 outputCtx->pointlist = NULL; 4565 outputCtx->pointattributelist = NULL; 4566 outputCtx->pointmarkerlist = NULL; 4567 outputCtx->numberoftriangles = 0; 4568 outputCtx->trianglelist = NULL; 4569 outputCtx->triangleattributelist = NULL; 4570 outputCtx->neighborlist = NULL; 4571 outputCtx->segmentlist = NULL; 4572 outputCtx->segmentmarkerlist = NULL; 4573 outputCtx->numberofedges = 0; 4574 outputCtx->edgelist = NULL; 4575 outputCtx->edgemarkerlist = NULL; 4576 PetscFunctionReturn(0); 4577 } 4578 4579 #undef __FUNCT__ 4580 #define __FUNCT__ "FiniOutput_Triangle" 4581 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4582 { 4583 PetscFunctionBegin; 4584 free(outputCtx->pointmarkerlist); 4585 free(outputCtx->edgelist); 4586 free(outputCtx->edgemarkerlist); 4587 free(outputCtx->trianglelist); 4588 free(outputCtx->neighborlist); 4589 PetscFunctionReturn(0); 4590 } 4591 4592 #undef __FUNCT__ 4593 #define __FUNCT__ "DMPlexGenerate_Triangle" 4594 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4595 { 4596 MPI_Comm comm; 4597 PetscInt dim = 2; 4598 const PetscBool createConvexHull = PETSC_FALSE; 4599 const PetscBool constrained = PETSC_FALSE; 4600 struct triangulateio in; 4601 struct triangulateio out; 4602 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4603 PetscMPIInt rank; 4604 PetscErrorCode ierr; 4605 4606 PetscFunctionBegin; 4607 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4608 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4609 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4610 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4611 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4612 4613 in.numberofpoints = vEnd - vStart; 4614 if (in.numberofpoints > 0) { 4615 PetscSection coordSection; 4616 Vec coordinates; 4617 PetscScalar *array; 4618 4619 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4620 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4621 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4622 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4623 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4624 for (v = vStart; v < vEnd; ++v) { 4625 const PetscInt idx = v - vStart; 4626 PetscInt off, d; 4627 4628 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4629 for (d = 0; d < dim; ++d) { 4630 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4631 } 4632 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4633 } 4634 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4635 } 4636 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4637 in.numberofsegments = eEnd - eStart; 4638 if (in.numberofsegments > 0) { 4639 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4640 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4641 for (e = eStart; e < eEnd; ++e) { 4642 const PetscInt idx = e - eStart; 4643 const PetscInt *cone; 4644 4645 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4646 4647 in.segmentlist[idx*2+0] = cone[0] - vStart; 4648 in.segmentlist[idx*2+1] = cone[1] - vStart; 4649 4650 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4651 } 4652 } 4653 #if 0 /* Do not currently support holes */ 4654 PetscReal *holeCoords; 4655 PetscInt h, d; 4656 4657 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4658 if (in.numberofholes > 0) { 4659 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4660 for (h = 0; h < in.numberofholes; ++h) { 4661 for (d = 0; d < dim; ++d) { 4662 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4663 } 4664 } 4665 } 4666 #endif 4667 if (!rank) { 4668 char args[32]; 4669 4670 /* Take away 'Q' for verbose output */ 4671 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4672 if (createConvexHull) { 4673 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4674 } 4675 if (constrained) { 4676 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4677 } 4678 triangulate(args, &in, &out, NULL); 4679 } 4680 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4681 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4682 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4683 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4684 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4685 4686 { 4687 const PetscInt numCorners = 3; 4688 const PetscInt numCells = out.numberoftriangles; 4689 const PetscInt numVertices = out.numberofpoints; 4690 const int *cells = out.trianglelist; 4691 const double *meshCoords = out.pointlist; 4692 4693 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4694 /* Set labels */ 4695 for (v = 0; v < numVertices; ++v) { 4696 if (out.pointmarkerlist[v]) { 4697 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4698 } 4699 } 4700 if (interpolate) { 4701 for (e = 0; e < out.numberofedges; e++) { 4702 if (out.edgemarkerlist[e]) { 4703 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4704 const PetscInt *edges; 4705 PetscInt numEdges; 4706 4707 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4708 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4709 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4710 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4711 } 4712 } 4713 } 4714 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4715 } 4716 #if 0 /* Do not currently support holes */ 4717 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4718 #endif 4719 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4720 PetscFunctionReturn(0); 4721 } 4722 4723 #undef __FUNCT__ 4724 #define __FUNCT__ "DMPlexRefine_Triangle" 4725 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4726 { 4727 MPI_Comm comm; 4728 PetscInt dim = 2; 4729 struct triangulateio in; 4730 struct triangulateio out; 4731 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4732 PetscMPIInt rank; 4733 PetscErrorCode ierr; 4734 4735 PetscFunctionBegin; 4736 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4737 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4738 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4739 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4740 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4741 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4742 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4743 4744 in.numberofpoints = vEnd - vStart; 4745 if (in.numberofpoints > 0) { 4746 PetscSection coordSection; 4747 Vec coordinates; 4748 PetscScalar *array; 4749 4750 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4751 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4752 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4753 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4754 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4755 for (v = vStart; v < vEnd; ++v) { 4756 const PetscInt idx = v - vStart; 4757 PetscInt off, d; 4758 4759 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4760 for (d = 0; d < dim; ++d) { 4761 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4762 } 4763 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4764 } 4765 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4766 } 4767 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4768 4769 in.numberofcorners = 3; 4770 in.numberoftriangles = cEnd - cStart; 4771 4772 in.trianglearealist = (double*) maxVolumes; 4773 if (in.numberoftriangles > 0) { 4774 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4775 for (c = cStart; c < cEnd; ++c) { 4776 const PetscInt idx = c - cStart; 4777 PetscInt *closure = NULL; 4778 PetscInt closureSize; 4779 4780 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4781 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4782 for (v = 0; v < 3; ++v) { 4783 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4784 } 4785 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4786 } 4787 } 4788 /* TODO: Segment markers are missing on input */ 4789 #if 0 /* Do not currently support holes */ 4790 PetscReal *holeCoords; 4791 PetscInt h, d; 4792 4793 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4794 if (in.numberofholes > 0) { 4795 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4796 for (h = 0; h < in.numberofholes; ++h) { 4797 for (d = 0; d < dim; ++d) { 4798 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4799 } 4800 } 4801 } 4802 #endif 4803 if (!rank) { 4804 char args[32]; 4805 4806 /* Take away 'Q' for verbose output */ 4807 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4808 triangulate(args, &in, &out, NULL); 4809 } 4810 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4811 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4812 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4813 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4814 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4815 4816 { 4817 const PetscInt numCorners = 3; 4818 const PetscInt numCells = out.numberoftriangles; 4819 const PetscInt numVertices = out.numberofpoints; 4820 const int *cells = out.trianglelist; 4821 const double *meshCoords = out.pointlist; 4822 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4823 4824 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4825 /* Set labels */ 4826 for (v = 0; v < numVertices; ++v) { 4827 if (out.pointmarkerlist[v]) { 4828 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4829 } 4830 } 4831 if (interpolate) { 4832 PetscInt e; 4833 4834 for (e = 0; e < out.numberofedges; e++) { 4835 if (out.edgemarkerlist[e]) { 4836 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4837 const PetscInt *edges; 4838 PetscInt numEdges; 4839 4840 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4841 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4842 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4843 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4844 } 4845 } 4846 } 4847 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4848 } 4849 #if 0 /* Do not currently support holes */ 4850 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4851 #endif 4852 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4853 PetscFunctionReturn(0); 4854 } 4855 #endif 4856 4857 #if defined(PETSC_HAVE_TETGEN) 4858 #include <tetgen.h> 4859 #undef __FUNCT__ 4860 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4861 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4862 { 4863 MPI_Comm comm; 4864 const PetscInt dim = 3; 4865 ::tetgenio in; 4866 ::tetgenio out; 4867 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4868 PetscMPIInt rank; 4869 PetscErrorCode ierr; 4870 4871 PetscFunctionBegin; 4872 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4873 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4874 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4875 in.numberofpoints = vEnd - vStart; 4876 if (in.numberofpoints > 0) { 4877 PetscSection coordSection; 4878 Vec coordinates; 4879 PetscScalar *array; 4880 4881 in.pointlist = new double[in.numberofpoints*dim]; 4882 in.pointmarkerlist = new int[in.numberofpoints]; 4883 4884 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4885 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4886 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4887 for (v = vStart; v < vEnd; ++v) { 4888 const PetscInt idx = v - vStart; 4889 PetscInt off, d; 4890 4891 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4892 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4893 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4894 } 4895 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4896 } 4897 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4898 4899 in.numberoffacets = fEnd - fStart; 4900 if (in.numberoffacets > 0) { 4901 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4902 in.facetmarkerlist = new int[in.numberoffacets]; 4903 for (f = fStart; f < fEnd; ++f) { 4904 const PetscInt idx = f - fStart; 4905 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 4906 4907 in.facetlist[idx].numberofpolygons = 1; 4908 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4909 in.facetlist[idx].numberofholes = 0; 4910 in.facetlist[idx].holelist = NULL; 4911 4912 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4913 for (p = 0; p < numPoints*2; p += 2) { 4914 const PetscInt point = points[p]; 4915 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 4916 } 4917 4918 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4919 poly->numberofvertices = numVertices; 4920 poly->vertexlist = new int[poly->numberofvertices]; 4921 for (v = 0; v < numVertices; ++v) { 4922 const PetscInt vIdx = points[v] - vStart; 4923 poly->vertexlist[v] = vIdx; 4924 } 4925 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4926 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4927 } 4928 } 4929 if (!rank) { 4930 char args[32]; 4931 4932 /* Take away 'Q' for verbose output */ 4933 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4934 ::tetrahedralize(args, &in, &out); 4935 } 4936 { 4937 const PetscInt numCorners = 4; 4938 const PetscInt numCells = out.numberoftetrahedra; 4939 const PetscInt numVertices = out.numberofpoints; 4940 const int *cells = out.tetrahedronlist; 4941 const double *meshCoords = out.pointlist; 4942 4943 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4944 /* Set labels */ 4945 for (v = 0; v < numVertices; ++v) { 4946 if (out.pointmarkerlist[v]) { 4947 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4948 } 4949 } 4950 if (interpolate) { 4951 PetscInt e; 4952 4953 for (e = 0; e < out.numberofedges; e++) { 4954 if (out.edgemarkerlist[e]) { 4955 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4956 const PetscInt *edges; 4957 PetscInt numEdges; 4958 4959 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4960 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4961 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4962 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4963 } 4964 } 4965 for (f = 0; f < out.numberoftrifaces; f++) { 4966 if (out.trifacemarkerlist[f]) { 4967 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4968 const PetscInt *faces; 4969 PetscInt numFaces; 4970 4971 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4972 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4973 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4974 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4975 } 4976 } 4977 } 4978 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4979 } 4980 PetscFunctionReturn(0); 4981 } 4982 4983 #undef __FUNCT__ 4984 #define __FUNCT__ "DMPlexRefine_Tetgen" 4985 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4986 { 4987 MPI_Comm comm; 4988 const PetscInt dim = 3; 4989 ::tetgenio in; 4990 ::tetgenio out; 4991 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4992 PetscMPIInt rank; 4993 PetscErrorCode ierr; 4994 4995 PetscFunctionBegin; 4996 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4997 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4998 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4999 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5000 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5001 5002 in.numberofpoints = vEnd - vStart; 5003 if (in.numberofpoints > 0) { 5004 PetscSection coordSection; 5005 Vec coordinates; 5006 PetscScalar *array; 5007 5008 in.pointlist = new double[in.numberofpoints*dim]; 5009 in.pointmarkerlist = new int[in.numberofpoints]; 5010 5011 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5012 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5013 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5014 for (v = vStart; v < vEnd; ++v) { 5015 const PetscInt idx = v - vStart; 5016 PetscInt off, d; 5017 5018 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5019 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5020 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5021 } 5022 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5023 } 5024 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5025 5026 in.numberofcorners = 4; 5027 in.numberoftetrahedra = cEnd - cStart; 5028 in.tetrahedronvolumelist = (double*) maxVolumes; 5029 if (in.numberoftetrahedra > 0) { 5030 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5031 for (c = cStart; c < cEnd; ++c) { 5032 const PetscInt idx = c - cStart; 5033 PetscInt *closure = NULL; 5034 PetscInt closureSize; 5035 5036 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5037 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5038 for (v = 0; v < 4; ++v) { 5039 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5040 } 5041 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5042 } 5043 } 5044 /* TODO: Put in boundary faces with markers */ 5045 if (!rank) { 5046 char args[32]; 5047 5048 /* Take away 'Q' for verbose output */ 5049 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5050 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5051 ::tetrahedralize(args, &in, &out); 5052 } 5053 in.tetrahedronvolumelist = NULL; 5054 5055 { 5056 const PetscInt numCorners = 4; 5057 const PetscInt numCells = out.numberoftetrahedra; 5058 const PetscInt numVertices = out.numberofpoints; 5059 const int *cells = out.tetrahedronlist; 5060 const double *meshCoords = out.pointlist; 5061 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5062 5063 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5064 /* Set labels */ 5065 for (v = 0; v < numVertices; ++v) { 5066 if (out.pointmarkerlist[v]) { 5067 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5068 } 5069 } 5070 if (interpolate) { 5071 PetscInt e, f; 5072 5073 for (e = 0; e < out.numberofedges; e++) { 5074 if (out.edgemarkerlist[e]) { 5075 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5076 const PetscInt *edges; 5077 PetscInt numEdges; 5078 5079 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5080 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5081 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5082 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5083 } 5084 } 5085 for (f = 0; f < out.numberoftrifaces; f++) { 5086 if (out.trifacemarkerlist[f]) { 5087 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5088 const PetscInt *faces; 5089 PetscInt numFaces; 5090 5091 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5092 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5093 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5094 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5095 } 5096 } 5097 } 5098 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5099 } 5100 PetscFunctionReturn(0); 5101 } 5102 #endif 5103 5104 #if defined(PETSC_HAVE_CTETGEN) 5105 #include "ctetgen.h" 5106 5107 #undef __FUNCT__ 5108 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5109 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5110 { 5111 MPI_Comm comm; 5112 const PetscInt dim = 3; 5113 PLC *in, *out; 5114 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5115 PetscMPIInt rank; 5116 PetscErrorCode ierr; 5117 5118 PetscFunctionBegin; 5119 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5120 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5121 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5122 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5123 ierr = PLCCreate(&in);CHKERRQ(ierr); 5124 ierr = PLCCreate(&out);CHKERRQ(ierr); 5125 5126 in->numberofpoints = vEnd - vStart; 5127 if (in->numberofpoints > 0) { 5128 PetscSection coordSection; 5129 Vec coordinates; 5130 PetscScalar *array; 5131 5132 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5133 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5134 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5135 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5136 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5137 for (v = vStart; v < vEnd; ++v) { 5138 const PetscInt idx = v - vStart; 5139 PetscInt off, d, m; 5140 5141 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5142 for (d = 0; d < dim; ++d) { 5143 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5144 } 5145 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5146 5147 in->pointmarkerlist[idx] = (int) m; 5148 } 5149 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5150 } 5151 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5152 5153 in->numberoffacets = fEnd - fStart; 5154 if (in->numberoffacets > 0) { 5155 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5156 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5157 for (f = fStart; f < fEnd; ++f) { 5158 const PetscInt idx = f - fStart; 5159 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5160 polygon *poly; 5161 5162 in->facetlist[idx].numberofpolygons = 1; 5163 5164 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5165 5166 in->facetlist[idx].numberofholes = 0; 5167 in->facetlist[idx].holelist = NULL; 5168 5169 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5170 for (p = 0; p < numPoints*2; p += 2) { 5171 const PetscInt point = points[p]; 5172 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5173 } 5174 5175 poly = in->facetlist[idx].polygonlist; 5176 poly->numberofvertices = numVertices; 5177 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5178 for (v = 0; v < numVertices; ++v) { 5179 const PetscInt vIdx = points[v] - vStart; 5180 poly->vertexlist[v] = vIdx; 5181 } 5182 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5183 in->facetmarkerlist[idx] = (int) m; 5184 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5185 } 5186 } 5187 if (!rank) { 5188 TetGenOpts t; 5189 5190 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5191 t.in = boundary; /* Should go away */ 5192 t.plc = 1; 5193 t.quality = 1; 5194 t.edgesout = 1; 5195 t.zeroindex = 1; 5196 t.quiet = 1; 5197 t.verbose = verbose; 5198 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5199 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5200 } 5201 { 5202 const PetscInt numCorners = 4; 5203 const PetscInt numCells = out->numberoftetrahedra; 5204 const PetscInt numVertices = out->numberofpoints; 5205 const int *cells = out->tetrahedronlist; 5206 const double *meshCoords = out->pointlist; 5207 5208 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5209 /* Set labels */ 5210 for (v = 0; v < numVertices; ++v) { 5211 if (out->pointmarkerlist[v]) { 5212 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5213 } 5214 } 5215 if (interpolate) { 5216 PetscInt e; 5217 5218 for (e = 0; e < out->numberofedges; e++) { 5219 if (out->edgemarkerlist[e]) { 5220 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5221 const PetscInt *edges; 5222 PetscInt numEdges; 5223 5224 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5225 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5226 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5227 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5228 } 5229 } 5230 for (f = 0; f < out->numberoftrifaces; f++) { 5231 if (out->trifacemarkerlist[f]) { 5232 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5233 const PetscInt *faces; 5234 PetscInt numFaces; 5235 5236 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5237 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5238 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5239 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5240 } 5241 } 5242 } 5243 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5244 } 5245 5246 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5247 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5248 PetscFunctionReturn(0); 5249 } 5250 5251 #undef __FUNCT__ 5252 #define __FUNCT__ "DMPlexRefine_CTetgen" 5253 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5254 { 5255 MPI_Comm comm; 5256 const PetscInt dim = 3; 5257 PLC *in, *out; 5258 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5259 PetscMPIInt rank; 5260 PetscErrorCode ierr; 5261 5262 PetscFunctionBegin; 5263 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5264 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5265 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5266 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5267 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5268 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5269 ierr = PLCCreate(&in);CHKERRQ(ierr); 5270 ierr = PLCCreate(&out);CHKERRQ(ierr); 5271 5272 in->numberofpoints = vEnd - vStart; 5273 if (in->numberofpoints > 0) { 5274 PetscSection coordSection; 5275 Vec coordinates; 5276 PetscScalar *array; 5277 5278 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5279 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5280 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5281 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5282 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5283 for (v = vStart; v < vEnd; ++v) { 5284 const PetscInt idx = v - vStart; 5285 PetscInt off, d, m; 5286 5287 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5288 for (d = 0; d < dim; ++d) { 5289 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5290 } 5291 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5292 5293 in->pointmarkerlist[idx] = (int) m; 5294 } 5295 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5296 } 5297 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5298 5299 in->numberofcorners = 4; 5300 in->numberoftetrahedra = cEnd - cStart; 5301 in->tetrahedronvolumelist = maxVolumes; 5302 if (in->numberoftetrahedra > 0) { 5303 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5304 for (c = cStart; c < cEnd; ++c) { 5305 const PetscInt idx = c - cStart; 5306 PetscInt *closure = NULL; 5307 PetscInt closureSize; 5308 5309 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5310 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5311 for (v = 0; v < 4; ++v) { 5312 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5313 } 5314 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5315 } 5316 } 5317 if (!rank) { 5318 TetGenOpts t; 5319 5320 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5321 5322 t.in = dm; /* Should go away */ 5323 t.refine = 1; 5324 t.varvolume = 1; 5325 t.quality = 1; 5326 t.edgesout = 1; 5327 t.zeroindex = 1; 5328 t.quiet = 1; 5329 t.verbose = verbose; /* Change this */ 5330 5331 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5332 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5333 } 5334 { 5335 const PetscInt numCorners = 4; 5336 const PetscInt numCells = out->numberoftetrahedra; 5337 const PetscInt numVertices = out->numberofpoints; 5338 const int *cells = out->tetrahedronlist; 5339 const double *meshCoords = out->pointlist; 5340 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5341 5342 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5343 /* Set labels */ 5344 for (v = 0; v < numVertices; ++v) { 5345 if (out->pointmarkerlist[v]) { 5346 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5347 } 5348 } 5349 if (interpolate) { 5350 PetscInt e, f; 5351 5352 for (e = 0; e < out->numberofedges; e++) { 5353 if (out->edgemarkerlist[e]) { 5354 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5355 const PetscInt *edges; 5356 PetscInt numEdges; 5357 5358 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5359 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5360 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5361 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5362 } 5363 } 5364 for (f = 0; f < out->numberoftrifaces; f++) { 5365 if (out->trifacemarkerlist[f]) { 5366 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5367 const PetscInt *faces; 5368 PetscInt numFaces; 5369 5370 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5371 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5372 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5373 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5374 } 5375 } 5376 } 5377 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5378 } 5379 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5380 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5381 PetscFunctionReturn(0); 5382 } 5383 #endif 5384 5385 #undef __FUNCT__ 5386 #define __FUNCT__ "DMPlexGenerate" 5387 /*@C 5388 DMPlexGenerate - Generates a mesh. 5389 5390 Not Collective 5391 5392 Input Parameters: 5393 + boundary - The DMPlex boundary object 5394 . name - The mesh generation package name 5395 - interpolate - Flag to create intermediate mesh elements 5396 5397 Output Parameter: 5398 . mesh - The DMPlex object 5399 5400 Level: intermediate 5401 5402 .keywords: mesh, elements 5403 .seealso: DMPlexCreate(), DMRefine() 5404 @*/ 5405 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5406 { 5407 PetscInt dim; 5408 char genname[1024]; 5409 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5410 PetscErrorCode ierr; 5411 5412 PetscFunctionBegin; 5413 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5414 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5415 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5416 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5417 if (flg) name = genname; 5418 if (name) { 5419 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5420 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5421 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5422 } 5423 switch (dim) { 5424 case 1: 5425 if (!name || isTriangle) { 5426 #if defined(PETSC_HAVE_TRIANGLE) 5427 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5428 #else 5429 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5430 #endif 5431 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5432 break; 5433 case 2: 5434 if (!name || isCTetgen) { 5435 #if defined(PETSC_HAVE_CTETGEN) 5436 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5437 #else 5438 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5439 #endif 5440 } else if (isTetgen) { 5441 #if defined(PETSC_HAVE_TETGEN) 5442 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5443 #else 5444 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5445 #endif 5446 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5447 break; 5448 default: 5449 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5450 } 5451 PetscFunctionReturn(0); 5452 } 5453 5454 typedef PetscInt CellRefiner; 5455 5456 #undef __FUNCT__ 5457 #define __FUNCT__ "GetDepthStart_Private" 5458 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5459 { 5460 PetscFunctionBegin; 5461 if (cStart) *cStart = 0; 5462 if (vStart) *vStart = depthSize[depth]; 5463 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5464 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5465 PetscFunctionReturn(0); 5466 } 5467 5468 #undef __FUNCT__ 5469 #define __FUNCT__ "GetDepthEnd_Private" 5470 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5471 { 5472 PetscFunctionBegin; 5473 if (cEnd) *cEnd = depthSize[depth]; 5474 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5475 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5476 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5477 PetscFunctionReturn(0); 5478 } 5479 5480 #undef __FUNCT__ 5481 #define __FUNCT__ "CellRefinerGetSizes" 5482 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5483 { 5484 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5485 PetscErrorCode ierr; 5486 5487 PetscFunctionBegin; 5488 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5489 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5490 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5491 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5492 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5493 switch (refiner) { 5494 case 1: 5495 /* Simplicial 2D */ 5496 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5497 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5498 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5499 break; 5500 case 3: 5501 /* Hybrid 2D */ 5502 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5503 cMax = PetscMin(cEnd, cMax); 5504 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5505 fMax = PetscMin(fEnd, fMax); 5506 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5507 depthSize[1] = 2*(fMax - fStart) + 3*(cMax - cStart) + (fEnd - fMax) + (cEnd - cMax); /* Every interior face is split into 2 faces, 3 faces are added for each interior cell, and one in each hybrid cell */ 5508 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5509 break; 5510 case 2: 5511 /* Hex 2D */ 5512 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5513 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5514 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5515 break; 5516 default: 5517 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5518 } 5519 PetscFunctionReturn(0); 5520 } 5521 5522 #undef __FUNCT__ 5523 #define __FUNCT__ "CellRefinerSetConeSizes" 5524 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5525 { 5526 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5527 PetscErrorCode ierr; 5528 5529 PetscFunctionBegin; 5530 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5531 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5532 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5533 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5534 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5535 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5536 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5537 switch (refiner) { 5538 case 1: 5539 /* Simplicial 2D */ 5540 /* All cells have 3 faces */ 5541 for (c = cStart; c < cEnd; ++c) { 5542 for (r = 0; r < 4; ++r) { 5543 const PetscInt newp = (c - cStart)*4 + r; 5544 5545 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5546 } 5547 } 5548 /* Split faces have 2 vertices and the same cells as the parent */ 5549 for (f = fStart; f < fEnd; ++f) { 5550 for (r = 0; r < 2; ++r) { 5551 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5552 PetscInt size; 5553 5554 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5555 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5556 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5557 } 5558 } 5559 /* Interior faces have 2 vertices and 2 cells */ 5560 for (c = cStart; c < cEnd; ++c) { 5561 for (r = 0; r < 3; ++r) { 5562 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5563 5564 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5565 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5566 } 5567 } 5568 /* Old vertices have identical supports */ 5569 for (v = vStart; v < vEnd; ++v) { 5570 const PetscInt newp = vStartNew + (v - vStart); 5571 PetscInt size; 5572 5573 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5574 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5575 } 5576 /* Face vertices have 2 + cells*2 supports */ 5577 for (f = fStart; f < fEnd; ++f) { 5578 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5579 PetscInt size; 5580 5581 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5582 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5583 } 5584 break; 5585 case 2: 5586 /* Hex 2D */ 5587 /* All cells have 4 faces */ 5588 for (c = cStart; c < cEnd; ++c) { 5589 for (r = 0; r < 4; ++r) { 5590 const PetscInt newp = (c - cStart)*4 + r; 5591 5592 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5593 } 5594 } 5595 /* Split faces have 2 vertices and the same cells as the parent */ 5596 for (f = fStart; f < fEnd; ++f) { 5597 for (r = 0; r < 2; ++r) { 5598 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5599 PetscInt size; 5600 5601 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5602 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5603 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5604 } 5605 } 5606 /* Interior faces have 2 vertices and 2 cells */ 5607 for (c = cStart; c < cEnd; ++c) { 5608 for (r = 0; r < 4; ++r) { 5609 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5610 5611 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5612 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5613 } 5614 } 5615 /* Old vertices have identical supports */ 5616 for (v = vStart; v < vEnd; ++v) { 5617 const PetscInt newp = vStartNew + (v - vStart); 5618 PetscInt size; 5619 5620 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5621 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5622 } 5623 /* Face vertices have 2 + cells supports */ 5624 for (f = fStart; f < fEnd; ++f) { 5625 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5626 PetscInt size; 5627 5628 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5629 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5630 } 5631 /* Cell vertices have 4 supports */ 5632 for (c = cStart; c < cEnd; ++c) { 5633 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5634 5635 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5636 } 5637 break; 5638 case 3: 5639 /* Hybrid 2D */ 5640 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5641 cMax = PetscMin(cEnd, cMax); 5642 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5643 fMax = PetscMin(fEnd, fMax); 5644 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5645 /* Interior cells have 3 faces */ 5646 for (c = cStart; c < cMax; ++c) { 5647 for (r = 0; r < 4; ++r) { 5648 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5649 5650 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5651 } 5652 } 5653 /* Hybrid cells have 4 faces */ 5654 for (c = cMax; c < cEnd; ++c) { 5655 for (r = 0; r < 2; ++r) { 5656 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5657 5658 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5659 } 5660 } 5661 /* Interior split faces have 2 vertices and the same cells as the parent */ 5662 for (f = fStart; f < fMax; ++f) { 5663 for (r = 0; r < 2; ++r) { 5664 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5665 PetscInt size; 5666 5667 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5668 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5669 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5670 } 5671 } 5672 /* Interior cell faces have 2 vertices and 2 cells */ 5673 for (c = cStart; c < cMax; ++c) { 5674 for (r = 0; r < 3; ++r) { 5675 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5676 5677 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5678 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5679 } 5680 } 5681 /* Hybrid faces have 2 vertices and the same cells */ 5682 for (f = fMax; f < fEnd; ++f) { 5683 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5684 PetscInt size; 5685 5686 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5687 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5688 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5689 } 5690 /* Hybrid cell faces have 2 vertices and 2 cells */ 5691 for (c = cMax; c < cEnd; ++c) { 5692 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5693 5694 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5695 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5696 } 5697 /* Old vertices have identical supports */ 5698 for (v = vStart; v < vEnd; ++v) { 5699 const PetscInt newp = vStartNew + (v - vStart); 5700 PetscInt size; 5701 5702 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5703 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5704 } 5705 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5706 for (f = fStart; f < fMax; ++f) { 5707 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5708 const PetscInt *support; 5709 PetscInt size, newSize = 2, s; 5710 5711 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5712 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5713 for (s = 0; s < size; ++s) { 5714 if (support[s] >= cMax) newSize += 1; 5715 else newSize += 2; 5716 } 5717 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5718 } 5719 break; 5720 default: 5721 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5722 } 5723 PetscFunctionReturn(0); 5724 } 5725 5726 #undef __FUNCT__ 5727 #define __FUNCT__ "CellRefinerSetCones" 5728 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5729 { 5730 PetscInt depth, cStart, cEnd, cMax, cStartNew, cEndNew, c, vStart, vEnd, vMax, vStartNew, vEndNew, v, fStart, fEnd, fMax, fStartNew, fEndNew, f, eStart, eEnd, eMax, eStartNew, eEndNew, r, p; 5731 PetscInt maxSupportSize, *supportRef; 5732 PetscErrorCode ierr; 5733 5734 PetscFunctionBegin; 5735 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5736 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5737 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5738 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5739 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5740 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5741 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5742 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5743 switch (refiner) { 5744 case 1: 5745 /* Simplicial 2D */ 5746 /* 5747 2 5748 |\ 5749 | \ 5750 | \ 5751 | \ 5752 | C \ 5753 | \ 5754 | \ 5755 2---1---1 5756 |\ D / \ 5757 | 2 0 \ 5758 |A \ / B \ 5759 0---0-------1 5760 */ 5761 /* All cells have 3 faces */ 5762 for (c = cStart; c < cEnd; ++c) { 5763 const PetscInt newp = cStartNew + (c - cStart)*4; 5764 const PetscInt *cone, *ornt; 5765 PetscInt coneNew[3], orntNew[3]; 5766 5767 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5768 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5769 /* A triangle */ 5770 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5771 orntNew[0] = ornt[0]; 5772 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5773 orntNew[1] = -2; 5774 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5775 orntNew[2] = ornt[2]; 5776 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5777 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5778 #if 1 5779 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5780 for (p = 0; p < 3; ++p) { 5781 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5782 } 5783 #endif 5784 /* B triangle */ 5785 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5786 orntNew[0] = ornt[0]; 5787 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5788 orntNew[1] = ornt[1]; 5789 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5790 orntNew[2] = -2; 5791 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5792 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5793 #if 1 5794 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 5795 for (p = 0; p < 3; ++p) { 5796 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5797 } 5798 #endif 5799 /* C triangle */ 5800 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5801 orntNew[0] = -2; 5802 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5803 orntNew[1] = ornt[1]; 5804 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5805 orntNew[2] = ornt[2]; 5806 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5807 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5808 #if 1 5809 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 5810 for (p = 0; p < 3; ++p) { 5811 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5812 } 5813 #endif 5814 /* D triangle */ 5815 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5816 orntNew[0] = 0; 5817 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5818 orntNew[1] = 0; 5819 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5820 orntNew[2] = 0; 5821 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5822 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5823 #if 1 5824 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 5825 for (p = 0; p < 3; ++p) { 5826 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5827 } 5828 #endif 5829 } 5830 /* Split faces have 2 vertices and the same cells as the parent */ 5831 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5832 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5833 for (f = fStart; f < fEnd; ++f) { 5834 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5835 5836 for (r = 0; r < 2; ++r) { 5837 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5838 const PetscInt *cone, *support; 5839 PetscInt coneNew[2], coneSize, c, supportSize, s; 5840 5841 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5842 coneNew[0] = vStartNew + (cone[0] - vStart); 5843 coneNew[1] = vStartNew + (cone[1] - vStart); 5844 coneNew[(r+1)%2] = newv; 5845 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5846 #if 1 5847 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5848 for (p = 0; p < 2; ++p) { 5849 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5850 } 5851 #endif 5852 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5853 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5854 for (s = 0; s < supportSize; ++s) { 5855 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5856 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5857 for (c = 0; c < coneSize; ++c) { 5858 if (cone[c] == f) break; 5859 } 5860 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5861 } 5862 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5863 #if 1 5864 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5865 for (p = 0; p < supportSize; ++p) { 5866 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 5867 } 5868 #endif 5869 } 5870 } 5871 /* Interior faces have 2 vertices and 2 cells */ 5872 for (c = cStart; c < cEnd; ++c) { 5873 const PetscInt *cone; 5874 5875 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5876 for (r = 0; r < 3; ++r) { 5877 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5878 PetscInt coneNew[2]; 5879 PetscInt supportNew[2]; 5880 5881 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5882 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5883 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5884 #if 1 5885 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5886 for (p = 0; p < 2; ++p) { 5887 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5888 } 5889 #endif 5890 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5891 supportNew[1] = (c - cStart)*4 + 3; 5892 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5893 #if 1 5894 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5895 for (p = 0; p < 2; ++p) { 5896 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5897 } 5898 #endif 5899 } 5900 } 5901 /* Old vertices have identical supports */ 5902 for (v = vStart; v < vEnd; ++v) { 5903 const PetscInt newp = vStartNew + (v - vStart); 5904 const PetscInt *support, *cone; 5905 PetscInt size, s; 5906 5907 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5908 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5909 for (s = 0; s < size; ++s) { 5910 PetscInt r = 0; 5911 5912 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5913 if (cone[1] == v) r = 1; 5914 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5915 } 5916 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5917 #if 1 5918 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5919 for (p = 0; p < size; ++p) { 5920 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5921 } 5922 #endif 5923 } 5924 /* Face vertices have 2 + cells*2 supports */ 5925 for (f = fStart; f < fEnd; ++f) { 5926 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5927 const PetscInt *cone, *support; 5928 PetscInt size, s; 5929 5930 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5931 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5932 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5933 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5934 for (s = 0; s < size; ++s) { 5935 PetscInt r = 0; 5936 5937 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5938 if (cone[1] == f) r = 1; 5939 else if (cone[2] == f) r = 2; 5940 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5941 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5942 } 5943 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5944 #if 1 5945 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5946 for (p = 0; p < 2+size*2; ++p) { 5947 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5948 } 5949 #endif 5950 } 5951 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5952 break; 5953 case 2: 5954 /* Hex 2D */ 5955 /* 5956 3---------2---------2 5957 | | | 5958 | D 2 C | 5959 | | | 5960 3----3----0----1----1 5961 | | | 5962 | A 0 B | 5963 | | | 5964 0---------0---------1 5965 */ 5966 /* All cells have 4 faces */ 5967 for (c = cStart; c < cEnd; ++c) { 5968 const PetscInt newp = (c - cStart)*4; 5969 const PetscInt *cone, *ornt; 5970 PetscInt coneNew[4], orntNew[4]; 5971 5972 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5973 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5974 /* A quad */ 5975 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5976 orntNew[0] = ornt[0]; 5977 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5978 orntNew[1] = 0; 5979 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5980 orntNew[2] = -2; 5981 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5982 orntNew[3] = ornt[3]; 5983 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5984 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5985 #if 1 5986 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5987 for (p = 0; p < 4; ++p) { 5988 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5989 } 5990 #endif 5991 /* B quad */ 5992 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5993 orntNew[0] = ornt[0]; 5994 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5995 orntNew[1] = ornt[1]; 5996 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5997 orntNew[2] = 0; 5998 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5999 orntNew[3] = -2; 6000 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6001 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6002 #if 1 6003 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6004 for (p = 0; p < 4; ++p) { 6005 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6006 } 6007 #endif 6008 /* C quad */ 6009 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6010 orntNew[0] = -2; 6011 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6012 orntNew[1] = ornt[1]; 6013 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6014 orntNew[2] = ornt[2]; 6015 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6016 orntNew[3] = 0; 6017 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6018 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6019 #if 1 6020 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6021 for (p = 0; p < 4; ++p) { 6022 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6023 } 6024 #endif 6025 /* D quad */ 6026 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6027 orntNew[0] = 0; 6028 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6029 orntNew[1] = -2; 6030 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6031 orntNew[2] = ornt[2]; 6032 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6033 orntNew[3] = ornt[3]; 6034 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6035 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6036 #if 1 6037 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6038 for (p = 0; p < 4; ++p) { 6039 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6040 } 6041 #endif 6042 } 6043 /* Split faces have 2 vertices and the same cells as the parent */ 6044 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6045 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6046 for (f = fStart; f < fEnd; ++f) { 6047 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6048 6049 for (r = 0; r < 2; ++r) { 6050 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6051 const PetscInt *cone, *support; 6052 PetscInt coneNew[2], coneSize, c, supportSize, s; 6053 6054 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6055 coneNew[0] = vStartNew + (cone[0] - vStart); 6056 coneNew[1] = vStartNew + (cone[1] - vStart); 6057 coneNew[(r+1)%2] = newv; 6058 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6059 #if 1 6060 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6061 for (p = 0; p < 2; ++p) { 6062 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6063 } 6064 #endif 6065 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6066 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6067 for (s = 0; s < supportSize; ++s) { 6068 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6069 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6070 for (c = 0; c < coneSize; ++c) { 6071 if (cone[c] == f) break; 6072 } 6073 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6074 } 6075 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6076 #if 1 6077 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6078 for (p = 0; p < supportSize; ++p) { 6079 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6080 } 6081 #endif 6082 } 6083 } 6084 /* Interior faces have 2 vertices and 2 cells */ 6085 for (c = cStart; c < cEnd; ++c) { 6086 const PetscInt *cone; 6087 PetscInt coneNew[2], supportNew[2]; 6088 6089 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6090 for (r = 0; r < 4; ++r) { 6091 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6092 6093 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6094 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6095 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6096 #if 1 6097 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6098 for (p = 0; p < 2; ++p) { 6099 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6100 } 6101 #endif 6102 supportNew[0] = (c - cStart)*4 + r; 6103 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6104 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6105 #if 1 6106 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6107 for (p = 0; p < 2; ++p) { 6108 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6109 } 6110 #endif 6111 } 6112 } 6113 /* Old vertices have identical supports */ 6114 for (v = vStart; v < vEnd; ++v) { 6115 const PetscInt newp = vStartNew + (v - vStart); 6116 const PetscInt *support, *cone; 6117 PetscInt size, s; 6118 6119 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6120 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6121 for (s = 0; s < size; ++s) { 6122 PetscInt r = 0; 6123 6124 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6125 if (cone[1] == v) r = 1; 6126 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6127 } 6128 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6129 #if 1 6130 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6131 for (p = 0; p < size; ++p) { 6132 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6133 } 6134 #endif 6135 } 6136 /* Face vertices have 2 + cells supports */ 6137 for (f = fStart; f < fEnd; ++f) { 6138 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6139 const PetscInt *cone, *support; 6140 PetscInt size, s; 6141 6142 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6143 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6144 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6145 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6146 for (s = 0; s < size; ++s) { 6147 PetscInt r = 0; 6148 6149 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6150 if (cone[1] == f) r = 1; 6151 else if (cone[2] == f) r = 2; 6152 else if (cone[3] == f) r = 3; 6153 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6154 } 6155 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6156 #if 1 6157 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6158 for (p = 0; p < 2+size; ++p) { 6159 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6160 } 6161 #endif 6162 } 6163 /* Cell vertices have 4 supports */ 6164 for (c = cStart; c < cEnd; ++c) { 6165 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6166 PetscInt supportNew[4]; 6167 6168 for (r = 0; r < 4; ++r) { 6169 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6170 } 6171 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6172 } 6173 break; 6174 case 3: 6175 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6176 cMax = PetscMin(cEnd, cMax); 6177 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6178 fMax = PetscMin(fEnd, fMax); 6179 /* Interior cells have 3 faces */ 6180 for (c = cStart; c < cMax; ++c) { 6181 const PetscInt newp = cStartNew + (c - cStart)*4; 6182 const PetscInt *cone, *ornt; 6183 PetscInt coneNew[3], orntNew[3]; 6184 6185 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6186 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6187 /* A triangle */ 6188 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6189 orntNew[0] = ornt[0]; 6190 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6191 orntNew[1] = -2; 6192 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6193 orntNew[2] = ornt[2]; 6194 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6195 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6196 #if 1 6197 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6198 for (p = 0; p < 3; ++p) { 6199 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6200 } 6201 #endif 6202 /* B triangle */ 6203 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6204 orntNew[0] = ornt[0]; 6205 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6206 orntNew[1] = ornt[1]; 6207 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6208 orntNew[2] = -2; 6209 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6210 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6211 #if 1 6212 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6213 for (p = 0; p < 3; ++p) { 6214 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6215 } 6216 #endif 6217 /* C triangle */ 6218 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6219 orntNew[0] = -2; 6220 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6221 orntNew[1] = ornt[1]; 6222 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6223 orntNew[2] = ornt[2]; 6224 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6225 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6226 #if 1 6227 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6228 for (p = 0; p < 3; ++p) { 6229 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6230 } 6231 #endif 6232 /* D triangle */ 6233 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6234 orntNew[0] = 0; 6235 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6236 orntNew[1] = 0; 6237 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6238 orntNew[2] = 0; 6239 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6240 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6241 #if 1 6242 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6243 for (p = 0; p < 3; ++p) { 6244 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6245 } 6246 #endif 6247 } 6248 /* 6249 2----3----3 6250 | | 6251 | B | 6252 | | 6253 0----4--- 1 6254 | | 6255 | A | 6256 | | 6257 0----2----1 6258 */ 6259 /* Hybrid cells have 4 faces */ 6260 for (c = cMax; c < cEnd; ++c) { 6261 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6262 const PetscInt *cone, *ornt; 6263 PetscInt coneNew[4], orntNew[4]; 6264 6265 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6266 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6267 /* A quad */ 6268 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6269 orntNew[0] = ornt[0]; 6270 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6271 orntNew[1] = ornt[1]; 6272 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6273 orntNew[2] = 0; 6274 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6275 orntNew[3] = 0; 6276 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6277 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6278 #if 1 6279 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6280 for (p = 0; p < 4; ++p) { 6281 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6282 } 6283 #endif 6284 /* B quad */ 6285 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6286 orntNew[0] = ornt[0]; 6287 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6288 orntNew[1] = ornt[1]; 6289 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6290 orntNew[2] = 0; 6291 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6292 orntNew[3] = 0; 6293 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6294 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6295 #if 1 6296 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6297 for (p = 0; p < 4; ++p) { 6298 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6299 } 6300 #endif 6301 } 6302 /* Interior split faces have 2 vertices and the same cells as the parent */ 6303 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6304 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6305 for (f = fStart; f < fMax; ++f) { 6306 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6307 6308 for (r = 0; r < 2; ++r) { 6309 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6310 const PetscInt *cone, *support; 6311 PetscInt coneNew[2], coneSize, c, supportSize, s; 6312 6313 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6314 coneNew[0] = vStartNew + (cone[0] - vStart); 6315 coneNew[1] = vStartNew + (cone[1] - vStart); 6316 coneNew[(r+1)%2] = newv; 6317 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6318 #if 1 6319 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6320 for (p = 0; p < 2; ++p) { 6321 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6322 } 6323 #endif 6324 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6325 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6326 for (s = 0; s < supportSize; ++s) { 6327 if (support[s] >= cMax) { 6328 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6329 } else { 6330 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6331 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6332 for (c = 0; c < coneSize; ++c) { 6333 if (cone[c] == f) break; 6334 } 6335 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6336 } 6337 } 6338 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6339 #if 1 6340 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6341 for (p = 0; p < supportSize; ++p) { 6342 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6343 } 6344 #endif 6345 } 6346 } 6347 /* Interior cell faces have 2 vertices and 2 cells */ 6348 for (c = cStart; c < cMax; ++c) { 6349 const PetscInt *cone; 6350 6351 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6352 for (r = 0; r < 3; ++r) { 6353 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6354 PetscInt coneNew[2]; 6355 PetscInt supportNew[2]; 6356 6357 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6358 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6359 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6360 #if 1 6361 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6362 for (p = 0; p < 2; ++p) { 6363 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6364 } 6365 #endif 6366 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6367 supportNew[1] = (c - cStart)*4 + 3; 6368 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6369 #if 1 6370 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6371 for (p = 0; p < 2; ++p) { 6372 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6373 } 6374 #endif 6375 } 6376 } 6377 /* Interior hybrid faces have 2 vertices and the same cells */ 6378 for (f = fMax; f < fEnd; ++f) { 6379 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6380 const PetscInt *cone; 6381 const PetscInt *support; 6382 PetscInt coneNew[2]; 6383 PetscInt supportNew[2]; 6384 PetscInt size, s, r; 6385 6386 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6387 coneNew[0] = vStartNew + (cone[0] - vStart); 6388 coneNew[1] = vStartNew + (cone[1] - vStart); 6389 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6390 #if 1 6391 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6392 for (p = 0; p < 2; ++p) { 6393 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6394 } 6395 #endif 6396 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6397 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6398 for (s = 0; s < size; ++s) { 6399 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6400 for (r = 0; r < 2; ++r) { 6401 if (cone[r+2] == f) break; 6402 } 6403 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6404 } 6405 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6406 #if 1 6407 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6408 for (p = 0; p < size; ++p) { 6409 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6410 } 6411 #endif 6412 } 6413 /* Cell hybrid faces have 2 vertices and 2 cells */ 6414 for (c = cMax; c < cEnd; ++c) { 6415 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6416 const PetscInt *cone; 6417 PetscInt coneNew[2]; 6418 PetscInt supportNew[2]; 6419 6420 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6421 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6422 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6423 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6424 #if 1 6425 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6426 for (p = 0; p < 2; ++p) { 6427 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6428 } 6429 #endif 6430 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6431 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6432 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6433 #if 1 6434 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6435 for (p = 0; p < 2; ++p) { 6436 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6437 } 6438 #endif 6439 } 6440 /* Old vertices have identical supports */ 6441 for (v = vStart; v < vEnd; ++v) { 6442 const PetscInt newp = vStartNew + (v - vStart); 6443 const PetscInt *support, *cone; 6444 PetscInt size, s; 6445 6446 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6447 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6448 for (s = 0; s < size; ++s) { 6449 if (support[s] >= fMax) { 6450 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6451 } else { 6452 PetscInt r = 0; 6453 6454 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6455 if (cone[1] == v) r = 1; 6456 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6457 } 6458 } 6459 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6460 #if 1 6461 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6462 for (p = 0; p < size; ++p) { 6463 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6464 } 6465 #endif 6466 } 6467 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6468 for (f = fStart; f < fMax; ++f) { 6469 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6470 const PetscInt *cone, *support; 6471 PetscInt size, newSize = 2, s; 6472 6473 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6474 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6475 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6476 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6477 for (s = 0; s < size; ++s) { 6478 PetscInt r = 0; 6479 6480 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6481 if (support[s] >= cMax) { 6482 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6483 6484 newSize += 1; 6485 } else { 6486 if (cone[1] == f) r = 1; 6487 else if (cone[2] == f) r = 2; 6488 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6489 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6490 6491 newSize += 2; 6492 } 6493 } 6494 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6495 #if 1 6496 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6497 for (p = 0; p < newSize; ++p) { 6498 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6499 } 6500 #endif 6501 } 6502 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6503 break; 6504 default: 6505 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6506 } 6507 PetscFunctionReturn(0); 6508 } 6509 6510 #undef __FUNCT__ 6511 #define __FUNCT__ "CellRefinerSetCoordinates" 6512 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6513 { 6514 PetscSection coordSection, coordSectionNew; 6515 Vec coordinates, coordinatesNew; 6516 PetscScalar *coords, *coordsNew; 6517 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6518 PetscErrorCode ierr; 6519 6520 PetscFunctionBegin; 6521 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6522 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6523 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6524 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6525 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6526 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6527 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6528 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6529 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6530 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6531 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6532 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6533 if (fMax < 0) fMax = fEnd; 6534 switch (refiner) { 6535 case 1: 6536 case 2: 6537 case 3: 6538 /* Simplicial and Hex 2D */ 6539 /* All vertices have the dim coordinates */ 6540 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6541 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6542 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6543 } 6544 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6545 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6546 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6547 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6548 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6549 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6550 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6551 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6552 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6553 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6554 /* Old vertices have the same coordinates */ 6555 for (v = vStart; v < vEnd; ++v) { 6556 const PetscInt newv = vStartNew + (v - vStart); 6557 PetscInt off, offnew, d; 6558 6559 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6560 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6561 for (d = 0; d < dim; ++d) { 6562 coordsNew[offnew+d] = coords[off+d]; 6563 } 6564 } 6565 /* Face vertices have the average of endpoint coordinates */ 6566 for (f = fStart; f < fMax; ++f) { 6567 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6568 const PetscInt *cone; 6569 PetscInt coneSize, offA, offB, offnew, d; 6570 6571 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6572 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6573 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6574 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6575 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6576 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6577 for (d = 0; d < dim; ++d) { 6578 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6579 } 6580 } 6581 /* Just Hex 2D */ 6582 if (refiner == 2) { 6583 /* Cell vertices have the average of corner coordinates */ 6584 for (c = cStart; c < cEnd; ++c) { 6585 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6586 PetscInt *cone = NULL; 6587 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6588 6589 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6590 for (p = 0; p < closureSize*2; p += 2) { 6591 const PetscInt point = cone[p]; 6592 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6593 } 6594 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6595 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6596 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6597 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6598 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6599 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6600 for (d = 0; d < dim; ++d) { 6601 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6602 } 6603 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6604 } 6605 } 6606 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6607 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6608 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6609 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6610 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 6611 break; 6612 default: 6613 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6614 } 6615 PetscFunctionReturn(0); 6616 } 6617 6618 #undef __FUNCT__ 6619 #define __FUNCT__ "DMPlexCreateProcessSF" 6620 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6621 { 6622 PetscInt numRoots, numLeaves, l; 6623 const PetscInt *localPoints; 6624 const PetscSFNode *remotePoints; 6625 PetscInt *localPointsNew; 6626 PetscSFNode *remotePointsNew; 6627 PetscInt *ranks, *ranksNew; 6628 PetscErrorCode ierr; 6629 6630 PetscFunctionBegin; 6631 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6632 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6633 for (l = 0; l < numLeaves; ++l) { 6634 ranks[l] = remotePoints[l].rank; 6635 } 6636 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6637 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6638 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6639 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6640 for (l = 0; l < numLeaves; ++l) { 6641 ranksNew[l] = ranks[l]; 6642 localPointsNew[l] = l; 6643 remotePointsNew[l].index = 0; 6644 remotePointsNew[l].rank = ranksNew[l]; 6645 } 6646 ierr = PetscFree(ranks);CHKERRQ(ierr); 6647 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6648 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 6649 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6650 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6651 PetscFunctionReturn(0); 6652 } 6653 6654 #undef __FUNCT__ 6655 #define __FUNCT__ "CellRefinerCreateSF" 6656 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6657 { 6658 PetscSF sf, sfNew, sfProcess; 6659 IS processRanks; 6660 MPI_Datatype depthType; 6661 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6662 const PetscInt *localPoints, *neighbors; 6663 const PetscSFNode *remotePoints; 6664 PetscInt *localPointsNew; 6665 PetscSFNode *remotePointsNew; 6666 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6667 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6668 PetscErrorCode ierr; 6669 6670 PetscFunctionBegin; 6671 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6672 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6673 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6674 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6675 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6676 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6677 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6678 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6679 switch (refiner) { 6680 case 3: 6681 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6682 cMax = PetscMin(cEnd, cMax); 6683 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6684 fMax = PetscMin(fEnd, fMax); 6685 } 6686 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6687 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6688 /* Caculate size of new SF */ 6689 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6690 if (numRoots < 0) PetscFunctionReturn(0); 6691 for (l = 0; l < numLeaves; ++l) { 6692 const PetscInt p = localPoints[l]; 6693 6694 switch (refiner) { 6695 case 1: 6696 /* Simplicial 2D */ 6697 if ((p >= vStart) && (p < vEnd)) { 6698 /* Old vertices stay the same */ 6699 ++numLeavesNew; 6700 } else if ((p >= fStart) && (p < fEnd)) { 6701 /* Old faces add new faces and vertex */ 6702 numLeavesNew += 1 + 2; 6703 } else if ((p >= cStart) && (p < cEnd)) { 6704 /* Old cells add new cells and interior faces */ 6705 numLeavesNew += 4 + 3; 6706 } 6707 break; 6708 case 2: 6709 /* Hex 2D */ 6710 if ((p >= vStart) && (p < vEnd)) { 6711 /* Old vertices stay the same */ 6712 ++numLeavesNew; 6713 } else if ((p >= fStart) && (p < fEnd)) { 6714 /* Old faces add new faces and vertex */ 6715 numLeavesNew += 1 + 2; 6716 } else if ((p >= cStart) && (p < cEnd)) { 6717 /* Old cells add new cells and interior faces */ 6718 numLeavesNew += 4 + 4; 6719 } 6720 break; 6721 default: 6722 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6723 } 6724 } 6725 /* Communicate depthSizes for each remote rank */ 6726 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6727 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6728 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6729 ierr = PetscMalloc7(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthMaxOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr); 6730 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6731 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6732 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6733 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6734 for (n = 0; n < numNeighbors; ++n) { 6735 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6736 } 6737 depthSizeOld[depth] = cMax; 6738 depthSizeOld[0] = vMax; 6739 depthSizeOld[depth-1] = fMax; 6740 depthSizeOld[1] = eMax; 6741 6742 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6743 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6744 6745 depthSizeOld[depth] = cEnd - cStart; 6746 depthSizeOld[0] = vEnd - vStart; 6747 depthSizeOld[depth-1] = fEnd - fStart; 6748 depthSizeOld[1] = eEnd - eStart; 6749 6750 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6751 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6752 for (n = 0; n < numNeighbors; ++n) { 6753 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6754 } 6755 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6756 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6757 /* Calculate new point SF */ 6758 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6759 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6760 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6761 for (l = 0, m = 0; l < numLeaves; ++l) { 6762 PetscInt p = localPoints[l]; 6763 PetscInt rp = remotePoints[l].index, n; 6764 PetscMPIInt rrank = remotePoints[l].rank; 6765 6766 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6767 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6768 switch (refiner) { 6769 case 1: 6770 /* Simplicial 2D */ 6771 if ((p >= vStart) && (p < vEnd)) { 6772 /* Old vertices stay the same */ 6773 localPointsNew[m] = vStartNew + (p - vStart); 6774 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6775 remotePointsNew[m].rank = rrank; 6776 ++m; 6777 } else if ((p >= fStart) && (p < fEnd)) { 6778 /* Old faces add new faces and vertex */ 6779 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6780 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6781 remotePointsNew[m].rank = rrank; 6782 ++m; 6783 for (r = 0; r < 2; ++r, ++m) { 6784 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6785 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6786 remotePointsNew[m].rank = rrank; 6787 } 6788 } else if ((p >= cStart) && (p < cEnd)) { 6789 /* Old cells add new cells and interior faces */ 6790 for (r = 0; r < 4; ++r, ++m) { 6791 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6792 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6793 remotePointsNew[m].rank = rrank; 6794 } 6795 for (r = 0; r < 3; ++r, ++m) { 6796 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6797 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6798 remotePointsNew[m].rank = rrank; 6799 } 6800 } 6801 break; 6802 case 2: 6803 /* Hex 2D */ 6804 if ((p >= vStart) && (p < vEnd)) { 6805 /* Old vertices stay the same */ 6806 localPointsNew[m] = vStartNew + (p - vStart); 6807 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6808 remotePointsNew[m].rank = rrank; 6809 ++m; 6810 } else if ((p >= fStart) && (p < fEnd)) { 6811 /* Old faces add new faces and vertex */ 6812 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6813 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6814 remotePointsNew[m].rank = rrank; 6815 ++m; 6816 for (r = 0; r < 2; ++r, ++m) { 6817 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6818 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6819 remotePointsNew[m].rank = rrank; 6820 } 6821 } else if ((p >= cStart) && (p < cEnd)) { 6822 /* Old cells add new cells and interior faces */ 6823 for (r = 0; r < 4; ++r, ++m) { 6824 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6825 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6826 remotePointsNew[m].rank = rrank; 6827 } 6828 for (r = 0; r < 4; ++r, ++m) { 6829 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6830 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6831 remotePointsNew[m].rank = rrank; 6832 } 6833 } 6834 break; 6835 case 3: 6836 /* Hybrid simplicial 2D */ 6837 if ((p >= vStart) && (p < vEnd)) { 6838 /* Old vertices stay the same */ 6839 localPointsNew[m] = vStartNew + (p - vStart); 6840 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6841 remotePointsNew[m].rank = rrank; 6842 ++m; 6843 } else if ((p >= fStart) && (p < fMax)) { 6844 /* Old interior faces add new faces and vertex */ 6845 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6846 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6847 remotePointsNew[m].rank = rrank; 6848 ++m; 6849 for (r = 0; r < 2; ++r, ++m) { 6850 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6851 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6852 remotePointsNew[m].rank = rrank; 6853 } 6854 } else if ((p >= fMax) && (p < fEnd)) { 6855 /* Old hybrid faces stay the same */ 6856 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6857 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6858 remotePointsNew[m].rank = rrank; 6859 ++m; 6860 } else if ((p >= cStart) && (p < cMax)) { 6861 /* Old interior cells add new cells and interior faces */ 6862 for (r = 0; r < 4; ++r, ++m) { 6863 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6864 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6865 remotePointsNew[m].rank = rrank; 6866 } 6867 for (r = 0; r < 3; ++r, ++m) { 6868 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6869 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6870 remotePointsNew[m].rank = rrank; 6871 } 6872 } else if ((p >= cStart) && (p < cMax)) { 6873 /* Old hybrid cells add new cells and hybrid face */ 6874 for (r = 0; r < 2; ++r, ++m) { 6875 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6876 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6877 remotePointsNew[m].rank = rrank; 6878 } 6879 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6880 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth]); 6881 remotePointsNew[m].rank = rrank; 6882 ++m; 6883 } 6884 break; 6885 default: 6886 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6887 } 6888 } 6889 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6890 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6891 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6892 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6893 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6894 PetscFunctionReturn(0); 6895 } 6896 6897 #undef __FUNCT__ 6898 #define __FUNCT__ "CellRefinerCreateLabels" 6899 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6900 { 6901 PetscInt numLabels, l; 6902 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6903 PetscErrorCode ierr; 6904 6905 PetscFunctionBegin; 6906 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6907 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6908 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6909 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6910 6911 cStartNew = 0; 6912 vStartNew = depthSize[2]; 6913 fStartNew = depthSize[2] + depthSize[0]; 6914 6915 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6916 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6917 switch (refiner) { 6918 case 3: 6919 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6920 cMax = PetscMin(cEnd, cMax); 6921 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6922 fMax = PetscMin(fEnd, fMax); 6923 } 6924 for (l = 0; l < numLabels; ++l) { 6925 DMLabel label, labelNew; 6926 const char *lname; 6927 PetscBool isDepth; 6928 IS valueIS; 6929 const PetscInt *values; 6930 PetscInt numValues, val; 6931 6932 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6933 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6934 if (isDepth) continue; 6935 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6936 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6937 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6938 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6939 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6940 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6941 for (val = 0; val < numValues; ++val) { 6942 IS pointIS; 6943 const PetscInt *points; 6944 PetscInt numPoints, n; 6945 6946 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6947 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6948 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6949 for (n = 0; n < numPoints; ++n) { 6950 const PetscInt p = points[n]; 6951 switch (refiner) { 6952 case 1: 6953 /* Simplicial 2D */ 6954 if ((p >= vStart) && (p < vEnd)) { 6955 /* Old vertices stay the same */ 6956 newp = vStartNew + (p - vStart); 6957 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6958 } else if ((p >= fStart) && (p < fEnd)) { 6959 /* Old faces add new faces and vertex */ 6960 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6961 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6962 for (r = 0; r < 2; ++r) { 6963 newp = fStartNew + (p - fStart)*2 + r; 6964 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6965 } 6966 } else if ((p >= cStart) && (p < cEnd)) { 6967 /* Old cells add new cells and interior faces */ 6968 for (r = 0; r < 4; ++r) { 6969 newp = cStartNew + (p - cStart)*4 + r; 6970 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6971 } 6972 for (r = 0; r < 3; ++r) { 6973 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6974 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6975 } 6976 } 6977 break; 6978 case 2: 6979 /* Hex 2D */ 6980 if ((p >= vStart) && (p < vEnd)) { 6981 /* Old vertices stay the same */ 6982 newp = vStartNew + (p - vStart); 6983 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6984 } else if ((p >= fStart) && (p < fEnd)) { 6985 /* Old faces add new faces and vertex */ 6986 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6987 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6988 for (r = 0; r < 2; ++r) { 6989 newp = fStartNew + (p - fStart)*2 + r; 6990 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6991 } 6992 } else if ((p >= cStart) && (p < cEnd)) { 6993 /* Old cells add new cells and interior faces and vertex */ 6994 for (r = 0; r < 4; ++r) { 6995 newp = cStartNew + (p - cStart)*4 + r; 6996 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6997 } 6998 for (r = 0; r < 4; ++r) { 6999 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7000 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7001 } 7002 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7003 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7004 } 7005 break; 7006 case 3: 7007 /* Hybrid simplicial 2D */ 7008 if ((p >= vStart) && (p < vEnd)) { 7009 /* Old vertices stay the same */ 7010 newp = vStartNew + (p - vStart); 7011 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7012 } else if ((p >= fStart) && (p < fMax)) { 7013 /* Old interior faces add new faces and vertex */ 7014 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7015 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7016 for (r = 0; r < 2; ++r) { 7017 newp = fStartNew + (p - fStart)*2 + r; 7018 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7019 } 7020 } else if ((p >= fMax) && (p < fEnd)) { 7021 /* Old hybrid faces stay the same */ 7022 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7023 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7024 } else if ((p >= cStart) && (p < cMax)) { 7025 /* Old interior cells add new cells and interior faces */ 7026 for (r = 0; r < 4; ++r) { 7027 newp = cStartNew + (p - cStart)*4 + r; 7028 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7029 } 7030 for (r = 0; r < 3; ++r) { 7031 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7032 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7033 } 7034 } else if ((p >= cMax) && (p < cEnd)) { 7035 /* Old hybrid cells add new cells and hybrid face */ 7036 for (r = 0; r < 2; ++r) { 7037 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7038 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7039 } 7040 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7041 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7042 } 7043 break; 7044 default: 7045 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7046 } 7047 } 7048 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7049 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7050 } 7051 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7052 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7053 if (0) { 7054 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7055 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7056 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7057 } 7058 } 7059 PetscFunctionReturn(0); 7060 } 7061 7062 #undef __FUNCT__ 7063 #define __FUNCT__ "DMPlexRefine_Uniform" 7064 /* This will only work for interpolated meshes */ 7065 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7066 { 7067 DM rdm; 7068 PetscInt *depthSize; 7069 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7070 PetscErrorCode ierr; 7071 7072 PetscFunctionBegin; 7073 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 7074 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7075 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7076 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7077 /* Calculate number of new points of each depth */ 7078 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7079 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7080 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7081 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7082 /* Step 1: Set chart */ 7083 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7084 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7085 /* Step 2: Set cone/support sizes */ 7086 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7087 /* Step 3: Setup refined DM */ 7088 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7089 /* Step 4: Set cones and supports */ 7090 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7091 /* Step 5: Stratify */ 7092 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7093 /* Step 6: Set coordinates for vertices */ 7094 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7095 /* Step 7: Create pointSF */ 7096 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7097 /* Step 8: Create labels */ 7098 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7099 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7100 7101 *dmRefined = rdm; 7102 PetscFunctionReturn(0); 7103 } 7104 7105 #undef __FUNCT__ 7106 #define __FUNCT__ "DMPlexSetRefinementUniform" 7107 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7108 { 7109 DM_Plex *mesh = (DM_Plex*) dm->data; 7110 7111 PetscFunctionBegin; 7112 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7113 mesh->refinementUniform = refinementUniform; 7114 PetscFunctionReturn(0); 7115 } 7116 7117 #undef __FUNCT__ 7118 #define __FUNCT__ "DMPlexGetRefinementUniform" 7119 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7120 { 7121 DM_Plex *mesh = (DM_Plex*) dm->data; 7122 7123 PetscFunctionBegin; 7124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7125 PetscValidPointer(refinementUniform, 2); 7126 *refinementUniform = mesh->refinementUniform; 7127 PetscFunctionReturn(0); 7128 } 7129 7130 #undef __FUNCT__ 7131 #define __FUNCT__ "DMPlexSetRefinementLimit" 7132 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7133 { 7134 DM_Plex *mesh = (DM_Plex*) dm->data; 7135 7136 PetscFunctionBegin; 7137 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7138 mesh->refinementLimit = refinementLimit; 7139 PetscFunctionReturn(0); 7140 } 7141 7142 #undef __FUNCT__ 7143 #define __FUNCT__ "DMPlexGetRefinementLimit" 7144 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7145 { 7146 DM_Plex *mesh = (DM_Plex*) dm->data; 7147 7148 PetscFunctionBegin; 7149 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7150 PetscValidPointer(refinementLimit, 2); 7151 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7152 *refinementLimit = mesh->refinementLimit; 7153 PetscFunctionReturn(0); 7154 } 7155 7156 #undef __FUNCT__ 7157 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7158 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7159 { 7160 PetscInt dim, cStart, coneSize, cMax; 7161 PetscErrorCode ierr; 7162 7163 PetscFunctionBegin; 7164 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7165 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7166 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7167 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7168 switch (dim) { 7169 case 2: 7170 switch (coneSize) { 7171 case 3: 7172 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7173 else *cellRefiner = 1; /* Triangular */ 7174 break; 7175 case 4: 7176 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7177 else *cellRefiner = 2; /* Quadrilateral */ 7178 break; 7179 default: 7180 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7181 } 7182 break; 7183 default: 7184 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7185 } 7186 PetscFunctionReturn(0); 7187 } 7188 7189 #undef __FUNCT__ 7190 #define __FUNCT__ "DMRefine_Plex" 7191 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7192 { 7193 PetscReal refinementLimit; 7194 PetscInt dim, cStart, cEnd; 7195 char genname[1024], *name = NULL; 7196 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7197 PetscErrorCode ierr; 7198 7199 PetscFunctionBegin; 7200 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7201 if (isUniform) { 7202 CellRefiner cellRefiner; 7203 7204 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7205 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7206 PetscFunctionReturn(0); 7207 } 7208 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7209 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7210 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7211 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7212 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7213 if (flg) name = genname; 7214 if (name) { 7215 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7216 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7217 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7218 } 7219 switch (dim) { 7220 case 2: 7221 if (!name || isTriangle) { 7222 #if defined(PETSC_HAVE_TRIANGLE) 7223 double *maxVolumes; 7224 PetscInt c; 7225 7226 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7227 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7228 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7229 #else 7230 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7231 #endif 7232 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7233 break; 7234 case 3: 7235 if (!name || isCTetgen) { 7236 #if defined(PETSC_HAVE_CTETGEN) 7237 PetscReal *maxVolumes; 7238 PetscInt c; 7239 7240 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7241 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7242 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7243 #else 7244 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7245 #endif 7246 } else if (isTetgen) { 7247 #if defined(PETSC_HAVE_TETGEN) 7248 double *maxVolumes; 7249 PetscInt c; 7250 7251 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7252 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7253 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7254 #else 7255 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7256 #endif 7257 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7258 break; 7259 default: 7260 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7261 } 7262 PetscFunctionReturn(0); 7263 } 7264 7265 #undef __FUNCT__ 7266 #define __FUNCT__ "DMPlexGetDepth" 7267 /*@ 7268 DMPlexGetDepth - get the number of strata 7269 7270 Not Collective 7271 7272 Input Parameters: 7273 . dm - The DMPlex object 7274 7275 Output Parameters: 7276 . depth - number of strata 7277 7278 Level: developer 7279 7280 Notes: 7281 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7282 7283 .keywords: mesh, points 7284 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7285 @*/ 7286 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7287 { 7288 PetscInt d; 7289 PetscErrorCode ierr; 7290 7291 PetscFunctionBegin; 7292 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7293 PetscValidPointer(depth, 2); 7294 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7295 *depth = d-1; 7296 PetscFunctionReturn(0); 7297 } 7298 7299 #undef __FUNCT__ 7300 #define __FUNCT__ "DMPlexGetDepthStratum" 7301 /*@ 7302 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7303 7304 Not Collective 7305 7306 Input Parameters: 7307 + dm - The DMPlex object 7308 - stratumValue - The requested depth 7309 7310 Output Parameters: 7311 + start - The first point at this depth 7312 - end - One beyond the last point at this depth 7313 7314 Level: developer 7315 7316 .keywords: mesh, points 7317 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7318 @*/ 7319 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7320 { 7321 DM_Plex *mesh = (DM_Plex*) dm->data; 7322 DMLabel next = mesh->labels; 7323 PetscBool flg = PETSC_FALSE; 7324 PetscInt depth; 7325 PetscErrorCode ierr; 7326 7327 PetscFunctionBegin; 7328 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7329 if (stratumValue < 0) { 7330 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7331 PetscFunctionReturn(0); 7332 } else { 7333 PetscInt pStart, pEnd; 7334 7335 if (start) *start = 0; 7336 if (end) *end = 0; 7337 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7338 if (pStart == pEnd) PetscFunctionReturn(0); 7339 } 7340 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7341 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7342 /* We should have a generic GetLabel() and a Label class */ 7343 while (next) { 7344 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7345 if (flg) break; 7346 next = next->next; 7347 } 7348 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7349 depth = stratumValue; 7350 if ((depth < 0) || (depth >= next->numStrata)) { 7351 if (start) *start = 0; 7352 if (end) *end = 0; 7353 } else { 7354 if (start) *start = next->points[next->stratumOffsets[depth]]; 7355 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7356 } 7357 PetscFunctionReturn(0); 7358 } 7359 7360 #undef __FUNCT__ 7361 #define __FUNCT__ "DMPlexGetHeightStratum" 7362 /*@ 7363 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7364 7365 Not Collective 7366 7367 Input Parameters: 7368 + dm - The DMPlex object 7369 - stratumValue - The requested height 7370 7371 Output Parameters: 7372 + start - The first point at this height 7373 - end - One beyond the last point at this height 7374 7375 Level: developer 7376 7377 .keywords: mesh, points 7378 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7379 @*/ 7380 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7381 { 7382 DM_Plex *mesh = (DM_Plex*) dm->data; 7383 DMLabel next = mesh->labels; 7384 PetscBool flg = PETSC_FALSE; 7385 PetscInt depth; 7386 PetscErrorCode ierr; 7387 7388 PetscFunctionBegin; 7389 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7390 if (stratumValue < 0) { 7391 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7392 } else { 7393 PetscInt pStart, pEnd; 7394 7395 if (start) *start = 0; 7396 if (end) *end = 0; 7397 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7398 if (pStart == pEnd) PetscFunctionReturn(0); 7399 } 7400 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7401 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7402 /* We should have a generic GetLabel() and a Label class */ 7403 while (next) { 7404 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7405 if (flg) break; 7406 next = next->next; 7407 } 7408 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7409 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7410 if ((depth < 0) || (depth >= next->numStrata)) { 7411 if (start) *start = 0; 7412 if (end) *end = 0; 7413 } else { 7414 if (start) *start = next->points[next->stratumOffsets[depth]]; 7415 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7416 } 7417 PetscFunctionReturn(0); 7418 } 7419 7420 #undef __FUNCT__ 7421 #define __FUNCT__ "DMPlexCreateSectionInitial" 7422 /* Set the number of dof on each point and separate by fields */ 7423 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7424 { 7425 PetscInt *numDofTot; 7426 PetscInt pStart = 0, pEnd = 0; 7427 PetscInt p, d, f; 7428 PetscErrorCode ierr; 7429 7430 PetscFunctionBegin; 7431 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7432 for (d = 0; d <= dim; ++d) { 7433 numDofTot[d] = 0; 7434 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7435 } 7436 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7437 if (numFields > 0) { 7438 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7439 if (numComp) { 7440 for (f = 0; f < numFields; ++f) { 7441 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7442 } 7443 } 7444 } 7445 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7446 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7447 for (d = 0; d <= dim; ++d) { 7448 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7449 for (p = pStart; p < pEnd; ++p) { 7450 for (f = 0; f < numFields; ++f) { 7451 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7452 } 7453 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7454 } 7455 } 7456 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7457 PetscFunctionReturn(0); 7458 } 7459 7460 #undef __FUNCT__ 7461 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7462 /* Set the number of dof on each point and separate by fields 7463 If constDof is PETSC_DETERMINE, constrain every dof on the point 7464 */ 7465 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7466 { 7467 PetscInt numFields; 7468 PetscInt bc; 7469 PetscErrorCode ierr; 7470 7471 PetscFunctionBegin; 7472 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7473 for (bc = 0; bc < numBC; ++bc) { 7474 PetscInt field = 0; 7475 const PetscInt *idx; 7476 PetscInt n, i; 7477 7478 if (numFields) field = bcField[bc]; 7479 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7480 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7481 for (i = 0; i < n; ++i) { 7482 const PetscInt p = idx[i]; 7483 PetscInt numConst = constDof; 7484 7485 /* Constrain every dof on the point */ 7486 if (numConst < 0) { 7487 if (numFields) { 7488 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7489 } else { 7490 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7491 } 7492 } 7493 if (numFields) { 7494 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7495 } 7496 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7497 } 7498 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7499 } 7500 PetscFunctionReturn(0); 7501 } 7502 7503 #undef __FUNCT__ 7504 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7505 /* Set the constrained indices on each point and separate by fields */ 7506 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7507 { 7508 PetscInt *maxConstraints; 7509 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7510 PetscErrorCode ierr; 7511 7512 PetscFunctionBegin; 7513 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7514 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7515 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7516 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7517 for (p = pStart; p < pEnd; ++p) { 7518 PetscInt cdof; 7519 7520 if (numFields) { 7521 for (f = 0; f < numFields; ++f) { 7522 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7523 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7524 } 7525 } else { 7526 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7527 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7528 } 7529 } 7530 for (f = 0; f < numFields; ++f) { 7531 maxConstraints[numFields] += maxConstraints[f]; 7532 } 7533 if (maxConstraints[numFields]) { 7534 PetscInt *indices; 7535 7536 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7537 for (p = pStart; p < pEnd; ++p) { 7538 PetscInt cdof, d; 7539 7540 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7541 if (cdof) { 7542 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7543 if (numFields) { 7544 PetscInt numConst = 0, foff = 0; 7545 7546 for (f = 0; f < numFields; ++f) { 7547 PetscInt cfdof, fdof; 7548 7549 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7550 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7551 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7552 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7553 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7554 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7555 numConst += cfdof; 7556 foff += fdof; 7557 } 7558 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7559 } else { 7560 for (d = 0; d < cdof; ++d) indices[d] = d; 7561 } 7562 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7563 } 7564 } 7565 ierr = PetscFree(indices);CHKERRQ(ierr); 7566 } 7567 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7568 PetscFunctionReturn(0); 7569 } 7570 7571 #undef __FUNCT__ 7572 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7573 /* Set the constrained field indices on each point */ 7574 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7575 { 7576 const PetscInt *points, *indices; 7577 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7578 PetscErrorCode ierr; 7579 7580 PetscFunctionBegin; 7581 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7582 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7583 7584 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7585 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7586 if (!constraintIndices) { 7587 PetscInt *idx, i; 7588 7589 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7590 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7591 for (i = 0; i < maxDof; ++i) idx[i] = i; 7592 for (p = 0; p < numPoints; ++p) { 7593 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7594 } 7595 ierr = PetscFree(idx);CHKERRQ(ierr); 7596 } else { 7597 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7598 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7599 for (p = 0; p < numPoints; ++p) { 7600 PetscInt fcdof; 7601 7602 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7603 if (fcdof != numConstraints) SETERRQ4(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 7604 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7605 } 7606 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7607 } 7608 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7609 PetscFunctionReturn(0); 7610 } 7611 7612 #undef __FUNCT__ 7613 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7614 /* Set the constrained indices on each point and separate by fields */ 7615 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7616 { 7617 PetscInt *indices; 7618 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7619 PetscErrorCode ierr; 7620 7621 PetscFunctionBegin; 7622 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7623 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7624 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7625 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7626 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7627 for (p = pStart; p < pEnd; ++p) { 7628 PetscInt cdof, d; 7629 7630 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7631 if (cdof) { 7632 PetscInt numConst = 0, foff = 0; 7633 7634 for (f = 0; f < numFields; ++f) { 7635 const PetscInt *fcind; 7636 PetscInt fdof, fcdof; 7637 7638 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7639 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7640 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7641 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7642 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7643 foff += fdof; 7644 numConst += fcdof; 7645 } 7646 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7647 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7648 } 7649 } 7650 ierr = PetscFree(indices);CHKERRQ(ierr); 7651 PetscFunctionReturn(0); 7652 } 7653 7654 #undef __FUNCT__ 7655 #define __FUNCT__ "DMPlexCreateSection" 7656 /*@C 7657 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7658 7659 Not Collective 7660 7661 Input Parameters: 7662 + dm - The DMPlex object 7663 . dim - The spatial dimension of the problem 7664 . numFields - The number of fields in the problem 7665 . numComp - An array of size numFields that holds the number of components for each field 7666 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7667 . numBC - The number of boundary conditions 7668 . bcField - An array of size numBC giving the field number for each boundry condition 7669 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7670 7671 Output Parameter: 7672 . section - The PetscSection object 7673 7674 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 7675 nubmer of dof for field 0 on each edge. 7676 7677 Level: developer 7678 7679 .keywords: mesh, elements 7680 .seealso: DMPlexCreate(), PetscSectionCreate() 7681 @*/ 7682 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 7683 { 7684 PetscErrorCode ierr; 7685 7686 PetscFunctionBegin; 7687 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7688 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7689 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7690 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7691 { 7692 PetscBool view = PETSC_FALSE; 7693 7694 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7695 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7696 } 7697 PetscFunctionReturn(0); 7698 } 7699 7700 #undef __FUNCT__ 7701 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7702 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7703 { 7704 PetscSection section; 7705 PetscErrorCode ierr; 7706 7707 PetscFunctionBegin; 7708 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7709 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7710 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7711 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7712 PetscFunctionReturn(0); 7713 } 7714 7715 #undef __FUNCT__ 7716 #define __FUNCT__ "DMPlexGetCoordinateSection" 7717 /*@ 7718 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7719 7720 Not Collective 7721 7722 Input Parameter: 7723 . dm - The DMPlex object 7724 7725 Output Parameter: 7726 . section - The PetscSection object 7727 7728 Level: intermediate 7729 7730 .keywords: mesh, coordinates 7731 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7732 @*/ 7733 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7734 { 7735 DM cdm; 7736 PetscErrorCode ierr; 7737 7738 PetscFunctionBegin; 7739 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7740 PetscValidPointer(section, 2); 7741 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7742 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7743 PetscFunctionReturn(0); 7744 } 7745 7746 #undef __FUNCT__ 7747 #define __FUNCT__ "DMPlexSetCoordinateSection" 7748 /*@ 7749 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7750 7751 Not Collective 7752 7753 Input Parameters: 7754 + dm - The DMPlex object 7755 - section - The PetscSection object 7756 7757 Level: intermediate 7758 7759 .keywords: mesh, coordinates 7760 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7761 @*/ 7762 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7763 { 7764 DM cdm; 7765 PetscErrorCode ierr; 7766 7767 PetscFunctionBegin; 7768 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7769 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 7770 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7771 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7772 PetscFunctionReturn(0); 7773 } 7774 7775 #undef __FUNCT__ 7776 #define __FUNCT__ "DMPlexGetConeSection" 7777 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7778 { 7779 DM_Plex *mesh = (DM_Plex*) dm->data; 7780 7781 PetscFunctionBegin; 7782 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7783 if (section) *section = mesh->coneSection; 7784 PetscFunctionReturn(0); 7785 } 7786 7787 #undef __FUNCT__ 7788 #define __FUNCT__ "DMPlexGetCones" 7789 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 7790 { 7791 DM_Plex *mesh = (DM_Plex*) dm->data; 7792 7793 PetscFunctionBegin; 7794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7795 if (cones) *cones = mesh->cones; 7796 PetscFunctionReturn(0); 7797 } 7798 7799 #undef __FUNCT__ 7800 #define __FUNCT__ "DMPlexGetConeOrientations" 7801 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 7802 { 7803 DM_Plex *mesh = (DM_Plex*) dm->data; 7804 7805 PetscFunctionBegin; 7806 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7807 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7808 PetscFunctionReturn(0); 7809 } 7810 7811 #undef __FUNCT__ 7812 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7813 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7814 { 7815 const PetscInt embedDim = 2; 7816 PetscReal x = PetscRealPart(point[0]); 7817 PetscReal y = PetscRealPart(point[1]); 7818 PetscReal v0[2], J[4], invJ[4], detJ; 7819 PetscReal xi, eta; 7820 PetscErrorCode ierr; 7821 7822 PetscFunctionBegin; 7823 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7824 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7825 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7826 7827 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 7828 else *cell = -1; 7829 PetscFunctionReturn(0); 7830 } 7831 7832 #undef __FUNCT__ 7833 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7834 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7835 { 7836 PetscSection coordSection; 7837 Vec coordsLocal; 7838 const PetscScalar *coords; 7839 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7840 PetscReal x = PetscRealPart(point[0]); 7841 PetscReal y = PetscRealPart(point[1]); 7842 PetscInt crossings = 0, f; 7843 PetscErrorCode ierr; 7844 7845 PetscFunctionBegin; 7846 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7847 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7848 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7849 for (f = 0; f < 4; ++f) { 7850 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7851 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7852 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7853 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7854 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7855 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7856 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7857 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7858 if ((cond1 || cond2) && above) ++crossings; 7859 } 7860 if (crossings % 2) *cell = c; 7861 else *cell = -1; 7862 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7863 PetscFunctionReturn(0); 7864 } 7865 7866 #undef __FUNCT__ 7867 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7868 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7869 { 7870 const PetscInt embedDim = 3; 7871 PetscReal v0[3], J[9], invJ[9], detJ; 7872 PetscReal x = PetscRealPart(point[0]); 7873 PetscReal y = PetscRealPart(point[1]); 7874 PetscReal z = PetscRealPart(point[2]); 7875 PetscReal xi, eta, zeta; 7876 PetscErrorCode ierr; 7877 7878 PetscFunctionBegin; 7879 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7880 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7881 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7882 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7883 7884 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 7885 else *cell = -1; 7886 PetscFunctionReturn(0); 7887 } 7888 7889 #undef __FUNCT__ 7890 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7891 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7892 { 7893 PetscSection coordSection; 7894 Vec coordsLocal; 7895 const PetscScalar *coords; 7896 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7897 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7898 PetscBool found = PETSC_TRUE; 7899 PetscInt f; 7900 PetscErrorCode ierr; 7901 7902 PetscFunctionBegin; 7903 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7904 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7905 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7906 for (f = 0; f < 6; ++f) { 7907 /* Check the point is under plane */ 7908 /* Get face normal */ 7909 PetscReal v_i[3]; 7910 PetscReal v_j[3]; 7911 PetscReal normal[3]; 7912 PetscReal pp[3]; 7913 PetscReal dot; 7914 7915 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 7916 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 7917 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 7918 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 7919 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 7920 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 7921 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 7922 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 7923 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 7924 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 7925 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 7926 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 7927 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7928 7929 /* Check that projected point is in face (2D location problem) */ 7930 if (dot < 0.0) { 7931 found = PETSC_FALSE; 7932 break; 7933 } 7934 } 7935 if (found) *cell = c; 7936 else *cell = -1; 7937 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7938 PetscFunctionReturn(0); 7939 } 7940 7941 #undef __FUNCT__ 7942 #define __FUNCT__ "DMLocatePoints_Plex" 7943 /* 7944 Need to implement using the guess 7945 */ 7946 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7947 { 7948 PetscInt cell = -1 /*, guess = -1*/; 7949 PetscInt bs, numPoints, p; 7950 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7951 PetscInt *cells; 7952 PetscScalar *a; 7953 PetscErrorCode ierr; 7954 7955 PetscFunctionBegin; 7956 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7957 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7958 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7959 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7960 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7961 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7962 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7963 if (bs != dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 7964 numPoints /= bs; 7965 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7966 for (p = 0; p < numPoints; ++p) { 7967 const PetscScalar *point = &a[p*bs]; 7968 7969 switch (dim) { 7970 case 2: 7971 for (c = cStart; c < cEnd; ++c) { 7972 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7973 switch (coneSize) { 7974 case 3: 7975 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7976 break; 7977 case 4: 7978 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7979 break; 7980 default: 7981 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7982 } 7983 if (cell >= 0) break; 7984 } 7985 break; 7986 case 3: 7987 for (c = cStart; c < cEnd; ++c) { 7988 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7989 switch (coneSize) { 7990 case 4: 7991 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7992 break; 7993 case 8: 7994 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7995 break; 7996 default: 7997 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7998 } 7999 if (cell >= 0) break; 8000 } 8001 break; 8002 default: 8003 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8004 } 8005 cells[p] = cell; 8006 } 8007 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8008 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8009 PetscFunctionReturn(0); 8010 } 8011 8012 /******************************** FEM Support **********************************/ 8013 8014 #undef __FUNCT__ 8015 #define __FUNCT__ "DMPlexVecGetClosure" 8016 /*@C 8017 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8018 8019 Not collective 8020 8021 Input Parameters: 8022 + dm - The DM 8023 . section - The section describing the layout in v, or NULL to use the default section 8024 . v - The local vector 8025 - point - The sieve point in the DM 8026 8027 Output Parameters: 8028 + csize - The number of values in the closure, or NULL 8029 - values - The array of values, which is a borrowed array and should not be freed 8030 8031 Level: intermediate 8032 8033 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8034 @*/ 8035 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8036 { 8037 PetscScalar *array, *vArray; 8038 PetscInt *points = NULL; 8039 PetscInt offsets[32]; 8040 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8041 PetscErrorCode ierr; 8042 8043 PetscFunctionBegin; 8044 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8045 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8046 if (!section) { 8047 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8048 } 8049 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8050 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8051 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8052 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8053 /* Compress out points not in the section */ 8054 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8055 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8056 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8057 points[q*2] = points[p]; 8058 points[q*2+1] = points[p+1]; 8059 ++q; 8060 } 8061 } 8062 numPoints = q; 8063 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8064 PetscInt dof, fdof; 8065 8066 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8067 for (f = 0; f < numFields; ++f) { 8068 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8069 offsets[f+1] += fdof; 8070 } 8071 size += dof; 8072 } 8073 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8074 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8075 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8076 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8077 for (p = 0; p < numPoints*2; p += 2) { 8078 PetscInt o = points[p+1]; 8079 PetscInt dof, off, d; 8080 PetscScalar *varr; 8081 8082 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8083 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8084 varr = &vArray[off]; 8085 if (numFields) { 8086 PetscInt fdof, foff, fcomp, f, c; 8087 8088 for (f = 0, foff = 0; f < numFields; ++f) { 8089 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8090 if (o >= 0) { 8091 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8092 array[offsets[f]] = varr[foff+d]; 8093 } 8094 } else { 8095 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8096 for (d = fdof/fcomp-1; d >= 0; --d) { 8097 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8098 array[offsets[f]] = varr[foff+d*fcomp+c]; 8099 } 8100 } 8101 } 8102 foff += fdof; 8103 } 8104 } else { 8105 if (o >= 0) { 8106 for (d = 0; d < dof; ++d, ++offsets[0]) { 8107 array[offsets[0]] = varr[d]; 8108 } 8109 } else { 8110 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8111 array[offsets[0]] = varr[d]; 8112 } 8113 } 8114 } 8115 } 8116 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8117 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8118 if (csize) *csize = size; 8119 *values = array; 8120 PetscFunctionReturn(0); 8121 } 8122 8123 #undef __FUNCT__ 8124 #define __FUNCT__ "DMPlexVecRestoreClosure" 8125 /*@C 8126 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8127 8128 Not collective 8129 8130 Input Parameters: 8131 + dm - The DM 8132 . section - The section describing the layout in v, or NULL to use the default section 8133 . v - The local vector 8134 . point - The sieve point in the DM 8135 . csize - The number of values in the closure, or NULL 8136 - values - The array of values, which is a borrowed array and should not be freed 8137 8138 Level: intermediate 8139 8140 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8141 @*/ 8142 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8143 { 8144 PetscInt size = 0; 8145 PetscErrorCode ierr; 8146 8147 PetscFunctionBegin; 8148 /* Should work without recalculating size */ 8149 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8150 PetscFunctionReturn(0); 8151 } 8152 8153 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8154 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8155 8156 #undef __FUNCT__ 8157 #define __FUNCT__ "updatePoint_private" 8158 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8159 { 8160 PetscInt cdof; /* The number of constraints on this point */ 8161 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8162 PetscScalar *a; 8163 PetscInt off, cind = 0, k; 8164 PetscErrorCode ierr; 8165 8166 PetscFunctionBegin; 8167 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8168 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8169 a = &array[off]; 8170 if (!cdof || setBC) { 8171 if (orientation >= 0) { 8172 for (k = 0; k < dof; ++k) { 8173 fuse(&a[k], values[k]); 8174 } 8175 } else { 8176 for (k = 0; k < dof; ++k) { 8177 fuse(&a[k], values[dof-k-1]); 8178 } 8179 } 8180 } else { 8181 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8182 if (orientation >= 0) { 8183 for (k = 0; k < dof; ++k) { 8184 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8185 fuse(&a[k], values[k]); 8186 } 8187 } else { 8188 for (k = 0; k < dof; ++k) { 8189 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8190 fuse(&a[k], values[dof-k-1]); 8191 } 8192 } 8193 } 8194 PetscFunctionReturn(0); 8195 } 8196 8197 #undef __FUNCT__ 8198 #define __FUNCT__ "updatePointFields_private" 8199 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8200 { 8201 PetscScalar *a; 8202 PetscInt numFields, off, foff, f; 8203 PetscErrorCode ierr; 8204 8205 PetscFunctionBegin; 8206 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8207 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8208 a = &array[off]; 8209 for (f = 0, foff = 0; f < numFields; ++f) { 8210 PetscInt fdof, fcomp, fcdof; 8211 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8212 PetscInt cind = 0, k, c; 8213 8214 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8215 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8216 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8217 if (!fcdof || setBC) { 8218 if (orientation >= 0) { 8219 for (k = 0; k < fdof; ++k) { 8220 fuse(&a[foff+k], values[foffs[f]+k]); 8221 } 8222 } else { 8223 for (k = fdof/fcomp-1; k >= 0; --k) { 8224 for (c = 0; c < fcomp; ++c) { 8225 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8226 } 8227 } 8228 } 8229 } else { 8230 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8231 if (orientation >= 0) { 8232 for (k = 0; k < fdof; ++k) { 8233 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8234 fuse(&a[foff+k], values[foffs[f]+k]); 8235 } 8236 } else { 8237 for (k = fdof/fcomp-1; k >= 0; --k) { 8238 for (c = 0; c < fcomp; ++c) { 8239 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8240 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8241 } 8242 } 8243 } 8244 } 8245 foff += fdof; 8246 foffs[f] += fdof; 8247 } 8248 PetscFunctionReturn(0); 8249 } 8250 8251 #undef __FUNCT__ 8252 #define __FUNCT__ "DMPlexVecSetClosure" 8253 /*@C 8254 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8255 8256 Not collective 8257 8258 Input Parameters: 8259 + dm - The DM 8260 . section - The section describing the layout in v, or NULL to use the default sectionw 8261 . v - The local vector 8262 . point - The sieve point in the DM 8263 . values - The array of values, which is a borrowed array and should not be freed 8264 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8265 8266 Level: intermediate 8267 8268 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8269 @*/ 8270 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8271 { 8272 PetscScalar *array; 8273 PetscInt *points = NULL; 8274 PetscInt offsets[32]; 8275 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8276 PetscErrorCode ierr; 8277 8278 PetscFunctionBegin; 8279 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8280 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8281 if (!section) { 8282 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8283 } 8284 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8285 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8286 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8287 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8288 /* Compress out points not in the section */ 8289 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8290 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8291 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8292 points[q*2] = points[p]; 8293 points[q*2+1] = points[p+1]; 8294 ++q; 8295 } 8296 } 8297 numPoints = q; 8298 for (p = 0; p < numPoints*2; p += 2) { 8299 PetscInt fdof; 8300 8301 for (f = 0; f < numFields; ++f) { 8302 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8303 offsets[f+1] += fdof; 8304 } 8305 } 8306 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8307 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8308 if (numFields) { 8309 switch (mode) { 8310 case INSERT_VALUES: 8311 for (p = 0; p < numPoints*2; p += 2) { 8312 PetscInt o = points[p+1]; 8313 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8314 } break; 8315 case INSERT_ALL_VALUES: 8316 for (p = 0; p < numPoints*2; p += 2) { 8317 PetscInt o = points[p+1]; 8318 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8319 } break; 8320 case ADD_VALUES: 8321 for (p = 0; p < numPoints*2; p += 2) { 8322 PetscInt o = points[p+1]; 8323 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8324 } break; 8325 case ADD_ALL_VALUES: 8326 for (p = 0; p < numPoints*2; p += 2) { 8327 PetscInt o = points[p+1]; 8328 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8329 } break; 8330 default: 8331 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8332 } 8333 } else { 8334 switch (mode) { 8335 case INSERT_VALUES: 8336 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8337 PetscInt o = points[p+1]; 8338 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8339 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8340 } break; 8341 case INSERT_ALL_VALUES: 8342 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8343 PetscInt o = points[p+1]; 8344 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8345 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8346 } break; 8347 case ADD_VALUES: 8348 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8349 PetscInt o = points[p+1]; 8350 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8351 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8352 } break; 8353 case ADD_ALL_VALUES: 8354 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8355 PetscInt o = points[p+1]; 8356 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8357 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8358 } break; 8359 default: 8360 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8361 } 8362 } 8363 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8364 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8365 PetscFunctionReturn(0); 8366 } 8367 8368 #undef __FUNCT__ 8369 #define __FUNCT__ "DMPlexPrintMatSetValues" 8370 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8371 { 8372 PetscMPIInt rank; 8373 PetscInt i, j; 8374 PetscErrorCode ierr; 8375 8376 PetscFunctionBegin; 8377 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8378 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8379 for (i = 0; i < numIndices; i++) { 8380 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8381 } 8382 for (i = 0; i < numIndices; i++) { 8383 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8384 for (j = 0; j < numIndices; j++) { 8385 #if defined(PETSC_USE_COMPLEX) 8386 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8387 #else 8388 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8389 #endif 8390 } 8391 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8392 } 8393 PetscFunctionReturn(0); 8394 } 8395 8396 #undef __FUNCT__ 8397 #define __FUNCT__ "indicesPoint_private" 8398 /* . off - The global offset of this point */ 8399 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8400 { 8401 PetscInt dof; /* The number of unknowns on this point */ 8402 PetscInt cdof; /* The number of constraints on this point */ 8403 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8404 PetscInt cind = 0, k; 8405 PetscErrorCode ierr; 8406 8407 PetscFunctionBegin; 8408 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8409 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8410 if (!cdof || setBC) { 8411 if (orientation >= 0) { 8412 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8413 } else { 8414 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8415 } 8416 } else { 8417 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8418 if (orientation >= 0) { 8419 for (k = 0; k < dof; ++k) { 8420 if ((cind < cdof) && (k == cdofs[cind])) { 8421 /* Insert check for returning constrained indices */ 8422 indices[*loff+k] = -(off+k+1); 8423 ++cind; 8424 } else { 8425 indices[*loff+k] = off+k-cind; 8426 } 8427 } 8428 } else { 8429 for (k = 0; k < dof; ++k) { 8430 if ((cind < cdof) && (k == cdofs[cind])) { 8431 /* Insert check for returning constrained indices */ 8432 indices[*loff+dof-k-1] = -(off+k+1); 8433 ++cind; 8434 } else { 8435 indices[*loff+dof-k-1] = off+k-cind; 8436 } 8437 } 8438 } 8439 } 8440 *loff += dof; 8441 PetscFunctionReturn(0); 8442 } 8443 8444 #undef __FUNCT__ 8445 #define __FUNCT__ "indicesPointFields_private" 8446 /* . off - The global offset of this point */ 8447 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8448 { 8449 PetscInt numFields, foff, f; 8450 PetscErrorCode ierr; 8451 8452 PetscFunctionBegin; 8453 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8454 for (f = 0, foff = 0; f < numFields; ++f) { 8455 PetscInt fdof, fcomp, cfdof; 8456 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8457 PetscInt cind = 0, k, c; 8458 8459 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8460 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8461 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8462 if (!cfdof || setBC) { 8463 if (orientation >= 0) { 8464 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8465 } else { 8466 for (k = fdof/fcomp-1; k >= 0; --k) { 8467 for (c = 0; c < fcomp; ++c) { 8468 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8469 } 8470 } 8471 } 8472 } else { 8473 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8474 if (orientation >= 0) { 8475 for (k = 0; k < fdof; ++k) { 8476 if ((cind < cfdof) && (k == fcdofs[cind])) { 8477 indices[foffs[f]+k] = -(off+foff+k+1); 8478 ++cind; 8479 } else { 8480 indices[foffs[f]+k] = off+foff+k-cind; 8481 } 8482 } 8483 } else { 8484 for (k = fdof/fcomp-1; k >= 0; --k) { 8485 for (c = 0; c < fcomp; ++c) { 8486 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8487 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8488 ++cind; 8489 } else { 8490 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8491 } 8492 } 8493 } 8494 } 8495 } 8496 foff += fdof - cfdof; 8497 foffs[f] += fdof; 8498 } 8499 PetscFunctionReturn(0); 8500 } 8501 8502 #undef __FUNCT__ 8503 #define __FUNCT__ "DMPlexMatSetClosure" 8504 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8505 { 8506 DM_Plex *mesh = (DM_Plex*) dm->data; 8507 PetscInt *points = NULL; 8508 PetscInt *indices; 8509 PetscInt offsets[32]; 8510 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8511 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8512 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8513 PetscErrorCode ierr; 8514 8515 PetscFunctionBegin; 8516 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8517 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8518 if (useDefault) { 8519 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8520 } 8521 if (useGlobalDefault) { 8522 if (useDefault) { 8523 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8524 } else { 8525 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8526 } 8527 } 8528 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8529 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8530 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8531 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8532 /* Compress out points not in the section */ 8533 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8534 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8535 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8536 points[q*2] = points[p]; 8537 points[q*2+1] = points[p+1]; 8538 ++q; 8539 } 8540 } 8541 numPoints = q; 8542 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8543 PetscInt fdof; 8544 8545 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8546 for (f = 0; f < numFields; ++f) { 8547 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8548 offsets[f+1] += fdof; 8549 } 8550 numIndices += dof; 8551 } 8552 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8553 8554 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8555 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8556 if (numFields) { 8557 for (p = 0; p < numPoints*2; p += 2) { 8558 PetscInt o = points[p+1]; 8559 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8560 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8561 } 8562 } else { 8563 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8564 PetscInt o = points[p+1]; 8565 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8566 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8567 } 8568 } 8569 if (useGlobalDefault && !useDefault) { 8570 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8571 } 8572 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8573 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8574 if (ierr) { 8575 PetscMPIInt rank; 8576 PetscErrorCode ierr2; 8577 8578 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8579 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8580 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8581 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8582 CHKERRQ(ierr); 8583 } 8584 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8585 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8586 PetscFunctionReturn(0); 8587 } 8588 8589 #undef __FUNCT__ 8590 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8591 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8592 { 8593 PetscSection coordSection; 8594 Vec coordinates; 8595 const PetscScalar *coords; 8596 const PetscInt dim = 2; 8597 PetscInt d, f; 8598 PetscErrorCode ierr; 8599 8600 PetscFunctionBegin; 8601 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8602 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8603 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8604 if (v0) { 8605 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8606 } 8607 if (J) { 8608 for (d = 0; d < dim; d++) { 8609 for (f = 0; f < dim; f++) { 8610 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8611 } 8612 } 8613 *detJ = J[0]*J[3] - J[1]*J[2]; 8614 #if 0 8615 if (detJ < 0.0) { 8616 const PetscReal xLength = mesh->periodicity[0]; 8617 8618 if (xLength != 0.0) { 8619 PetscReal v0x = coords[0*dim+0]; 8620 8621 if (v0x == 0.0) v0x = v0[0] = xLength; 8622 for (f = 0; f < dim; f++) { 8623 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8624 8625 J[0*dim+f] = 0.5*(px - v0x); 8626 } 8627 } 8628 detJ = J[0]*J[3] - J[1]*J[2]; 8629 } 8630 #endif 8631 PetscLogFlops(8.0 + 3.0); 8632 } 8633 if (invJ) { 8634 const PetscReal invDet = 1.0/(*detJ); 8635 8636 invJ[0] = invDet*J[3]; 8637 invJ[1] = -invDet*J[1]; 8638 invJ[2] = -invDet*J[2]; 8639 invJ[3] = invDet*J[0]; 8640 PetscLogFlops(5.0); 8641 } 8642 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8643 PetscFunctionReturn(0); 8644 } 8645 8646 #undef __FUNCT__ 8647 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8648 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8649 { 8650 PetscSection coordSection; 8651 Vec coordinates; 8652 const PetscScalar *coords; 8653 const PetscInt dim = 2; 8654 PetscInt d, f; 8655 PetscErrorCode ierr; 8656 8657 PetscFunctionBegin; 8658 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8659 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8660 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8661 if (v0) { 8662 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8663 } 8664 if (J) { 8665 for (d = 0; d < dim; d++) { 8666 for (f = 0; f < dim; f++) { 8667 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8668 } 8669 } 8670 *detJ = J[0]*J[3] - J[1]*J[2]; 8671 PetscLogFlops(8.0 + 3.0); 8672 } 8673 if (invJ) { 8674 const PetscReal invDet = 1.0/(*detJ); 8675 8676 invJ[0] = invDet*J[3]; 8677 invJ[1] = -invDet*J[1]; 8678 invJ[2] = -invDet*J[2]; 8679 invJ[3] = invDet*J[0]; 8680 PetscLogFlops(5.0); 8681 } 8682 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8683 PetscFunctionReturn(0); 8684 } 8685 8686 #undef __FUNCT__ 8687 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8688 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8689 { 8690 PetscSection coordSection; 8691 Vec coordinates; 8692 const PetscScalar *coords; 8693 const PetscInt dim = 3; 8694 PetscInt d, f; 8695 PetscErrorCode ierr; 8696 8697 PetscFunctionBegin; 8698 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8699 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8700 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8701 if (v0) { 8702 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8703 } 8704 if (J) { 8705 for (d = 0; d < dim; d++) { 8706 for (f = 0; f < dim; f++) { 8707 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8708 } 8709 } 8710 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8711 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8712 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8713 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8714 PetscLogFlops(18.0 + 12.0); 8715 } 8716 if (invJ) { 8717 const PetscReal invDet = 1.0/(*detJ); 8718 8719 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8720 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8721 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8722 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8723 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8724 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8725 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8726 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8727 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8728 PetscLogFlops(37.0); 8729 } 8730 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8731 PetscFunctionReturn(0); 8732 } 8733 8734 #undef __FUNCT__ 8735 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8736 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8737 { 8738 PetscSection coordSection; 8739 Vec coordinates; 8740 const PetscScalar *coords; 8741 const PetscInt dim = 3; 8742 PetscInt d; 8743 PetscErrorCode ierr; 8744 8745 PetscFunctionBegin; 8746 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8747 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8748 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8749 if (v0) { 8750 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8751 } 8752 if (J) { 8753 for (d = 0; d < dim; d++) { 8754 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8755 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8756 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8757 } 8758 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8759 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8760 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8761 PetscLogFlops(18.0 + 12.0); 8762 } 8763 if (invJ) { 8764 const PetscReal invDet = -1.0/(*detJ); 8765 8766 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8767 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8768 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8769 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8770 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8771 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8772 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8773 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8774 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8775 PetscLogFlops(37.0); 8776 } 8777 *detJ *= 8.0; 8778 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8779 PetscFunctionReturn(0); 8780 } 8781 8782 #undef __FUNCT__ 8783 #define __FUNCT__ "DMPlexComputeCellGeometry" 8784 /*@C 8785 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8786 8787 Collective on DM 8788 8789 Input Arguments: 8790 + dm - the DM 8791 - cell - the cell 8792 8793 Output Arguments: 8794 + v0 - the translation part of this affine transform 8795 . J - the Jacobian of the transform to the reference element 8796 . invJ - the inverse of the Jacobian 8797 - detJ - the Jacobian determinant 8798 8799 Level: advanced 8800 8801 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8802 @*/ 8803 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8804 { 8805 PetscInt dim, coneSize; 8806 PetscErrorCode ierr; 8807 8808 PetscFunctionBegin; 8809 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8810 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8811 switch (dim) { 8812 case 2: 8813 switch (coneSize) { 8814 case 3: 8815 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8816 break; 8817 case 4: 8818 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8819 break; 8820 default: 8821 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8822 } 8823 break; 8824 case 3: 8825 switch (coneSize) { 8826 case 4: 8827 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8828 break; 8829 case 8: 8830 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8831 break; 8832 default: 8833 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8834 } 8835 break; 8836 default: 8837 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8838 } 8839 PetscFunctionReturn(0); 8840 } 8841 8842 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8843 { 8844 switch (i) { 8845 case 0: 8846 switch (j) { 8847 case 0: return 0; 8848 case 1: 8849 switch (k) { 8850 case 0: return 0; 8851 case 1: return 0; 8852 case 2: return 1; 8853 } 8854 case 2: 8855 switch (k) { 8856 case 0: return 0; 8857 case 1: return -1; 8858 case 2: return 0; 8859 } 8860 } 8861 case 1: 8862 switch (j) { 8863 case 0: 8864 switch (k) { 8865 case 0: return 0; 8866 case 1: return 0; 8867 case 2: return -1; 8868 } 8869 case 1: return 0; 8870 case 2: 8871 switch (k) { 8872 case 0: return 1; 8873 case 1: return 0; 8874 case 2: return 0; 8875 } 8876 } 8877 case 2: 8878 switch (j) { 8879 case 0: 8880 switch (k) { 8881 case 0: return 0; 8882 case 1: return 1; 8883 case 2: return 0; 8884 } 8885 case 1: 8886 switch (k) { 8887 case 0: return -1; 8888 case 1: return 0; 8889 case 2: return 0; 8890 } 8891 case 2: return 0; 8892 } 8893 } 8894 return 0; 8895 } 8896 8897 #undef __FUNCT__ 8898 #define __FUNCT__ "DMPlexCreateRigidBody" 8899 /*@C 8900 DMPlexCreateRigidBody - create rigid body modes from coordinates 8901 8902 Collective on DM 8903 8904 Input Arguments: 8905 + dm - the DM 8906 . section - the local section associated with the rigid field, or NULL for the default section 8907 - globalSection - the global section associated with the rigid field, or NULL for the default section 8908 8909 Output Argument: 8910 . sp - the null space 8911 8912 Note: This is necessary to take account of Dirichlet conditions on the displacements 8913 8914 Level: advanced 8915 8916 .seealso: MatNullSpaceCreate() 8917 @*/ 8918 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8919 { 8920 MPI_Comm comm; 8921 Vec coordinates, localMode, mode[6]; 8922 PetscSection coordSection; 8923 PetscScalar *coords; 8924 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8925 PetscErrorCode ierr; 8926 8927 PetscFunctionBegin; 8928 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 8929 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8930 if (dim == 1) { 8931 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 8932 PetscFunctionReturn(0); 8933 } 8934 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8935 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8936 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8937 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8938 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8939 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8940 m = (dim*(dim+1))/2; 8941 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8942 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8943 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8944 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8945 /* Assume P1 */ 8946 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8947 for (d = 0; d < dim; ++d) { 8948 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8949 8950 values[d] = 1.0; 8951 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8952 for (v = vStart; v < vEnd; ++v) { 8953 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8954 } 8955 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8956 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8957 } 8958 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8959 for (d = dim; d < dim*(dim+1)/2; ++d) { 8960 PetscInt i, j, k = dim > 2 ? d - dim : d; 8961 8962 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8963 for (v = vStart; v < vEnd; ++v) { 8964 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8965 PetscInt off; 8966 8967 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8968 for (i = 0; i < dim; ++i) { 8969 for (j = 0; j < dim; ++j) { 8970 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8971 } 8972 } 8973 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8974 } 8975 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8976 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8977 } 8978 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8979 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8980 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 8981 /* Orthonormalize system */ 8982 for (i = dim; i < m; ++i) { 8983 PetscScalar dots[6]; 8984 8985 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8986 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8987 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8988 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 8989 } 8990 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8991 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8992 PetscFunctionReturn(0); 8993 } 8994 8995 #undef __FUNCT__ 8996 #define __FUNCT__ "DMPlexGetHybridBounds" 8997 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 8998 { 8999 DM_Plex *mesh = (DM_Plex*) dm->data; 9000 PetscInt dim; 9001 PetscErrorCode ierr; 9002 9003 PetscFunctionBegin; 9004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9005 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9006 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9007 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9008 if (eMax) *eMax = mesh->hybridPointMax[1]; 9009 if (vMax) *vMax = mesh->hybridPointMax[0]; 9010 PetscFunctionReturn(0); 9011 } 9012 9013 #undef __FUNCT__ 9014 #define __FUNCT__ "DMPlexSetHybridBounds" 9015 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9016 { 9017 DM_Plex *mesh = (DM_Plex*) dm->data; 9018 PetscInt dim; 9019 PetscErrorCode ierr; 9020 9021 PetscFunctionBegin; 9022 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9023 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9024 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9025 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9026 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9027 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9028 PetscFunctionReturn(0); 9029 } 9030 9031 #undef __FUNCT__ 9032 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9033 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9034 { 9035 DM_Plex *mesh = (DM_Plex*) dm->data; 9036 9037 PetscFunctionBegin; 9038 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9039 PetscValidPointer(cellHeight, 2); 9040 *cellHeight = mesh->vtkCellHeight; 9041 PetscFunctionReturn(0); 9042 } 9043 9044 #undef __FUNCT__ 9045 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9046 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9047 { 9048 DM_Plex *mesh = (DM_Plex*) dm->data; 9049 9050 PetscFunctionBegin; 9051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9052 mesh->vtkCellHeight = cellHeight; 9053 PetscFunctionReturn(0); 9054 } 9055 9056 #undef __FUNCT__ 9057 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9058 /* We can easily have a form that takes an IS instead */ 9059 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9060 { 9061 PetscSection section, globalSection; 9062 PetscInt *numbers, p; 9063 PetscErrorCode ierr; 9064 9065 PetscFunctionBegin; 9066 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 9067 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9068 for (p = pStart; p < pEnd; ++p) { 9069 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9070 } 9071 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9072 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9073 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9074 for (p = pStart; p < pEnd; ++p) { 9075 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9076 } 9077 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9078 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9079 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9080 PetscFunctionReturn(0); 9081 } 9082 9083 #undef __FUNCT__ 9084 #define __FUNCT__ "DMPlexGetCellNumbering" 9085 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9086 { 9087 DM_Plex *mesh = (DM_Plex*) dm->data; 9088 PetscInt cellHeight, cStart, cEnd, cMax; 9089 PetscErrorCode ierr; 9090 9091 PetscFunctionBegin; 9092 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9093 if (!mesh->globalCellNumbers) { 9094 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9095 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9096 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 9097 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9098 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9099 } 9100 *globalCellNumbers = mesh->globalCellNumbers; 9101 PetscFunctionReturn(0); 9102 } 9103 9104 #undef __FUNCT__ 9105 #define __FUNCT__ "DMPlexGetVertexNumbering" 9106 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9107 { 9108 DM_Plex *mesh = (DM_Plex*) dm->data; 9109 PetscInt vStart, vEnd, vMax; 9110 PetscErrorCode ierr; 9111 9112 PetscFunctionBegin; 9113 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9114 if (!mesh->globalVertexNumbers) { 9115 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9116 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9117 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9118 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9119 } 9120 *globalVertexNumbers = mesh->globalVertexNumbers; 9121 PetscFunctionReturn(0); 9122 } 9123 9124 #undef __FUNCT__ 9125 #define __FUNCT__ "DMPlexGetScale" 9126 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9127 { 9128 DM_Plex *mesh = (DM_Plex*) dm->data; 9129 9130 PetscFunctionBegin; 9131 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9132 PetscValidPointer(scale, 3); 9133 *scale = mesh->scale[unit]; 9134 PetscFunctionReturn(0); 9135 } 9136 9137 #undef __FUNCT__ 9138 #define __FUNCT__ "DMPlexSetScale" 9139 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9140 { 9141 DM_Plex *mesh = (DM_Plex*) dm->data; 9142 9143 PetscFunctionBegin; 9144 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9145 mesh->scale[unit] = scale; 9146 PetscFunctionReturn(0); 9147 } 9148 9149 9150 /******************************************************************************* 9151 This should be in a separate Discretization object, but I am not sure how to lay 9152 it out yet, so I am stuffing things here while I experiment. 9153 *******************************************************************************/ 9154 #undef __FUNCT__ 9155 #define __FUNCT__ "DMPlexSetFEMIntegration" 9156 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9157 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9158 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9159 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9160 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9161 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9162 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9163 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9164 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9165 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9166 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9167 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9168 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9169 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9170 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9171 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9172 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9173 { 9174 DM_Plex *mesh = (DM_Plex*) dm->data; 9175 9176 PetscFunctionBegin; 9177 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9178 mesh->integrateResidualFEM = integrateResidualFEM; 9179 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9180 mesh->integrateJacobianFEM = integrateJacobianFEM; 9181 PetscFunctionReturn(0); 9182 } 9183 9184 #undef __FUNCT__ 9185 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9186 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9187 { 9188 Vec coordinates; 9189 PetscSection section, cSection; 9190 PetscInt dim, vStart, vEnd, v, c, d; 9191 PetscScalar *values, *cArray; 9192 PetscReal *coords; 9193 PetscErrorCode ierr; 9194 9195 PetscFunctionBegin; 9196 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9197 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9198 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9199 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9200 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9201 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9202 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9203 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9204 for (v = vStart; v < vEnd; ++v) { 9205 PetscInt dof, off; 9206 9207 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9208 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9209 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9210 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9211 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9212 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9213 } 9214 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9215 /* Temporary, must be replaced by a projection on the finite element basis */ 9216 { 9217 PetscInt eStart = 0, eEnd = 0, e, depth; 9218 9219 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9220 --depth; 9221 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9222 for (e = eStart; e < eEnd; ++e) { 9223 const PetscInt *cone = NULL; 9224 PetscInt coneSize, d; 9225 PetscScalar *coordsA, *coordsB; 9226 9227 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9228 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9229 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9230 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9231 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9232 for (d = 0; d < dim; ++d) { 9233 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9234 } 9235 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9236 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9237 } 9238 } 9239 9240 ierr = PetscFree(coords);CHKERRQ(ierr); 9241 ierr = PetscFree(values);CHKERRQ(ierr); 9242 #if 0 9243 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9244 PetscReal detJ; 9245 9246 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9247 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9248 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9249 9250 for (PetscInt c = cStart; c < cEnd; ++c) { 9251 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9252 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9253 const int oSize = pV.getSize(); 9254 int v = 0; 9255 9256 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9257 for (PetscInt cl = 0; cl < oSize; ++cl) { 9258 const PetscInt fDim; 9259 9260 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9261 if (pointDim) { 9262 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9263 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9264 } 9265 } 9266 } 9267 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9268 pV.clear(); 9269 } 9270 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9271 ierr = PetscFree(values);CHKERRQ(ierr); 9272 #endif 9273 PetscFunctionReturn(0); 9274 } 9275 9276 #undef __FUNCT__ 9277 #define __FUNCT__ "DMPlexProjectFunction" 9278 /*@C 9279 DMPlexProjectFunction - This projects the given function into the function space provided. 9280 9281 Input Parameters: 9282 + dm - The DM 9283 . numComp - The number of components (functions) 9284 . funcs - The coordinate functions to evaluate 9285 - mode - The insertion mode for values 9286 9287 Output Parameter: 9288 . X - vector 9289 9290 Level: developer 9291 9292 Note: 9293 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9294 We will eventually fix it. 9295 9296 ,seealso: DMPlexComputeL2Diff() 9297 */ 9298 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9299 { 9300 Vec localX; 9301 PetscErrorCode ierr; 9302 9303 PetscFunctionBegin; 9304 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9305 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9306 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9307 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9308 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9309 PetscFunctionReturn(0); 9310 } 9311 9312 #undef __FUNCT__ 9313 #define __FUNCT__ "DMPlexComputeL2Diff" 9314 /*@C 9315 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9316 9317 Input Parameters: 9318 + dm - The DM 9319 . quad - The PetscQuadrature object for each field 9320 . funcs - The functions to evaluate for each field component 9321 - X - The coefficient vector u_h 9322 9323 Output Parameter: 9324 . diff - The diff ||u - u_h||_2 9325 9326 Level: developer 9327 9328 .seealso: DMPlexProjectFunction() 9329 */ 9330 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9331 { 9332 const PetscInt debug = 0; 9333 PetscSection section; 9334 Vec localX; 9335 PetscReal *coords, *v0, *J, *invJ, detJ; 9336 PetscReal localDiff = 0.0; 9337 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9338 PetscErrorCode ierr; 9339 9340 PetscFunctionBegin; 9341 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9342 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9343 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9344 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9345 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9346 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9347 for (field = 0; field < numFields; ++field) { 9348 numComponents += quad[field].numComponents; 9349 } 9350 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9351 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9352 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9353 for (c = cStart; c < cEnd; ++c) { 9354 const PetscScalar *x; 9355 PetscReal elemDiff = 0.0; 9356 9357 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9358 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9359 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9360 9361 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9362 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9363 const PetscReal *quadPoints = quad[field].quadPoints; 9364 const PetscReal *quadWeights = quad[field].quadWeights; 9365 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9366 const PetscInt numBasisComps = quad[field].numComponents; 9367 const PetscReal *basis = quad[field].basis; 9368 PetscInt q, d, e, fc, f; 9369 9370 if (debug) { 9371 char title[1024]; 9372 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9373 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9374 } 9375 for (q = 0; q < numQuadPoints; ++q) { 9376 for (d = 0; d < dim; d++) { 9377 coords[d] = v0[d]; 9378 for (e = 0; e < dim; e++) { 9379 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9380 } 9381 } 9382 for (fc = 0; fc < numBasisComps; ++fc) { 9383 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9384 PetscReal interpolant = 0.0; 9385 for (f = 0; f < numBasisFuncs; ++f) { 9386 const PetscInt fidx = f*numBasisComps+fc; 9387 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9388 } 9389 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9390 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9391 } 9392 } 9393 comp += numBasisComps; 9394 fieldOffset += numBasisFuncs*numBasisComps; 9395 } 9396 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9397 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9398 localDiff += elemDiff; 9399 } 9400 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9401 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9402 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9403 *diff = PetscSqrtReal(*diff); 9404 PetscFunctionReturn(0); 9405 } 9406 9407 #undef __FUNCT__ 9408 #define __FUNCT__ "DMPlexComputeResidualFEM" 9409 /*@ 9410 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9411 9412 Input Parameters: 9413 + dm - The mesh 9414 . X - Local input vector 9415 - user - The user context 9416 9417 Output Parameter: 9418 . F - Local output vector 9419 9420 Note: 9421 The second member of the user context must be an FEMContext. 9422 9423 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9424 like a GPU, or vectorize on a multicore machine. 9425 9426 .seealso: DMPlexComputeJacobianActionFEM() 9427 */ 9428 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9429 { 9430 DM_Plex *mesh = (DM_Plex*) dm->data; 9431 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9432 PetscQuadrature *quad = fem->quad; 9433 PetscSection section; 9434 PetscReal *v0, *J, *invJ, *detJ; 9435 PetscScalar *elemVec, *u; 9436 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9437 PetscInt cellDof = 0, numComponents = 0; 9438 PetscErrorCode ierr; 9439 9440 PetscFunctionBegin; 9441 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9442 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9443 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9444 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9445 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9446 numCells = cEnd - cStart; 9447 for (field = 0; field < numFields; ++field) { 9448 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9449 numComponents += quad[field].numComponents; 9450 } 9451 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9452 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9453 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); 9454 for (c = cStart; c < cEnd; ++c) { 9455 const PetscScalar *x; 9456 PetscInt i; 9457 9458 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9459 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9460 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9461 9462 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9463 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9464 } 9465 for (field = 0; field < numFields; ++field) { 9466 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9467 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9468 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9469 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9470 /* Conforming batches */ 9471 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9472 PetscInt numBlocks = 1; 9473 PetscInt batchSize = numBlocks * blockSize; 9474 PetscInt numBatches = numBatchesTmp; 9475 PetscInt numChunks = numCells / (numBatches*batchSize); 9476 /* Remainder */ 9477 PetscInt numRemainder = numCells % (numBatches * batchSize); 9478 PetscInt offset = numCells - numRemainder; 9479 9480 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9481 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9482 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9483 } 9484 for (c = cStart; c < cEnd; ++c) { 9485 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9486 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9487 } 9488 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9489 if (mesh->printFEM) { 9490 PetscMPIInt rank, numProcs; 9491 PetscInt p; 9492 9493 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9494 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9495 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9496 for (p = 0; p < numProcs; ++p) { 9497 if (p == rank) { 9498 Vec f; 9499 9500 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9501 ierr = VecCopy(F, f);CHKERRQ(ierr); 9502 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9503 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9504 ierr = VecDestroy(&f);CHKERRQ(ierr); 9505 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9506 } 9507 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9508 } 9509 } 9510 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9511 PetscFunctionReturn(0); 9512 } 9513 9514 #undef __FUNCT__ 9515 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9516 /*@C 9517 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9518 9519 Input Parameters: 9520 + dm - The mesh 9521 . J - The Jacobian shell matrix 9522 . X - Local input vector 9523 - user - The user context 9524 9525 Output Parameter: 9526 . F - Local output vector 9527 9528 Note: 9529 The second member of the user context must be an FEMContext. 9530 9531 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9532 like a GPU, or vectorize on a multicore machine. 9533 9534 .seealso: DMPlexComputeResidualFEM() 9535 */ 9536 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9537 { 9538 DM_Plex *mesh = (DM_Plex*) dm->data; 9539 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9540 PetscQuadrature *quad = fem->quad; 9541 PetscSection section; 9542 JacActionCtx *jctx; 9543 PetscReal *v0, *J, *invJ, *detJ; 9544 PetscScalar *elemVec, *u, *a; 9545 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9546 PetscInt cellDof = 0; 9547 PetscErrorCode ierr; 9548 9549 PetscFunctionBegin; 9550 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9551 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9552 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9553 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9554 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9555 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9556 numCells = cEnd - cStart; 9557 for (field = 0; field < numFields; ++field) { 9558 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9559 } 9560 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9561 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); 9562 for (c = cStart; c < cEnd; ++c) { 9563 const PetscScalar *x; 9564 PetscInt i; 9565 9566 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9567 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9568 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9569 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9570 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9571 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9572 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9573 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9574 } 9575 for (field = 0; field < numFields; ++field) { 9576 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9577 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9578 /* Conforming batches */ 9579 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9580 PetscInt numBlocks = 1; 9581 PetscInt batchSize = numBlocks * blockSize; 9582 PetscInt numBatches = numBatchesTmp; 9583 PetscInt numChunks = numCells / (numBatches*batchSize); 9584 /* Remainder */ 9585 PetscInt numRemainder = numCells % (numBatches * batchSize); 9586 PetscInt offset = numCells - numRemainder; 9587 9588 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); 9589 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], 9590 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9591 } 9592 for (c = cStart; c < cEnd; ++c) { 9593 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9594 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9595 } 9596 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9597 if (mesh->printFEM) { 9598 PetscMPIInt rank, numProcs; 9599 PetscInt p; 9600 9601 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9602 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9603 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9604 for (p = 0; p < numProcs; ++p) { 9605 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9606 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9607 } 9608 } 9609 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9610 PetscFunctionReturn(0); 9611 } 9612 9613 #undef __FUNCT__ 9614 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9615 /*@ 9616 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9617 9618 Input Parameters: 9619 + dm - The mesh 9620 . X - Local input vector 9621 - user - The user context 9622 9623 Output Parameter: 9624 . Jac - Jacobian matrix 9625 9626 Note: 9627 The second member of the user context must be an FEMContext. 9628 9629 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9630 like a GPU, or vectorize on a multicore machine. 9631 9632 .seealso: FormFunctionLocal() 9633 */ 9634 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9635 { 9636 DM_Plex *mesh = (DM_Plex*) dm->data; 9637 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9638 PetscQuadrature *quad = fem->quad; 9639 PetscSection section; 9640 PetscReal *v0, *J, *invJ, *detJ; 9641 PetscScalar *elemMat, *u; 9642 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9643 PetscInt cellDof = 0, numComponents = 0; 9644 PetscBool isShell; 9645 PetscErrorCode ierr; 9646 9647 PetscFunctionBegin; 9648 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9649 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9650 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9651 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9652 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9653 numCells = cEnd - cStart; 9654 for (field = 0; field < numFields; ++field) { 9655 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9656 numComponents += quad[field].numComponents; 9657 } 9658 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9659 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9660 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); 9661 for (c = cStart; c < cEnd; ++c) { 9662 const PetscScalar *x; 9663 PetscInt i; 9664 9665 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9666 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9667 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9668 9669 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9670 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9671 } 9672 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9673 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9674 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9675 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9676 PetscInt fieldJ; 9677 9678 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9679 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9680 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9681 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9682 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9683 /* Conforming batches */ 9684 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9685 PetscInt numBlocks = 1; 9686 PetscInt batchSize = numBlocks * blockSize; 9687 PetscInt numBatches = numBatchesTmp; 9688 PetscInt numChunks = numCells / (numBatches*batchSize); 9689 /* Remainder */ 9690 PetscInt numRemainder = numCells % (numBatches * batchSize); 9691 PetscInt offset = numCells - numRemainder; 9692 9693 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9694 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9695 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9696 } 9697 } 9698 for (c = cStart; c < cEnd; ++c) { 9699 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9700 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9701 } 9702 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9703 9704 /* Assemble matrix, using the 2-step process: 9705 MatAssemblyBegin(), MatAssemblyEnd(). */ 9706 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9707 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9708 9709 if (mesh->printFEM) { 9710 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9711 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9712 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9713 } 9714 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9715 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9716 if (isShell) { 9717 JacActionCtx *jctx; 9718 9719 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9720 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9721 } 9722 *str = SAME_NONZERO_PATTERN; 9723 PetscFunctionReturn(0); 9724 } 9725 9726 9727 #undef __FUNCT__ 9728 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9729 /*@C 9730 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9731 the local section and an SF describing the section point overlap. 9732 9733 Input Parameters: 9734 + s - The PetscSection for the local field layout 9735 . sf - The SF describing parallel layout of the section points 9736 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9737 . label - The label specifying the points 9738 - labelValue - The label stratum specifying the points 9739 9740 Output Parameter: 9741 . gsection - The PetscSection for the global field layout 9742 9743 Note: This gives negative sizes and offsets to points not owned by this process 9744 9745 Level: developer 9746 9747 .seealso: PetscSectionCreate() 9748 @*/ 9749 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9750 { 9751 PetscInt *neg; 9752 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9753 PetscErrorCode ierr; 9754 9755 PetscFunctionBegin; 9756 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9757 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9758 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9759 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9760 /* Mark ghost points with negative dof */ 9761 for (p = pStart; p < pEnd; ++p) { 9762 PetscInt value; 9763 9764 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9765 if (value != labelValue) continue; 9766 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9767 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9768 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9769 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9770 neg[p-pStart] = -(dof+1); 9771 } 9772 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9773 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 9774 if (nroots >= 0) { 9775 if (nroots > pEnd - pStart) { 9776 PetscInt *tmpDof; 9777 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9778 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9779 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9780 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9781 for (p = pStart; p < pEnd; ++p) { 9782 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 9783 } 9784 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9785 } else { 9786 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9787 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9788 } 9789 } 9790 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9791 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9792 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9793 9794 (*gsection)->atlasOff[p] = off; 9795 9796 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9797 } 9798 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9799 globalOff -= off; 9800 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9801 (*gsection)->atlasOff[p] += globalOff; 9802 9803 neg[p] = -((*gsection)->atlasOff[p]+1); 9804 } 9805 /* Put in negative offsets for ghost points */ 9806 if (nroots >= 0) { 9807 if (nroots > pEnd - pStart) { 9808 PetscInt *tmpOff; 9809 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9810 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9811 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9812 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9813 for (p = pStart; p < pEnd; ++p) { 9814 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 9815 } 9816 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9817 } else { 9818 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9819 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9820 } 9821 } 9822 ierr = PetscFree(neg);CHKERRQ(ierr); 9823 PetscFunctionReturn(0); 9824 } 9825