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 = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4510 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 4511 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);CHKERRQ(ierr); 4512 for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 4513 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 4514 } 4515 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4516 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4517 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4518 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4519 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4520 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4521 for (v = 0; v < numPoints[0]; ++v) { 4522 PetscInt off; 4523 4524 ierr = PetscSectionGetOffset(coordSection, v+firstVertex, &off);CHKERRQ(ierr); 4525 for (d = 0; d < dim; ++d) { 4526 coords[off+d] = vertexCoords[v*dim+d]; 4527 } 4528 } 4529 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4530 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4531 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4532 PetscFunctionReturn(0); 4533 } 4534 4535 #if defined(PETSC_HAVE_TRIANGLE) 4536 #include <triangle.h> 4537 4538 #undef __FUNCT__ 4539 #define __FUNCT__ "InitInput_Triangle" 4540 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4541 { 4542 PetscFunctionBegin; 4543 inputCtx->numberofpoints = 0; 4544 inputCtx->numberofpointattributes = 0; 4545 inputCtx->pointlist = NULL; 4546 inputCtx->pointattributelist = NULL; 4547 inputCtx->pointmarkerlist = NULL; 4548 inputCtx->numberofsegments = 0; 4549 inputCtx->segmentlist = NULL; 4550 inputCtx->segmentmarkerlist = NULL; 4551 inputCtx->numberoftriangleattributes = 0; 4552 inputCtx->trianglelist = NULL; 4553 inputCtx->numberofholes = 0; 4554 inputCtx->holelist = NULL; 4555 inputCtx->numberofregions = 0; 4556 inputCtx->regionlist = NULL; 4557 PetscFunctionReturn(0); 4558 } 4559 4560 #undef __FUNCT__ 4561 #define __FUNCT__ "InitOutput_Triangle" 4562 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4563 { 4564 PetscFunctionBegin; 4565 outputCtx->numberofpoints = 0; 4566 outputCtx->pointlist = NULL; 4567 outputCtx->pointattributelist = NULL; 4568 outputCtx->pointmarkerlist = NULL; 4569 outputCtx->numberoftriangles = 0; 4570 outputCtx->trianglelist = NULL; 4571 outputCtx->triangleattributelist = NULL; 4572 outputCtx->neighborlist = NULL; 4573 outputCtx->segmentlist = NULL; 4574 outputCtx->segmentmarkerlist = NULL; 4575 outputCtx->numberofedges = 0; 4576 outputCtx->edgelist = NULL; 4577 outputCtx->edgemarkerlist = NULL; 4578 PetscFunctionReturn(0); 4579 } 4580 4581 #undef __FUNCT__ 4582 #define __FUNCT__ "FiniOutput_Triangle" 4583 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4584 { 4585 PetscFunctionBegin; 4586 free(outputCtx->pointmarkerlist); 4587 free(outputCtx->edgelist); 4588 free(outputCtx->edgemarkerlist); 4589 free(outputCtx->trianglelist); 4590 free(outputCtx->neighborlist); 4591 PetscFunctionReturn(0); 4592 } 4593 4594 #undef __FUNCT__ 4595 #define __FUNCT__ "DMPlexGenerate_Triangle" 4596 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4597 { 4598 MPI_Comm comm; 4599 PetscInt dim = 2; 4600 const PetscBool createConvexHull = PETSC_FALSE; 4601 const PetscBool constrained = PETSC_FALSE; 4602 struct triangulateio in; 4603 struct triangulateio out; 4604 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4605 PetscMPIInt rank; 4606 PetscErrorCode ierr; 4607 4608 PetscFunctionBegin; 4609 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4610 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4611 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4612 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4613 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4614 4615 in.numberofpoints = vEnd - vStart; 4616 if (in.numberofpoints > 0) { 4617 PetscSection coordSection; 4618 Vec coordinates; 4619 PetscScalar *array; 4620 4621 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4622 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4623 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4624 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4625 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4626 for (v = vStart; v < vEnd; ++v) { 4627 const PetscInt idx = v - vStart; 4628 PetscInt off, d; 4629 4630 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4631 for (d = 0; d < dim; ++d) { 4632 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4633 } 4634 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4635 } 4636 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4637 } 4638 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4639 in.numberofsegments = eEnd - eStart; 4640 if (in.numberofsegments > 0) { 4641 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4642 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4643 for (e = eStart; e < eEnd; ++e) { 4644 const PetscInt idx = e - eStart; 4645 const PetscInt *cone; 4646 4647 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4648 4649 in.segmentlist[idx*2+0] = cone[0] - vStart; 4650 in.segmentlist[idx*2+1] = cone[1] - vStart; 4651 4652 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4653 } 4654 } 4655 #if 0 /* Do not currently support holes */ 4656 PetscReal *holeCoords; 4657 PetscInt h, d; 4658 4659 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4660 if (in.numberofholes > 0) { 4661 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4662 for (h = 0; h < in.numberofholes; ++h) { 4663 for (d = 0; d < dim; ++d) { 4664 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4665 } 4666 } 4667 } 4668 #endif 4669 if (!rank) { 4670 char args[32]; 4671 4672 /* Take away 'Q' for verbose output */ 4673 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4674 if (createConvexHull) { 4675 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4676 } 4677 if (constrained) { 4678 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4679 } 4680 triangulate(args, &in, &out, NULL); 4681 } 4682 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4683 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4684 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4685 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4686 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4687 4688 { 4689 const PetscInt numCorners = 3; 4690 const PetscInt numCells = out.numberoftriangles; 4691 const PetscInt numVertices = out.numberofpoints; 4692 const int *cells = out.trianglelist; 4693 const double *meshCoords = out.pointlist; 4694 4695 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4696 /* Set labels */ 4697 for (v = 0; v < numVertices; ++v) { 4698 if (out.pointmarkerlist[v]) { 4699 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4700 } 4701 } 4702 if (interpolate) { 4703 for (e = 0; e < out.numberofedges; e++) { 4704 if (out.edgemarkerlist[e]) { 4705 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4706 const PetscInt *edges; 4707 PetscInt numEdges; 4708 4709 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4710 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4711 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4712 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4713 } 4714 } 4715 } 4716 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4717 } 4718 #if 0 /* Do not currently support holes */ 4719 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4720 #endif 4721 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4722 PetscFunctionReturn(0); 4723 } 4724 4725 #undef __FUNCT__ 4726 #define __FUNCT__ "DMPlexRefine_Triangle" 4727 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4728 { 4729 MPI_Comm comm; 4730 PetscInt dim = 2; 4731 struct triangulateio in; 4732 struct triangulateio out; 4733 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4734 PetscMPIInt rank; 4735 PetscErrorCode ierr; 4736 4737 PetscFunctionBegin; 4738 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4739 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4740 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4741 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4742 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4743 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4744 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4745 4746 in.numberofpoints = vEnd - vStart; 4747 if (in.numberofpoints > 0) { 4748 PetscSection coordSection; 4749 Vec coordinates; 4750 PetscScalar *array; 4751 4752 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4753 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4754 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4755 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4756 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4757 for (v = vStart; v < vEnd; ++v) { 4758 const PetscInt idx = v - vStart; 4759 PetscInt off, d; 4760 4761 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4762 for (d = 0; d < dim; ++d) { 4763 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4764 } 4765 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4766 } 4767 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4768 } 4769 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4770 4771 in.numberofcorners = 3; 4772 in.numberoftriangles = cEnd - cStart; 4773 4774 in.trianglearealist = (double*) maxVolumes; 4775 if (in.numberoftriangles > 0) { 4776 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4777 for (c = cStart; c < cEnd; ++c) { 4778 const PetscInt idx = c - cStart; 4779 PetscInt *closure = NULL; 4780 PetscInt closureSize; 4781 4782 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4783 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4784 for (v = 0; v < 3; ++v) { 4785 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4786 } 4787 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4788 } 4789 } 4790 /* TODO: Segment markers are missing on input */ 4791 #if 0 /* Do not currently support holes */ 4792 PetscReal *holeCoords; 4793 PetscInt h, d; 4794 4795 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4796 if (in.numberofholes > 0) { 4797 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4798 for (h = 0; h < in.numberofholes; ++h) { 4799 for (d = 0; d < dim; ++d) { 4800 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4801 } 4802 } 4803 } 4804 #endif 4805 if (!rank) { 4806 char args[32]; 4807 4808 /* Take away 'Q' for verbose output */ 4809 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4810 triangulate(args, &in, &out, NULL); 4811 } 4812 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4813 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4814 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4815 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4816 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4817 4818 { 4819 const PetscInt numCorners = 3; 4820 const PetscInt numCells = out.numberoftriangles; 4821 const PetscInt numVertices = out.numberofpoints; 4822 const int *cells = out.trianglelist; 4823 const double *meshCoords = out.pointlist; 4824 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4825 4826 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4827 /* Set labels */ 4828 for (v = 0; v < numVertices; ++v) { 4829 if (out.pointmarkerlist[v]) { 4830 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4831 } 4832 } 4833 if (interpolate) { 4834 PetscInt e; 4835 4836 for (e = 0; e < out.numberofedges; e++) { 4837 if (out.edgemarkerlist[e]) { 4838 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4839 const PetscInt *edges; 4840 PetscInt numEdges; 4841 4842 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4843 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4844 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4845 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4846 } 4847 } 4848 } 4849 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4850 } 4851 #if 0 /* Do not currently support holes */ 4852 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4853 #endif 4854 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4855 PetscFunctionReturn(0); 4856 } 4857 #endif 4858 4859 #if defined(PETSC_HAVE_TETGEN) 4860 #include <tetgen.h> 4861 #undef __FUNCT__ 4862 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4863 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4864 { 4865 MPI_Comm comm; 4866 const PetscInt dim = 3; 4867 ::tetgenio in; 4868 ::tetgenio out; 4869 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4870 PetscMPIInt rank; 4871 PetscErrorCode ierr; 4872 4873 PetscFunctionBegin; 4874 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4875 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4876 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4877 in.numberofpoints = vEnd - vStart; 4878 if (in.numberofpoints > 0) { 4879 PetscSection coordSection; 4880 Vec coordinates; 4881 PetscScalar *array; 4882 4883 in.pointlist = new double[in.numberofpoints*dim]; 4884 in.pointmarkerlist = new int[in.numberofpoints]; 4885 4886 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4887 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4888 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4889 for (v = vStart; v < vEnd; ++v) { 4890 const PetscInt idx = v - vStart; 4891 PetscInt off, d; 4892 4893 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4894 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4895 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4896 } 4897 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4898 } 4899 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4900 4901 in.numberoffacets = fEnd - fStart; 4902 if (in.numberoffacets > 0) { 4903 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4904 in.facetmarkerlist = new int[in.numberoffacets]; 4905 for (f = fStart; f < fEnd; ++f) { 4906 const PetscInt idx = f - fStart; 4907 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 4908 4909 in.facetlist[idx].numberofpolygons = 1; 4910 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4911 in.facetlist[idx].numberofholes = 0; 4912 in.facetlist[idx].holelist = NULL; 4913 4914 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4915 for (p = 0; p < numPoints*2; p += 2) { 4916 const PetscInt point = points[p]; 4917 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 4918 } 4919 4920 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4921 poly->numberofvertices = numVertices; 4922 poly->vertexlist = new int[poly->numberofvertices]; 4923 for (v = 0; v < numVertices; ++v) { 4924 const PetscInt vIdx = points[v] - vStart; 4925 poly->vertexlist[v] = vIdx; 4926 } 4927 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4928 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4929 } 4930 } 4931 if (!rank) { 4932 char args[32]; 4933 4934 /* Take away 'Q' for verbose output */ 4935 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4936 ::tetrahedralize(args, &in, &out); 4937 } 4938 { 4939 const PetscInt numCorners = 4; 4940 const PetscInt numCells = out.numberoftetrahedra; 4941 const PetscInt numVertices = out.numberofpoints; 4942 const int *cells = out.tetrahedronlist; 4943 const double *meshCoords = out.pointlist; 4944 4945 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4946 /* Set labels */ 4947 for (v = 0; v < numVertices; ++v) { 4948 if (out.pointmarkerlist[v]) { 4949 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4950 } 4951 } 4952 if (interpolate) { 4953 PetscInt e; 4954 4955 for (e = 0; e < out.numberofedges; e++) { 4956 if (out.edgemarkerlist[e]) { 4957 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4958 const PetscInt *edges; 4959 PetscInt numEdges; 4960 4961 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4962 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4963 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4964 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4965 } 4966 } 4967 for (f = 0; f < out.numberoftrifaces; f++) { 4968 if (out.trifacemarkerlist[f]) { 4969 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4970 const PetscInt *faces; 4971 PetscInt numFaces; 4972 4973 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4974 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4975 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4976 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4977 } 4978 } 4979 } 4980 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4981 } 4982 PetscFunctionReturn(0); 4983 } 4984 4985 #undef __FUNCT__ 4986 #define __FUNCT__ "DMPlexRefine_Tetgen" 4987 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4988 { 4989 MPI_Comm comm; 4990 const PetscInt dim = 3; 4991 ::tetgenio in; 4992 ::tetgenio out; 4993 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4994 PetscMPIInt rank; 4995 PetscErrorCode ierr; 4996 4997 PetscFunctionBegin; 4998 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4999 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5000 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5001 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5002 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5003 5004 in.numberofpoints = vEnd - vStart; 5005 if (in.numberofpoints > 0) { 5006 PetscSection coordSection; 5007 Vec coordinates; 5008 PetscScalar *array; 5009 5010 in.pointlist = new double[in.numberofpoints*dim]; 5011 in.pointmarkerlist = new int[in.numberofpoints]; 5012 5013 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5014 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5015 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5016 for (v = vStart; v < vEnd; ++v) { 5017 const PetscInt idx = v - vStart; 5018 PetscInt off, d; 5019 5020 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5021 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5022 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5023 } 5024 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5025 } 5026 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5027 5028 in.numberofcorners = 4; 5029 in.numberoftetrahedra = cEnd - cStart; 5030 in.tetrahedronvolumelist = (double*) maxVolumes; 5031 if (in.numberoftetrahedra > 0) { 5032 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5033 for (c = cStart; c < cEnd; ++c) { 5034 const PetscInt idx = c - cStart; 5035 PetscInt *closure = NULL; 5036 PetscInt closureSize; 5037 5038 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5039 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5040 for (v = 0; v < 4; ++v) { 5041 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5042 } 5043 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5044 } 5045 } 5046 /* TODO: Put in boundary faces with markers */ 5047 if (!rank) { 5048 char args[32]; 5049 5050 /* Take away 'Q' for verbose output */ 5051 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5052 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5053 ::tetrahedralize(args, &in, &out); 5054 } 5055 in.tetrahedronvolumelist = NULL; 5056 5057 { 5058 const PetscInt numCorners = 4; 5059 const PetscInt numCells = out.numberoftetrahedra; 5060 const PetscInt numVertices = out.numberofpoints; 5061 const int *cells = out.tetrahedronlist; 5062 const double *meshCoords = out.pointlist; 5063 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5064 5065 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5066 /* Set labels */ 5067 for (v = 0; v < numVertices; ++v) { 5068 if (out.pointmarkerlist[v]) { 5069 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5070 } 5071 } 5072 if (interpolate) { 5073 PetscInt e, f; 5074 5075 for (e = 0; e < out.numberofedges; e++) { 5076 if (out.edgemarkerlist[e]) { 5077 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5078 const PetscInt *edges; 5079 PetscInt numEdges; 5080 5081 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5082 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5083 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5084 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5085 } 5086 } 5087 for (f = 0; f < out.numberoftrifaces; f++) { 5088 if (out.trifacemarkerlist[f]) { 5089 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5090 const PetscInt *faces; 5091 PetscInt numFaces; 5092 5093 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5094 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5095 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5096 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5097 } 5098 } 5099 } 5100 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5101 } 5102 PetscFunctionReturn(0); 5103 } 5104 #endif 5105 5106 #if defined(PETSC_HAVE_CTETGEN) 5107 #include "ctetgen.h" 5108 5109 #undef __FUNCT__ 5110 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5111 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5112 { 5113 MPI_Comm comm; 5114 const PetscInt dim = 3; 5115 PLC *in, *out; 5116 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5117 PetscMPIInt rank; 5118 PetscErrorCode ierr; 5119 5120 PetscFunctionBegin; 5121 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5122 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5123 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5124 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5125 ierr = PLCCreate(&in);CHKERRQ(ierr); 5126 ierr = PLCCreate(&out);CHKERRQ(ierr); 5127 5128 in->numberofpoints = vEnd - vStart; 5129 if (in->numberofpoints > 0) { 5130 PetscSection coordSection; 5131 Vec coordinates; 5132 PetscScalar *array; 5133 5134 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5135 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5136 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5137 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5138 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5139 for (v = vStart; v < vEnd; ++v) { 5140 const PetscInt idx = v - vStart; 5141 PetscInt off, d, m; 5142 5143 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5144 for (d = 0; d < dim; ++d) { 5145 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5146 } 5147 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5148 5149 in->pointmarkerlist[idx] = (int) m; 5150 } 5151 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5152 } 5153 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5154 5155 in->numberoffacets = fEnd - fStart; 5156 if (in->numberoffacets > 0) { 5157 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5158 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5159 for (f = fStart; f < fEnd; ++f) { 5160 const PetscInt idx = f - fStart; 5161 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5162 polygon *poly; 5163 5164 in->facetlist[idx].numberofpolygons = 1; 5165 5166 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5167 5168 in->facetlist[idx].numberofholes = 0; 5169 in->facetlist[idx].holelist = NULL; 5170 5171 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5172 for (p = 0; p < numPoints*2; p += 2) { 5173 const PetscInt point = points[p]; 5174 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5175 } 5176 5177 poly = in->facetlist[idx].polygonlist; 5178 poly->numberofvertices = numVertices; 5179 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5180 for (v = 0; v < numVertices; ++v) { 5181 const PetscInt vIdx = points[v] - vStart; 5182 poly->vertexlist[v] = vIdx; 5183 } 5184 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5185 in->facetmarkerlist[idx] = (int) m; 5186 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5187 } 5188 } 5189 if (!rank) { 5190 TetGenOpts t; 5191 5192 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5193 t.in = boundary; /* Should go away */ 5194 t.plc = 1; 5195 t.quality = 1; 5196 t.edgesout = 1; 5197 t.zeroindex = 1; 5198 t.quiet = 1; 5199 t.verbose = verbose; 5200 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5201 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5202 } 5203 { 5204 const PetscInt numCorners = 4; 5205 const PetscInt numCells = out->numberoftetrahedra; 5206 const PetscInt numVertices = out->numberofpoints; 5207 const int *cells = out->tetrahedronlist; 5208 const double *meshCoords = out->pointlist; 5209 5210 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5211 /* Set labels */ 5212 for (v = 0; v < numVertices; ++v) { 5213 if (out->pointmarkerlist[v]) { 5214 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5215 } 5216 } 5217 if (interpolate) { 5218 PetscInt e; 5219 5220 for (e = 0; e < out->numberofedges; e++) { 5221 if (out->edgemarkerlist[e]) { 5222 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5223 const PetscInt *edges; 5224 PetscInt numEdges; 5225 5226 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5227 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5228 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5229 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5230 } 5231 } 5232 for (f = 0; f < out->numberoftrifaces; f++) { 5233 if (out->trifacemarkerlist[f]) { 5234 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5235 const PetscInt *faces; 5236 PetscInt numFaces; 5237 5238 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5239 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5240 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5241 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5242 } 5243 } 5244 } 5245 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5246 } 5247 5248 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5249 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5250 PetscFunctionReturn(0); 5251 } 5252 5253 #undef __FUNCT__ 5254 #define __FUNCT__ "DMPlexRefine_CTetgen" 5255 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5256 { 5257 MPI_Comm comm; 5258 const PetscInt dim = 3; 5259 PLC *in, *out; 5260 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5261 PetscMPIInt rank; 5262 PetscErrorCode ierr; 5263 5264 PetscFunctionBegin; 5265 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5266 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5267 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5268 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5269 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5270 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5271 ierr = PLCCreate(&in);CHKERRQ(ierr); 5272 ierr = PLCCreate(&out);CHKERRQ(ierr); 5273 5274 in->numberofpoints = vEnd - vStart; 5275 if (in->numberofpoints > 0) { 5276 PetscSection coordSection; 5277 Vec coordinates; 5278 PetscScalar *array; 5279 5280 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5281 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5282 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5283 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5284 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5285 for (v = vStart; v < vEnd; ++v) { 5286 const PetscInt idx = v - vStart; 5287 PetscInt off, d, m; 5288 5289 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5290 for (d = 0; d < dim; ++d) { 5291 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5292 } 5293 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5294 5295 in->pointmarkerlist[idx] = (int) m; 5296 } 5297 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5298 } 5299 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5300 5301 in->numberofcorners = 4; 5302 in->numberoftetrahedra = cEnd - cStart; 5303 in->tetrahedronvolumelist = maxVolumes; 5304 if (in->numberoftetrahedra > 0) { 5305 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5306 for (c = cStart; c < cEnd; ++c) { 5307 const PetscInt idx = c - cStart; 5308 PetscInt *closure = NULL; 5309 PetscInt closureSize; 5310 5311 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5312 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5313 for (v = 0; v < 4; ++v) { 5314 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5315 } 5316 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5317 } 5318 } 5319 if (!rank) { 5320 TetGenOpts t; 5321 5322 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5323 5324 t.in = dm; /* Should go away */ 5325 t.refine = 1; 5326 t.varvolume = 1; 5327 t.quality = 1; 5328 t.edgesout = 1; 5329 t.zeroindex = 1; 5330 t.quiet = 1; 5331 t.verbose = verbose; /* Change this */ 5332 5333 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5334 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5335 } 5336 { 5337 const PetscInt numCorners = 4; 5338 const PetscInt numCells = out->numberoftetrahedra; 5339 const PetscInt numVertices = out->numberofpoints; 5340 const int *cells = out->tetrahedronlist; 5341 const double *meshCoords = out->pointlist; 5342 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5343 5344 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5345 /* Set labels */ 5346 for (v = 0; v < numVertices; ++v) { 5347 if (out->pointmarkerlist[v]) { 5348 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5349 } 5350 } 5351 if (interpolate) { 5352 PetscInt e, f; 5353 5354 for (e = 0; e < out->numberofedges; e++) { 5355 if (out->edgemarkerlist[e]) { 5356 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5357 const PetscInt *edges; 5358 PetscInt numEdges; 5359 5360 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5361 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5362 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5363 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5364 } 5365 } 5366 for (f = 0; f < out->numberoftrifaces; f++) { 5367 if (out->trifacemarkerlist[f]) { 5368 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5369 const PetscInt *faces; 5370 PetscInt numFaces; 5371 5372 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5373 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5374 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5375 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5376 } 5377 } 5378 } 5379 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5380 } 5381 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5382 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5383 PetscFunctionReturn(0); 5384 } 5385 #endif 5386 5387 #undef __FUNCT__ 5388 #define __FUNCT__ "DMPlexGenerate" 5389 /*@C 5390 DMPlexGenerate - Generates a mesh. 5391 5392 Not Collective 5393 5394 Input Parameters: 5395 + boundary - The DMPlex boundary object 5396 . name - The mesh generation package name 5397 - interpolate - Flag to create intermediate mesh elements 5398 5399 Output Parameter: 5400 . mesh - The DMPlex object 5401 5402 Level: intermediate 5403 5404 .keywords: mesh, elements 5405 .seealso: DMPlexCreate(), DMRefine() 5406 @*/ 5407 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5408 { 5409 PetscInt dim; 5410 char genname[1024]; 5411 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5412 PetscErrorCode ierr; 5413 5414 PetscFunctionBegin; 5415 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5416 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5417 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5418 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5419 if (flg) name = genname; 5420 if (name) { 5421 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5422 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5423 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5424 } 5425 switch (dim) { 5426 case 1: 5427 if (!name || isTriangle) { 5428 #if defined(PETSC_HAVE_TRIANGLE) 5429 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5430 #else 5431 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5432 #endif 5433 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5434 break; 5435 case 2: 5436 if (!name || isCTetgen) { 5437 #if defined(PETSC_HAVE_CTETGEN) 5438 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5439 #else 5440 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5441 #endif 5442 } else if (isTetgen) { 5443 #if defined(PETSC_HAVE_TETGEN) 5444 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5445 #else 5446 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5447 #endif 5448 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5449 break; 5450 default: 5451 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5452 } 5453 PetscFunctionReturn(0); 5454 } 5455 5456 typedef PetscInt CellRefiner; 5457 5458 #undef __FUNCT__ 5459 #define __FUNCT__ "GetDepthStart_Private" 5460 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5461 { 5462 PetscFunctionBegin; 5463 if (cStart) *cStart = 0; 5464 if (vStart) *vStart = depthSize[depth]; 5465 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5466 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5467 PetscFunctionReturn(0); 5468 } 5469 5470 #undef __FUNCT__ 5471 #define __FUNCT__ "GetDepthEnd_Private" 5472 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5473 { 5474 PetscFunctionBegin; 5475 if (cEnd) *cEnd = depthSize[depth]; 5476 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5477 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5478 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5479 PetscFunctionReturn(0); 5480 } 5481 5482 #undef __FUNCT__ 5483 #define __FUNCT__ "CellRefinerGetSizes" 5484 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5485 { 5486 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5487 PetscErrorCode ierr; 5488 5489 PetscFunctionBegin; 5490 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5491 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5492 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5493 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5494 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5495 switch (refiner) { 5496 case 1: 5497 /* Simplicial 2D */ 5498 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5499 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5500 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5501 break; 5502 case 3: 5503 /* Hybrid 2D */ 5504 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5505 cMax = PetscMin(cEnd, cMax); 5506 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5507 fMax = PetscMin(fEnd, fMax); 5508 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5509 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 */ 5510 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5511 break; 5512 case 2: 5513 /* Hex 2D */ 5514 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5515 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5516 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5517 break; 5518 default: 5519 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5520 } 5521 PetscFunctionReturn(0); 5522 } 5523 5524 #undef __FUNCT__ 5525 #define __FUNCT__ "CellRefinerSetConeSizes" 5526 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5527 { 5528 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5529 PetscErrorCode ierr; 5530 5531 PetscFunctionBegin; 5532 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5533 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5534 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5535 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5536 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5537 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5538 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5539 switch (refiner) { 5540 case 1: 5541 /* Simplicial 2D */ 5542 /* All cells have 3 faces */ 5543 for (c = cStart; c < cEnd; ++c) { 5544 for (r = 0; r < 4; ++r) { 5545 const PetscInt newp = (c - cStart)*4 + r; 5546 5547 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5548 } 5549 } 5550 /* Split faces have 2 vertices and the same cells as the parent */ 5551 for (f = fStart; f < fEnd; ++f) { 5552 for (r = 0; r < 2; ++r) { 5553 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5554 PetscInt size; 5555 5556 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5557 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5558 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5559 } 5560 } 5561 /* Interior faces have 2 vertices and 2 cells */ 5562 for (c = cStart; c < cEnd; ++c) { 5563 for (r = 0; r < 3; ++r) { 5564 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5565 5566 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5567 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5568 } 5569 } 5570 /* Old vertices have identical supports */ 5571 for (v = vStart; v < vEnd; ++v) { 5572 const PetscInt newp = vStartNew + (v - vStart); 5573 PetscInt size; 5574 5575 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5576 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5577 } 5578 /* Face vertices have 2 + cells*2 supports */ 5579 for (f = fStart; f < fEnd; ++f) { 5580 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5581 PetscInt size; 5582 5583 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5584 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5585 } 5586 break; 5587 case 2: 5588 /* Hex 2D */ 5589 /* All cells have 4 faces */ 5590 for (c = cStart; c < cEnd; ++c) { 5591 for (r = 0; r < 4; ++r) { 5592 const PetscInt newp = (c - cStart)*4 + r; 5593 5594 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5595 } 5596 } 5597 /* Split faces have 2 vertices and the same cells as the parent */ 5598 for (f = fStart; f < fEnd; ++f) { 5599 for (r = 0; r < 2; ++r) { 5600 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5601 PetscInt size; 5602 5603 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5604 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5605 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5606 } 5607 } 5608 /* Interior faces have 2 vertices and 2 cells */ 5609 for (c = cStart; c < cEnd; ++c) { 5610 for (r = 0; r < 4; ++r) { 5611 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5612 5613 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5614 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5615 } 5616 } 5617 /* Old vertices have identical supports */ 5618 for (v = vStart; v < vEnd; ++v) { 5619 const PetscInt newp = vStartNew + (v - vStart); 5620 PetscInt size; 5621 5622 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5623 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5624 } 5625 /* Face vertices have 2 + cells supports */ 5626 for (f = fStart; f < fEnd; ++f) { 5627 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5628 PetscInt size; 5629 5630 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5631 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5632 } 5633 /* Cell vertices have 4 supports */ 5634 for (c = cStart; c < cEnd; ++c) { 5635 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5636 5637 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5638 } 5639 break; 5640 case 3: 5641 /* Hybrid 2D */ 5642 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5643 cMax = PetscMin(cEnd, cMax); 5644 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5645 fMax = PetscMin(fEnd, fMax); 5646 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5647 /* Interior cells have 3 faces */ 5648 for (c = cStart; c < cMax; ++c) { 5649 for (r = 0; r < 4; ++r) { 5650 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5651 5652 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5653 } 5654 } 5655 /* Hybrid cells have 4 faces */ 5656 for (c = cMax; c < cEnd; ++c) { 5657 for (r = 0; r < 2; ++r) { 5658 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5659 5660 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5661 } 5662 } 5663 /* Interior split faces have 2 vertices and the same cells as the parent */ 5664 for (f = fStart; f < fMax; ++f) { 5665 for (r = 0; r < 2; ++r) { 5666 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5667 PetscInt size; 5668 5669 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5670 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5671 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5672 } 5673 } 5674 /* Interior cell faces have 2 vertices and 2 cells */ 5675 for (c = cStart; c < cMax; ++c) { 5676 for (r = 0; r < 3; ++r) { 5677 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5678 5679 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5680 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5681 } 5682 } 5683 /* Hybrid faces have 2 vertices and the same cells */ 5684 for (f = fMax; f < fEnd; ++f) { 5685 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5686 PetscInt size; 5687 5688 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5689 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5690 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5691 } 5692 /* Hybrid cell faces have 2 vertices and 2 cells */ 5693 for (c = cMax; c < cEnd; ++c) { 5694 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5695 5696 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5697 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5698 } 5699 /* Old vertices have identical supports */ 5700 for (v = vStart; v < vEnd; ++v) { 5701 const PetscInt newp = vStartNew + (v - vStart); 5702 PetscInt size; 5703 5704 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5705 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5706 } 5707 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5708 for (f = fStart; f < fMax; ++f) { 5709 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5710 const PetscInt *support; 5711 PetscInt size, newSize = 2, s; 5712 5713 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5714 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5715 for (s = 0; s < size; ++s) { 5716 if (support[s] >= cMax) newSize += 1; 5717 else newSize += 2; 5718 } 5719 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5720 } 5721 break; 5722 default: 5723 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5724 } 5725 PetscFunctionReturn(0); 5726 } 5727 5728 #undef __FUNCT__ 5729 #define __FUNCT__ "CellRefinerSetCones" 5730 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5731 { 5732 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; 5733 PetscInt maxSupportSize, *supportRef; 5734 PetscErrorCode ierr; 5735 5736 PetscFunctionBegin; 5737 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5738 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5739 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5740 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5741 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5742 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5743 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5744 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5745 switch (refiner) { 5746 case 1: 5747 /* Simplicial 2D */ 5748 /* 5749 2 5750 |\ 5751 | \ 5752 | \ 5753 | \ 5754 | C \ 5755 | \ 5756 | \ 5757 2---1---1 5758 |\ D / \ 5759 | 2 0 \ 5760 |A \ / B \ 5761 0---0-------1 5762 */ 5763 /* All cells have 3 faces */ 5764 for (c = cStart; c < cEnd; ++c) { 5765 const PetscInt newp = cStartNew + (c - cStart)*4; 5766 const PetscInt *cone, *ornt; 5767 PetscInt coneNew[3], orntNew[3]; 5768 5769 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5770 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5771 /* A triangle */ 5772 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5773 orntNew[0] = ornt[0]; 5774 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5775 orntNew[1] = -2; 5776 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5777 orntNew[2] = ornt[2]; 5778 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5779 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5780 #if 1 5781 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); 5782 for (p = 0; p < 3; ++p) { 5783 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); 5784 } 5785 #endif 5786 /* B triangle */ 5787 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5788 orntNew[0] = ornt[0]; 5789 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5790 orntNew[1] = ornt[1]; 5791 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5792 orntNew[2] = -2; 5793 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5794 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5795 #if 1 5796 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); 5797 for (p = 0; p < 3; ++p) { 5798 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); 5799 } 5800 #endif 5801 /* C triangle */ 5802 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5803 orntNew[0] = -2; 5804 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5805 orntNew[1] = ornt[1]; 5806 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5807 orntNew[2] = ornt[2]; 5808 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5809 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5810 #if 1 5811 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); 5812 for (p = 0; p < 3; ++p) { 5813 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); 5814 } 5815 #endif 5816 /* D triangle */ 5817 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5818 orntNew[0] = 0; 5819 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5820 orntNew[1] = 0; 5821 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5822 orntNew[2] = 0; 5823 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5824 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5825 #if 1 5826 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); 5827 for (p = 0; p < 3; ++p) { 5828 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); 5829 } 5830 #endif 5831 } 5832 /* Split faces have 2 vertices and the same cells as the parent */ 5833 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5834 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5835 for (f = fStart; f < fEnd; ++f) { 5836 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5837 5838 for (r = 0; r < 2; ++r) { 5839 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5840 const PetscInt *cone, *support; 5841 PetscInt coneNew[2], coneSize, c, supportSize, s; 5842 5843 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5844 coneNew[0] = vStartNew + (cone[0] - vStart); 5845 coneNew[1] = vStartNew + (cone[1] - vStart); 5846 coneNew[(r+1)%2] = newv; 5847 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5848 #if 1 5849 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5850 for (p = 0; p < 2; ++p) { 5851 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); 5852 } 5853 #endif 5854 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5855 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5856 for (s = 0; s < supportSize; ++s) { 5857 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5858 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5859 for (c = 0; c < coneSize; ++c) { 5860 if (cone[c] == f) break; 5861 } 5862 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5863 } 5864 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5865 #if 1 5866 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5867 for (p = 0; p < supportSize; ++p) { 5868 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); 5869 } 5870 #endif 5871 } 5872 } 5873 /* Interior faces have 2 vertices and 2 cells */ 5874 for (c = cStart; c < cEnd; ++c) { 5875 const PetscInt *cone; 5876 5877 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5878 for (r = 0; r < 3; ++r) { 5879 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5880 PetscInt coneNew[2]; 5881 PetscInt supportNew[2]; 5882 5883 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5884 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5885 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5886 #if 1 5887 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5888 for (p = 0; p < 2; ++p) { 5889 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); 5890 } 5891 #endif 5892 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5893 supportNew[1] = (c - cStart)*4 + 3; 5894 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5895 #if 1 5896 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5897 for (p = 0; p < 2; ++p) { 5898 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); 5899 } 5900 #endif 5901 } 5902 } 5903 /* Old vertices have identical supports */ 5904 for (v = vStart; v < vEnd; ++v) { 5905 const PetscInt newp = vStartNew + (v - vStart); 5906 const PetscInt *support, *cone; 5907 PetscInt size, s; 5908 5909 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5910 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5911 for (s = 0; s < size; ++s) { 5912 PetscInt r = 0; 5913 5914 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5915 if (cone[1] == v) r = 1; 5916 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5917 } 5918 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5919 #if 1 5920 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5921 for (p = 0; p < size; ++p) { 5922 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); 5923 } 5924 #endif 5925 } 5926 /* Face vertices have 2 + cells*2 supports */ 5927 for (f = fStart; f < fEnd; ++f) { 5928 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5929 const PetscInt *cone, *support; 5930 PetscInt size, s; 5931 5932 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5933 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5934 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5935 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5936 for (s = 0; s < size; ++s) { 5937 PetscInt r = 0; 5938 5939 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5940 if (cone[1] == f) r = 1; 5941 else if (cone[2] == f) r = 2; 5942 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5943 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5944 } 5945 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5946 #if 1 5947 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5948 for (p = 0; p < 2+size*2; ++p) { 5949 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); 5950 } 5951 #endif 5952 } 5953 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5954 break; 5955 case 2: 5956 /* Hex 2D */ 5957 /* 5958 3---------2---------2 5959 | | | 5960 | D 2 C | 5961 | | | 5962 3----3----0----1----1 5963 | | | 5964 | A 0 B | 5965 | | | 5966 0---------0---------1 5967 */ 5968 /* All cells have 4 faces */ 5969 for (c = cStart; c < cEnd; ++c) { 5970 const PetscInt newp = (c - cStart)*4; 5971 const PetscInt *cone, *ornt; 5972 PetscInt coneNew[4], orntNew[4]; 5973 5974 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5975 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5976 /* A quad */ 5977 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5978 orntNew[0] = ornt[0]; 5979 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5980 orntNew[1] = 0; 5981 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5982 orntNew[2] = -2; 5983 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5984 orntNew[3] = ornt[3]; 5985 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5986 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5987 #if 1 5988 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); 5989 for (p = 0; p < 4; ++p) { 5990 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); 5991 } 5992 #endif 5993 /* B quad */ 5994 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5995 orntNew[0] = ornt[0]; 5996 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5997 orntNew[1] = ornt[1]; 5998 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5999 orntNew[2] = 0; 6000 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6001 orntNew[3] = -2; 6002 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6003 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6004 #if 1 6005 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); 6006 for (p = 0; p < 4; ++p) { 6007 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); 6008 } 6009 #endif 6010 /* C quad */ 6011 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6012 orntNew[0] = -2; 6013 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6014 orntNew[1] = ornt[1]; 6015 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6016 orntNew[2] = ornt[2]; 6017 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6018 orntNew[3] = 0; 6019 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6020 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6021 #if 1 6022 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); 6023 for (p = 0; p < 4; ++p) { 6024 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); 6025 } 6026 #endif 6027 /* D quad */ 6028 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6029 orntNew[0] = 0; 6030 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6031 orntNew[1] = -2; 6032 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6033 orntNew[2] = ornt[2]; 6034 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6035 orntNew[3] = ornt[3]; 6036 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6037 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6038 #if 1 6039 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); 6040 for (p = 0; p < 4; ++p) { 6041 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); 6042 } 6043 #endif 6044 } 6045 /* Split faces have 2 vertices and the same cells as the parent */ 6046 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6047 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6048 for (f = fStart; f < fEnd; ++f) { 6049 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6050 6051 for (r = 0; r < 2; ++r) { 6052 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6053 const PetscInt *cone, *support; 6054 PetscInt coneNew[2], coneSize, c, supportSize, s; 6055 6056 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6057 coneNew[0] = vStartNew + (cone[0] - vStart); 6058 coneNew[1] = vStartNew + (cone[1] - vStart); 6059 coneNew[(r+1)%2] = newv; 6060 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6061 #if 1 6062 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6063 for (p = 0; p < 2; ++p) { 6064 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); 6065 } 6066 #endif 6067 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6068 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6069 for (s = 0; s < supportSize; ++s) { 6070 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6071 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6072 for (c = 0; c < coneSize; ++c) { 6073 if (cone[c] == f) break; 6074 } 6075 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6076 } 6077 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6078 #if 1 6079 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6080 for (p = 0; p < supportSize; ++p) { 6081 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); 6082 } 6083 #endif 6084 } 6085 } 6086 /* Interior faces have 2 vertices and 2 cells */ 6087 for (c = cStart; c < cEnd; ++c) { 6088 const PetscInt *cone; 6089 PetscInt coneNew[2], supportNew[2]; 6090 6091 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6092 for (r = 0; r < 4; ++r) { 6093 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6094 6095 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6096 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6097 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6098 #if 1 6099 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6100 for (p = 0; p < 2; ++p) { 6101 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); 6102 } 6103 #endif 6104 supportNew[0] = (c - cStart)*4 + r; 6105 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6106 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6107 #if 1 6108 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6109 for (p = 0; p < 2; ++p) { 6110 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); 6111 } 6112 #endif 6113 } 6114 } 6115 /* Old vertices have identical supports */ 6116 for (v = vStart; v < vEnd; ++v) { 6117 const PetscInt newp = vStartNew + (v - vStart); 6118 const PetscInt *support, *cone; 6119 PetscInt size, s; 6120 6121 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6122 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6123 for (s = 0; s < size; ++s) { 6124 PetscInt r = 0; 6125 6126 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6127 if (cone[1] == v) r = 1; 6128 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6129 } 6130 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6131 #if 1 6132 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6133 for (p = 0; p < size; ++p) { 6134 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); 6135 } 6136 #endif 6137 } 6138 /* Face vertices have 2 + cells supports */ 6139 for (f = fStart; f < fEnd; ++f) { 6140 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6141 const PetscInt *cone, *support; 6142 PetscInt size, s; 6143 6144 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6145 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6146 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6147 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6148 for (s = 0; s < size; ++s) { 6149 PetscInt r = 0; 6150 6151 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6152 if (cone[1] == f) r = 1; 6153 else if (cone[2] == f) r = 2; 6154 else if (cone[3] == f) r = 3; 6155 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6156 } 6157 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6158 #if 1 6159 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6160 for (p = 0; p < 2+size; ++p) { 6161 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); 6162 } 6163 #endif 6164 } 6165 /* Cell vertices have 4 supports */ 6166 for (c = cStart; c < cEnd; ++c) { 6167 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6168 PetscInt supportNew[4]; 6169 6170 for (r = 0; r < 4; ++r) { 6171 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6172 } 6173 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6174 } 6175 break; 6176 case 3: 6177 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6178 cMax = PetscMin(cEnd, cMax); 6179 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6180 fMax = PetscMin(fEnd, fMax); 6181 /* Interior cells have 3 faces */ 6182 for (c = cStart; c < cMax; ++c) { 6183 const PetscInt newp = cStartNew + (c - cStart)*4; 6184 const PetscInt *cone, *ornt; 6185 PetscInt coneNew[3], orntNew[3]; 6186 6187 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6188 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6189 /* A triangle */ 6190 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6191 orntNew[0] = ornt[0]; 6192 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6193 orntNew[1] = -2; 6194 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6195 orntNew[2] = ornt[2]; 6196 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6197 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6198 #if 1 6199 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); 6200 for (p = 0; p < 3; ++p) { 6201 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); 6202 } 6203 #endif 6204 /* B triangle */ 6205 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6206 orntNew[0] = ornt[0]; 6207 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6208 orntNew[1] = ornt[1]; 6209 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6210 orntNew[2] = -2; 6211 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6212 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6213 #if 1 6214 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); 6215 for (p = 0; p < 3; ++p) { 6216 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); 6217 } 6218 #endif 6219 /* C triangle */ 6220 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6221 orntNew[0] = -2; 6222 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6223 orntNew[1] = ornt[1]; 6224 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6225 orntNew[2] = ornt[2]; 6226 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6227 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6228 #if 1 6229 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); 6230 for (p = 0; p < 3; ++p) { 6231 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); 6232 } 6233 #endif 6234 /* D triangle */ 6235 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6236 orntNew[0] = 0; 6237 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6238 orntNew[1] = 0; 6239 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6240 orntNew[2] = 0; 6241 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6242 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6243 #if 1 6244 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); 6245 for (p = 0; p < 3; ++p) { 6246 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); 6247 } 6248 #endif 6249 } 6250 /* 6251 2----3----3 6252 | | 6253 | B | 6254 | | 6255 0----4--- 1 6256 | | 6257 | A | 6258 | | 6259 0----2----1 6260 */ 6261 /* Hybrid cells have 4 faces */ 6262 for (c = cMax; c < cEnd; ++c) { 6263 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6264 const PetscInt *cone, *ornt; 6265 PetscInt coneNew[4], orntNew[4]; 6266 6267 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6268 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6269 /* A quad */ 6270 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6271 orntNew[0] = ornt[0]; 6272 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6273 orntNew[1] = ornt[1]; 6274 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6275 orntNew[2] = 0; 6276 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6277 orntNew[3] = 0; 6278 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6279 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6280 #if 1 6281 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); 6282 for (p = 0; p < 4; ++p) { 6283 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); 6284 } 6285 #endif 6286 /* B quad */ 6287 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6288 orntNew[0] = ornt[0]; 6289 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6290 orntNew[1] = ornt[1]; 6291 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6292 orntNew[2] = 0; 6293 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6294 orntNew[3] = 0; 6295 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6296 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6297 #if 1 6298 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); 6299 for (p = 0; p < 4; ++p) { 6300 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); 6301 } 6302 #endif 6303 } 6304 /* Interior split faces have 2 vertices and the same cells as the parent */ 6305 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6306 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6307 for (f = fStart; f < fMax; ++f) { 6308 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6309 6310 for (r = 0; r < 2; ++r) { 6311 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6312 const PetscInt *cone, *support; 6313 PetscInt coneNew[2], coneSize, c, supportSize, s; 6314 6315 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6316 coneNew[0] = vStartNew + (cone[0] - vStart); 6317 coneNew[1] = vStartNew + (cone[1] - vStart); 6318 coneNew[(r+1)%2] = newv; 6319 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6320 #if 1 6321 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6322 for (p = 0; p < 2; ++p) { 6323 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); 6324 } 6325 #endif 6326 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6327 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6328 for (s = 0; s < supportSize; ++s) { 6329 if (support[s] >= cMax) { 6330 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6331 } else { 6332 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6333 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6334 for (c = 0; c < coneSize; ++c) { 6335 if (cone[c] == f) break; 6336 } 6337 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6338 } 6339 } 6340 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6341 #if 1 6342 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6343 for (p = 0; p < supportSize; ++p) { 6344 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); 6345 } 6346 #endif 6347 } 6348 } 6349 /* Interior cell faces have 2 vertices and 2 cells */ 6350 for (c = cStart; c < cMax; ++c) { 6351 const PetscInt *cone; 6352 6353 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6354 for (r = 0; r < 3; ++r) { 6355 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6356 PetscInt coneNew[2]; 6357 PetscInt supportNew[2]; 6358 6359 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6360 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6361 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6362 #if 1 6363 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6364 for (p = 0; p < 2; ++p) { 6365 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); 6366 } 6367 #endif 6368 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6369 supportNew[1] = (c - cStart)*4 + 3; 6370 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6371 #if 1 6372 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6373 for (p = 0; p < 2; ++p) { 6374 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); 6375 } 6376 #endif 6377 } 6378 } 6379 /* Interior hybrid faces have 2 vertices and the same cells */ 6380 for (f = fMax; f < fEnd; ++f) { 6381 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6382 const PetscInt *cone; 6383 const PetscInt *support; 6384 PetscInt coneNew[2]; 6385 PetscInt supportNew[2]; 6386 PetscInt size, s, r; 6387 6388 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6389 coneNew[0] = vStartNew + (cone[0] - vStart); 6390 coneNew[1] = vStartNew + (cone[1] - vStart); 6391 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6392 #if 1 6393 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6394 for (p = 0; p < 2; ++p) { 6395 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); 6396 } 6397 #endif 6398 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6399 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6400 for (s = 0; s < size; ++s) { 6401 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6402 for (r = 0; r < 2; ++r) { 6403 if (cone[r+2] == f) break; 6404 } 6405 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6406 } 6407 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6408 #if 1 6409 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6410 for (p = 0; p < size; ++p) { 6411 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); 6412 } 6413 #endif 6414 } 6415 /* Cell hybrid faces have 2 vertices and 2 cells */ 6416 for (c = cMax; c < cEnd; ++c) { 6417 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6418 const PetscInt *cone; 6419 PetscInt coneNew[2]; 6420 PetscInt supportNew[2]; 6421 6422 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6423 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6424 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6425 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6426 #if 1 6427 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6428 for (p = 0; p < 2; ++p) { 6429 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); 6430 } 6431 #endif 6432 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6433 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6434 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6435 #if 1 6436 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6437 for (p = 0; p < 2; ++p) { 6438 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); 6439 } 6440 #endif 6441 } 6442 /* Old vertices have identical supports */ 6443 for (v = vStart; v < vEnd; ++v) { 6444 const PetscInt newp = vStartNew + (v - vStart); 6445 const PetscInt *support, *cone; 6446 PetscInt size, s; 6447 6448 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6449 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6450 for (s = 0; s < size; ++s) { 6451 if (support[s] >= fMax) { 6452 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6453 } else { 6454 PetscInt r = 0; 6455 6456 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6457 if (cone[1] == v) r = 1; 6458 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6459 } 6460 } 6461 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6462 #if 1 6463 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6464 for (p = 0; p < size; ++p) { 6465 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); 6466 } 6467 #endif 6468 } 6469 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6470 for (f = fStart; f < fMax; ++f) { 6471 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6472 const PetscInt *cone, *support; 6473 PetscInt size, newSize = 2, s; 6474 6475 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6476 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6477 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6478 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6479 for (s = 0; s < size; ++s) { 6480 PetscInt r = 0; 6481 6482 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6483 if (support[s] >= cMax) { 6484 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6485 6486 newSize += 1; 6487 } else { 6488 if (cone[1] == f) r = 1; 6489 else if (cone[2] == f) r = 2; 6490 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6491 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6492 6493 newSize += 2; 6494 } 6495 } 6496 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6497 #if 1 6498 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6499 for (p = 0; p < newSize; ++p) { 6500 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); 6501 } 6502 #endif 6503 } 6504 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6505 break; 6506 default: 6507 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6508 } 6509 PetscFunctionReturn(0); 6510 } 6511 6512 #undef __FUNCT__ 6513 #define __FUNCT__ "CellRefinerSetCoordinates" 6514 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6515 { 6516 PetscSection coordSection, coordSectionNew; 6517 Vec coordinates, coordinatesNew; 6518 PetscScalar *coords, *coordsNew; 6519 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6520 PetscErrorCode ierr; 6521 6522 PetscFunctionBegin; 6523 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6524 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6525 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6526 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6527 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6528 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6529 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6530 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6531 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6532 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6533 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6534 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6535 if (fMax < 0) fMax = fEnd; 6536 switch (refiner) { 6537 case 1: 6538 case 2: 6539 case 3: 6540 /* Simplicial and Hex 2D */ 6541 /* All vertices have the dim coordinates */ 6542 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6543 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6544 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6545 } 6546 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6547 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6548 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6549 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6550 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6551 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6552 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6553 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6554 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6555 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6556 /* Old vertices have the same coordinates */ 6557 for (v = vStart; v < vEnd; ++v) { 6558 const PetscInt newv = vStartNew + (v - vStart); 6559 PetscInt off, offnew, d; 6560 6561 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6562 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6563 for (d = 0; d < dim; ++d) { 6564 coordsNew[offnew+d] = coords[off+d]; 6565 } 6566 } 6567 /* Face vertices have the average of endpoint coordinates */ 6568 for (f = fStart; f < fMax; ++f) { 6569 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6570 const PetscInt *cone; 6571 PetscInt coneSize, offA, offB, offnew, d; 6572 6573 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6574 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6575 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6576 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6577 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6578 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6579 for (d = 0; d < dim; ++d) { 6580 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6581 } 6582 } 6583 /* Just Hex 2D */ 6584 if (refiner == 2) { 6585 /* Cell vertices have the average of corner coordinates */ 6586 for (c = cStart; c < cEnd; ++c) { 6587 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6588 PetscInt *cone = NULL; 6589 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6590 6591 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6592 for (p = 0; p < closureSize*2; p += 2) { 6593 const PetscInt point = cone[p]; 6594 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6595 } 6596 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6597 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6598 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6599 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6600 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6601 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6602 for (d = 0; d < dim; ++d) { 6603 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6604 } 6605 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6606 } 6607 } 6608 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6609 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6610 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6611 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6612 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 6613 break; 6614 default: 6615 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6616 } 6617 PetscFunctionReturn(0); 6618 } 6619 6620 #undef __FUNCT__ 6621 #define __FUNCT__ "DMPlexCreateProcessSF" 6622 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6623 { 6624 PetscInt numRoots, numLeaves, l; 6625 const PetscInt *localPoints; 6626 const PetscSFNode *remotePoints; 6627 PetscInt *localPointsNew; 6628 PetscSFNode *remotePointsNew; 6629 PetscInt *ranks, *ranksNew; 6630 PetscErrorCode ierr; 6631 6632 PetscFunctionBegin; 6633 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6634 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6635 for (l = 0; l < numLeaves; ++l) { 6636 ranks[l] = remotePoints[l].rank; 6637 } 6638 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6639 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6640 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6641 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6642 for (l = 0; l < numLeaves; ++l) { 6643 ranksNew[l] = ranks[l]; 6644 localPointsNew[l] = l; 6645 remotePointsNew[l].index = 0; 6646 remotePointsNew[l].rank = ranksNew[l]; 6647 } 6648 ierr = PetscFree(ranks);CHKERRQ(ierr); 6649 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6650 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 6651 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6652 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6653 PetscFunctionReturn(0); 6654 } 6655 6656 #undef __FUNCT__ 6657 #define __FUNCT__ "CellRefinerCreateSF" 6658 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6659 { 6660 PetscSF sf, sfNew, sfProcess; 6661 IS processRanks; 6662 MPI_Datatype depthType; 6663 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6664 const PetscInt *localPoints, *neighbors; 6665 const PetscSFNode *remotePoints; 6666 PetscInt *localPointsNew; 6667 PetscSFNode *remotePointsNew; 6668 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6669 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6670 PetscErrorCode ierr; 6671 6672 PetscFunctionBegin; 6673 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6674 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6675 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6676 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6677 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6678 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6679 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6680 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6681 switch (refiner) { 6682 case 3: 6683 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6684 cMax = PetscMin(cEnd, cMax); 6685 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6686 fMax = PetscMin(fEnd, fMax); 6687 } 6688 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6689 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6690 /* Caculate size of new SF */ 6691 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6692 if (numRoots < 0) PetscFunctionReturn(0); 6693 for (l = 0; l < numLeaves; ++l) { 6694 const PetscInt p = localPoints[l]; 6695 6696 switch (refiner) { 6697 case 1: 6698 /* Simplicial 2D */ 6699 if ((p >= vStart) && (p < vEnd)) { 6700 /* Old vertices stay the same */ 6701 ++numLeavesNew; 6702 } else if ((p >= fStart) && (p < fEnd)) { 6703 /* Old faces add new faces and vertex */ 6704 numLeavesNew += 1 + 2; 6705 } else if ((p >= cStart) && (p < cEnd)) { 6706 /* Old cells add new cells and interior faces */ 6707 numLeavesNew += 4 + 3; 6708 } 6709 break; 6710 case 2: 6711 /* Hex 2D */ 6712 if ((p >= vStart) && (p < vEnd)) { 6713 /* Old vertices stay the same */ 6714 ++numLeavesNew; 6715 } else if ((p >= fStart) && (p < fEnd)) { 6716 /* Old faces add new faces and vertex */ 6717 numLeavesNew += 1 + 2; 6718 } else if ((p >= cStart) && (p < cEnd)) { 6719 /* Old cells add new cells and interior faces */ 6720 numLeavesNew += 4 + 4; 6721 } 6722 break; 6723 default: 6724 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6725 } 6726 } 6727 /* Communicate depthSizes for each remote rank */ 6728 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6729 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6730 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6731 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); 6732 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6733 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6734 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6735 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6736 for (n = 0; n < numNeighbors; ++n) { 6737 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6738 } 6739 depthSizeOld[depth] = cMax; 6740 depthSizeOld[0] = vMax; 6741 depthSizeOld[depth-1] = fMax; 6742 depthSizeOld[1] = eMax; 6743 6744 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6745 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6746 6747 depthSizeOld[depth] = cEnd - cStart; 6748 depthSizeOld[0] = vEnd - vStart; 6749 depthSizeOld[depth-1] = fEnd - fStart; 6750 depthSizeOld[1] = eEnd - eStart; 6751 6752 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6753 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6754 for (n = 0; n < numNeighbors; ++n) { 6755 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6756 } 6757 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6758 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6759 /* Calculate new point SF */ 6760 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6761 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6762 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6763 for (l = 0, m = 0; l < numLeaves; ++l) { 6764 PetscInt p = localPoints[l]; 6765 PetscInt rp = remotePoints[l].index, n; 6766 PetscMPIInt rrank = remotePoints[l].rank; 6767 6768 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6769 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6770 switch (refiner) { 6771 case 1: 6772 /* Simplicial 2D */ 6773 if ((p >= vStart) && (p < vEnd)) { 6774 /* Old vertices stay the same */ 6775 localPointsNew[m] = vStartNew + (p - vStart); 6776 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6777 remotePointsNew[m].rank = rrank; 6778 ++m; 6779 } else if ((p >= fStart) && (p < fEnd)) { 6780 /* Old faces add new faces and vertex */ 6781 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6782 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6783 remotePointsNew[m].rank = rrank; 6784 ++m; 6785 for (r = 0; r < 2; ++r, ++m) { 6786 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6787 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6788 remotePointsNew[m].rank = rrank; 6789 } 6790 } else if ((p >= cStart) && (p < cEnd)) { 6791 /* Old cells add new cells and interior faces */ 6792 for (r = 0; r < 4; ++r, ++m) { 6793 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6794 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6795 remotePointsNew[m].rank = rrank; 6796 } 6797 for (r = 0; r < 3; ++r, ++m) { 6798 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6799 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6800 remotePointsNew[m].rank = rrank; 6801 } 6802 } 6803 break; 6804 case 2: 6805 /* Hex 2D */ 6806 if ((p >= vStart) && (p < vEnd)) { 6807 /* Old vertices stay the same */ 6808 localPointsNew[m] = vStartNew + (p - vStart); 6809 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6810 remotePointsNew[m].rank = rrank; 6811 ++m; 6812 } else if ((p >= fStart) && (p < fEnd)) { 6813 /* Old faces add new faces and vertex */ 6814 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6815 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6816 remotePointsNew[m].rank = rrank; 6817 ++m; 6818 for (r = 0; r < 2; ++r, ++m) { 6819 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6820 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6821 remotePointsNew[m].rank = rrank; 6822 } 6823 } else if ((p >= cStart) && (p < cEnd)) { 6824 /* Old cells add new cells and interior faces */ 6825 for (r = 0; r < 4; ++r, ++m) { 6826 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6827 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6828 remotePointsNew[m].rank = rrank; 6829 } 6830 for (r = 0; r < 4; ++r, ++m) { 6831 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6832 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6833 remotePointsNew[m].rank = rrank; 6834 } 6835 } 6836 break; 6837 case 3: 6838 /* Hybrid simplicial 2D */ 6839 if ((p >= vStart) && (p < vEnd)) { 6840 /* Old vertices stay the same */ 6841 localPointsNew[m] = vStartNew + (p - vStart); 6842 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6843 remotePointsNew[m].rank = rrank; 6844 ++m; 6845 } else if ((p >= fStart) && (p < fMax)) { 6846 /* Old interior faces add new faces and vertex */ 6847 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6848 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6849 remotePointsNew[m].rank = rrank; 6850 ++m; 6851 for (r = 0; r < 2; ++r, ++m) { 6852 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6853 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6854 remotePointsNew[m].rank = rrank; 6855 } 6856 } else if ((p >= fMax) && (p < fEnd)) { 6857 /* Old hybrid faces stay the same */ 6858 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6859 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6860 remotePointsNew[m].rank = rrank; 6861 ++m; 6862 } else if ((p >= cStart) && (p < cMax)) { 6863 /* Old interior cells add new cells and interior faces */ 6864 for (r = 0; r < 4; ++r, ++m) { 6865 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6866 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6867 remotePointsNew[m].rank = rrank; 6868 } 6869 for (r = 0; r < 3; ++r, ++m) { 6870 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6871 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6872 remotePointsNew[m].rank = rrank; 6873 } 6874 } else if ((p >= cStart) && (p < cMax)) { 6875 /* Old hybrid cells add new cells and hybrid face */ 6876 for (r = 0; r < 2; ++r, ++m) { 6877 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6878 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6879 remotePointsNew[m].rank = rrank; 6880 } 6881 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6882 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]); 6883 remotePointsNew[m].rank = rrank; 6884 ++m; 6885 } 6886 break; 6887 default: 6888 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6889 } 6890 } 6891 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6892 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6893 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6894 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6895 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6896 PetscFunctionReturn(0); 6897 } 6898 6899 #undef __FUNCT__ 6900 #define __FUNCT__ "CellRefinerCreateLabels" 6901 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6902 { 6903 PetscInt numLabels, l; 6904 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6905 PetscErrorCode ierr; 6906 6907 PetscFunctionBegin; 6908 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6909 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6910 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6911 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6912 6913 cStartNew = 0; 6914 vStartNew = depthSize[2]; 6915 fStartNew = depthSize[2] + depthSize[0]; 6916 6917 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6918 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6919 switch (refiner) { 6920 case 3: 6921 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6922 cMax = PetscMin(cEnd, cMax); 6923 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6924 fMax = PetscMin(fEnd, fMax); 6925 } 6926 for (l = 0; l < numLabels; ++l) { 6927 DMLabel label, labelNew; 6928 const char *lname; 6929 PetscBool isDepth; 6930 IS valueIS; 6931 const PetscInt *values; 6932 PetscInt numValues, val; 6933 6934 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6935 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6936 if (isDepth) continue; 6937 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6938 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6939 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6940 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6941 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6942 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6943 for (val = 0; val < numValues; ++val) { 6944 IS pointIS; 6945 const PetscInt *points; 6946 PetscInt numPoints, n; 6947 6948 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6949 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6950 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6951 for (n = 0; n < numPoints; ++n) { 6952 const PetscInt p = points[n]; 6953 switch (refiner) { 6954 case 1: 6955 /* Simplicial 2D */ 6956 if ((p >= vStart) && (p < vEnd)) { 6957 /* Old vertices stay the same */ 6958 newp = vStartNew + (p - vStart); 6959 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6960 } else if ((p >= fStart) && (p < fEnd)) { 6961 /* Old faces add new faces and vertex */ 6962 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6963 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6964 for (r = 0; r < 2; ++r) { 6965 newp = fStartNew + (p - fStart)*2 + r; 6966 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6967 } 6968 } else if ((p >= cStart) && (p < cEnd)) { 6969 /* Old cells add new cells and interior faces */ 6970 for (r = 0; r < 4; ++r) { 6971 newp = cStartNew + (p - cStart)*4 + r; 6972 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6973 } 6974 for (r = 0; r < 3; ++r) { 6975 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6976 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6977 } 6978 } 6979 break; 6980 case 2: 6981 /* Hex 2D */ 6982 if ((p >= vStart) && (p < vEnd)) { 6983 /* Old vertices stay the same */ 6984 newp = vStartNew + (p - vStart); 6985 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6986 } else if ((p >= fStart) && (p < fEnd)) { 6987 /* Old faces add new faces and vertex */ 6988 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6989 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6990 for (r = 0; r < 2; ++r) { 6991 newp = fStartNew + (p - fStart)*2 + r; 6992 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6993 } 6994 } else if ((p >= cStart) && (p < cEnd)) { 6995 /* Old cells add new cells and interior faces and vertex */ 6996 for (r = 0; r < 4; ++r) { 6997 newp = cStartNew + (p - cStart)*4 + r; 6998 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6999 } 7000 for (r = 0; r < 4; ++r) { 7001 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7002 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7003 } 7004 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7005 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7006 } 7007 break; 7008 case 3: 7009 /* Hybrid simplicial 2D */ 7010 if ((p >= vStart) && (p < vEnd)) { 7011 /* Old vertices stay the same */ 7012 newp = vStartNew + (p - vStart); 7013 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7014 } else if ((p >= fStart) && (p < fMax)) { 7015 /* Old interior faces add new faces and vertex */ 7016 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7017 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7018 for (r = 0; r < 2; ++r) { 7019 newp = fStartNew + (p - fStart)*2 + r; 7020 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7021 } 7022 } else if ((p >= fMax) && (p < fEnd)) { 7023 /* Old hybrid faces stay the same */ 7024 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7025 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7026 } else if ((p >= cStart) && (p < cMax)) { 7027 /* Old interior cells add new cells and interior faces */ 7028 for (r = 0; r < 4; ++r) { 7029 newp = cStartNew + (p - cStart)*4 + r; 7030 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7031 } 7032 for (r = 0; r < 3; ++r) { 7033 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7034 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7035 } 7036 } else if ((p >= cMax) && (p < cEnd)) { 7037 /* Old hybrid cells add new cells and hybrid face */ 7038 for (r = 0; r < 2; ++r) { 7039 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7040 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7041 } 7042 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7043 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7044 } 7045 break; 7046 default: 7047 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7048 } 7049 } 7050 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7051 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7052 } 7053 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7054 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7055 if (0) { 7056 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7057 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7058 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7059 } 7060 } 7061 PetscFunctionReturn(0); 7062 } 7063 7064 #undef __FUNCT__ 7065 #define __FUNCT__ "DMPlexRefine_Uniform" 7066 /* This will only work for interpolated meshes */ 7067 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7068 { 7069 DM rdm; 7070 PetscInt *depthSize; 7071 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7072 PetscErrorCode ierr; 7073 7074 PetscFunctionBegin; 7075 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 7076 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7077 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7078 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7079 /* Calculate number of new points of each depth */ 7080 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7081 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7082 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7083 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7084 /* Step 1: Set chart */ 7085 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7086 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7087 /* Step 2: Set cone/support sizes */ 7088 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7089 /* Step 3: Setup refined DM */ 7090 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7091 /* Step 4: Set cones and supports */ 7092 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7093 /* Step 5: Stratify */ 7094 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7095 /* Step 6: Set coordinates for vertices */ 7096 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7097 /* Step 7: Create pointSF */ 7098 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7099 /* Step 8: Create labels */ 7100 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7101 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7102 7103 *dmRefined = rdm; 7104 PetscFunctionReturn(0); 7105 } 7106 7107 #undef __FUNCT__ 7108 #define __FUNCT__ "DMPlexSetRefinementUniform" 7109 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7110 { 7111 DM_Plex *mesh = (DM_Plex*) dm->data; 7112 7113 PetscFunctionBegin; 7114 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7115 mesh->refinementUniform = refinementUniform; 7116 PetscFunctionReturn(0); 7117 } 7118 7119 #undef __FUNCT__ 7120 #define __FUNCT__ "DMPlexGetRefinementUniform" 7121 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7122 { 7123 DM_Plex *mesh = (DM_Plex*) dm->data; 7124 7125 PetscFunctionBegin; 7126 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7127 PetscValidPointer(refinementUniform, 2); 7128 *refinementUniform = mesh->refinementUniform; 7129 PetscFunctionReturn(0); 7130 } 7131 7132 #undef __FUNCT__ 7133 #define __FUNCT__ "DMPlexSetRefinementLimit" 7134 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7135 { 7136 DM_Plex *mesh = (DM_Plex*) dm->data; 7137 7138 PetscFunctionBegin; 7139 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7140 mesh->refinementLimit = refinementLimit; 7141 PetscFunctionReturn(0); 7142 } 7143 7144 #undef __FUNCT__ 7145 #define __FUNCT__ "DMPlexGetRefinementLimit" 7146 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7147 { 7148 DM_Plex *mesh = (DM_Plex*) dm->data; 7149 7150 PetscFunctionBegin; 7151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7152 PetscValidPointer(refinementLimit, 2); 7153 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7154 *refinementLimit = mesh->refinementLimit; 7155 PetscFunctionReturn(0); 7156 } 7157 7158 #undef __FUNCT__ 7159 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7160 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7161 { 7162 PetscInt dim, cStart, coneSize, cMax; 7163 PetscErrorCode ierr; 7164 7165 PetscFunctionBegin; 7166 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7167 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7168 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7169 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7170 switch (dim) { 7171 case 2: 7172 switch (coneSize) { 7173 case 3: 7174 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7175 else *cellRefiner = 1; /* Triangular */ 7176 break; 7177 case 4: 7178 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7179 else *cellRefiner = 2; /* Quadrilateral */ 7180 break; 7181 default: 7182 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7183 } 7184 break; 7185 default: 7186 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7187 } 7188 PetscFunctionReturn(0); 7189 } 7190 7191 #undef __FUNCT__ 7192 #define __FUNCT__ "DMRefine_Plex" 7193 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7194 { 7195 PetscReal refinementLimit; 7196 PetscInt dim, cStart, cEnd; 7197 char genname[1024], *name = NULL; 7198 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7199 PetscErrorCode ierr; 7200 7201 PetscFunctionBegin; 7202 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7203 if (isUniform) { 7204 CellRefiner cellRefiner; 7205 7206 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7207 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7208 PetscFunctionReturn(0); 7209 } 7210 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7211 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7212 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7213 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7214 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7215 if (flg) name = genname; 7216 if (name) { 7217 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7218 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7219 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7220 } 7221 switch (dim) { 7222 case 2: 7223 if (!name || isTriangle) { 7224 #if defined(PETSC_HAVE_TRIANGLE) 7225 double *maxVolumes; 7226 PetscInt c; 7227 7228 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7229 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7230 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7231 #else 7232 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7233 #endif 7234 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7235 break; 7236 case 3: 7237 if (!name || isCTetgen) { 7238 #if defined(PETSC_HAVE_CTETGEN) 7239 PetscReal *maxVolumes; 7240 PetscInt c; 7241 7242 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7243 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7244 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7245 #else 7246 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7247 #endif 7248 } else if (isTetgen) { 7249 #if defined(PETSC_HAVE_TETGEN) 7250 double *maxVolumes; 7251 PetscInt c; 7252 7253 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7254 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7255 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7256 #else 7257 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7258 #endif 7259 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7260 break; 7261 default: 7262 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7263 } 7264 PetscFunctionReturn(0); 7265 } 7266 7267 #undef __FUNCT__ 7268 #define __FUNCT__ "DMPlexGetDepth" 7269 /*@ 7270 DMPlexGetDepth - get the number of strata 7271 7272 Not Collective 7273 7274 Input Parameters: 7275 . dm - The DMPlex object 7276 7277 Output Parameters: 7278 . depth - number of strata 7279 7280 Level: developer 7281 7282 Notes: 7283 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7284 7285 .keywords: mesh, points 7286 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7287 @*/ 7288 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7289 { 7290 PetscInt d; 7291 PetscErrorCode ierr; 7292 7293 PetscFunctionBegin; 7294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7295 PetscValidPointer(depth, 2); 7296 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7297 *depth = d-1; 7298 PetscFunctionReturn(0); 7299 } 7300 7301 #undef __FUNCT__ 7302 #define __FUNCT__ "DMPlexGetDepthStratum" 7303 /*@ 7304 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7305 7306 Not Collective 7307 7308 Input Parameters: 7309 + dm - The DMPlex object 7310 - stratumValue - The requested depth 7311 7312 Output Parameters: 7313 + start - The first point at this depth 7314 - end - One beyond the last point at this depth 7315 7316 Level: developer 7317 7318 .keywords: mesh, points 7319 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7320 @*/ 7321 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7322 { 7323 DM_Plex *mesh = (DM_Plex*) dm->data; 7324 DMLabel next = mesh->labels; 7325 PetscBool flg = PETSC_FALSE; 7326 PetscInt depth; 7327 PetscErrorCode ierr; 7328 7329 PetscFunctionBegin; 7330 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7331 if (stratumValue < 0) { 7332 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7333 PetscFunctionReturn(0); 7334 } else { 7335 PetscInt pStart, pEnd; 7336 7337 if (start) *start = 0; 7338 if (end) *end = 0; 7339 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7340 if (pStart == pEnd) PetscFunctionReturn(0); 7341 } 7342 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7343 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7344 /* We should have a generic GetLabel() and a Label class */ 7345 while (next) { 7346 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7347 if (flg) break; 7348 next = next->next; 7349 } 7350 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7351 depth = stratumValue; 7352 if ((depth < 0) || (depth >= next->numStrata)) { 7353 if (start) *start = 0; 7354 if (end) *end = 0; 7355 } else { 7356 if (start) *start = next->points[next->stratumOffsets[depth]]; 7357 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7358 } 7359 PetscFunctionReturn(0); 7360 } 7361 7362 #undef __FUNCT__ 7363 #define __FUNCT__ "DMPlexGetHeightStratum" 7364 /*@ 7365 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7366 7367 Not Collective 7368 7369 Input Parameters: 7370 + dm - The DMPlex object 7371 - stratumValue - The requested height 7372 7373 Output Parameters: 7374 + start - The first point at this height 7375 - end - One beyond the last point at this height 7376 7377 Level: developer 7378 7379 .keywords: mesh, points 7380 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7381 @*/ 7382 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7383 { 7384 DM_Plex *mesh = (DM_Plex*) dm->data; 7385 DMLabel next = mesh->labels; 7386 PetscBool flg = PETSC_FALSE; 7387 PetscInt depth; 7388 PetscErrorCode ierr; 7389 7390 PetscFunctionBegin; 7391 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7392 if (stratumValue < 0) { 7393 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7394 } else { 7395 PetscInt pStart, pEnd; 7396 7397 if (start) *start = 0; 7398 if (end) *end = 0; 7399 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7400 if (pStart == pEnd) PetscFunctionReturn(0); 7401 } 7402 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7403 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7404 /* We should have a generic GetLabel() and a Label class */ 7405 while (next) { 7406 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7407 if (flg) break; 7408 next = next->next; 7409 } 7410 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7411 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7412 if ((depth < 0) || (depth >= next->numStrata)) { 7413 if (start) *start = 0; 7414 if (end) *end = 0; 7415 } else { 7416 if (start) *start = next->points[next->stratumOffsets[depth]]; 7417 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7418 } 7419 PetscFunctionReturn(0); 7420 } 7421 7422 #undef __FUNCT__ 7423 #define __FUNCT__ "DMPlexCreateSectionInitial" 7424 /* Set the number of dof on each point and separate by fields */ 7425 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7426 { 7427 PetscInt *numDofTot; 7428 PetscInt pStart = 0, pEnd = 0; 7429 PetscInt p, d, f; 7430 PetscErrorCode ierr; 7431 7432 PetscFunctionBegin; 7433 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7434 for (d = 0; d <= dim; ++d) { 7435 numDofTot[d] = 0; 7436 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7437 } 7438 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7439 if (numFields > 0) { 7440 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7441 if (numComp) { 7442 for (f = 0; f < numFields; ++f) { 7443 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7444 } 7445 } 7446 } 7447 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7448 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7449 for (d = 0; d <= dim; ++d) { 7450 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7451 for (p = pStart; p < pEnd; ++p) { 7452 for (f = 0; f < numFields; ++f) { 7453 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7454 } 7455 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7456 } 7457 } 7458 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7459 PetscFunctionReturn(0); 7460 } 7461 7462 #undef __FUNCT__ 7463 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7464 /* Set the number of dof on each point and separate by fields 7465 If constDof is PETSC_DETERMINE, constrain every dof on the point 7466 */ 7467 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7468 { 7469 PetscInt numFields; 7470 PetscInt bc; 7471 PetscErrorCode ierr; 7472 7473 PetscFunctionBegin; 7474 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7475 for (bc = 0; bc < numBC; ++bc) { 7476 PetscInt field = 0; 7477 const PetscInt *idx; 7478 PetscInt n, i; 7479 7480 if (numFields) field = bcField[bc]; 7481 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7482 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7483 for (i = 0; i < n; ++i) { 7484 const PetscInt p = idx[i]; 7485 PetscInt numConst = constDof; 7486 7487 /* Constrain every dof on the point */ 7488 if (numConst < 0) { 7489 if (numFields) { 7490 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7491 } else { 7492 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7493 } 7494 } 7495 if (numFields) { 7496 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7497 } 7498 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7499 } 7500 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7501 } 7502 PetscFunctionReturn(0); 7503 } 7504 7505 #undef __FUNCT__ 7506 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7507 /* Set the constrained indices on each point and separate by fields */ 7508 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7509 { 7510 PetscInt *maxConstraints; 7511 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7512 PetscErrorCode ierr; 7513 7514 PetscFunctionBegin; 7515 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7516 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7517 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7518 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7519 for (p = pStart; p < pEnd; ++p) { 7520 PetscInt cdof; 7521 7522 if (numFields) { 7523 for (f = 0; f < numFields; ++f) { 7524 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7525 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7526 } 7527 } else { 7528 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7529 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7530 } 7531 } 7532 for (f = 0; f < numFields; ++f) { 7533 maxConstraints[numFields] += maxConstraints[f]; 7534 } 7535 if (maxConstraints[numFields]) { 7536 PetscInt *indices; 7537 7538 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7539 for (p = pStart; p < pEnd; ++p) { 7540 PetscInt cdof, d; 7541 7542 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7543 if (cdof) { 7544 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7545 if (numFields) { 7546 PetscInt numConst = 0, foff = 0; 7547 7548 for (f = 0; f < numFields; ++f) { 7549 PetscInt cfdof, fdof; 7550 7551 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7552 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7553 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7554 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7555 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7556 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7557 numConst += cfdof; 7558 foff += fdof; 7559 } 7560 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7561 } else { 7562 for (d = 0; d < cdof; ++d) indices[d] = d; 7563 } 7564 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7565 } 7566 } 7567 ierr = PetscFree(indices);CHKERRQ(ierr); 7568 } 7569 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7570 PetscFunctionReturn(0); 7571 } 7572 7573 #undef __FUNCT__ 7574 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7575 /* Set the constrained field indices on each point */ 7576 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7577 { 7578 const PetscInt *points, *indices; 7579 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7580 PetscErrorCode ierr; 7581 7582 PetscFunctionBegin; 7583 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7584 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7585 7586 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7587 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7588 if (!constraintIndices) { 7589 PetscInt *idx, i; 7590 7591 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7592 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7593 for (i = 0; i < maxDof; ++i) idx[i] = i; 7594 for (p = 0; p < numPoints; ++p) { 7595 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7596 } 7597 ierr = PetscFree(idx);CHKERRQ(ierr); 7598 } else { 7599 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7600 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7601 for (p = 0; p < numPoints; ++p) { 7602 PetscInt fcdof; 7603 7604 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7605 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); 7606 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7607 } 7608 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7609 } 7610 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7611 PetscFunctionReturn(0); 7612 } 7613 7614 #undef __FUNCT__ 7615 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7616 /* Set the constrained indices on each point and separate by fields */ 7617 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7618 { 7619 PetscInt *indices; 7620 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7621 PetscErrorCode ierr; 7622 7623 PetscFunctionBegin; 7624 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7625 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7626 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7627 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7628 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7629 for (p = pStart; p < pEnd; ++p) { 7630 PetscInt cdof, d; 7631 7632 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7633 if (cdof) { 7634 PetscInt numConst = 0, foff = 0; 7635 7636 for (f = 0; f < numFields; ++f) { 7637 const PetscInt *fcind; 7638 PetscInt fdof, fcdof; 7639 7640 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7641 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7642 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7643 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7644 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7645 foff += fdof; 7646 numConst += fcdof; 7647 } 7648 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7649 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7650 } 7651 } 7652 ierr = PetscFree(indices);CHKERRQ(ierr); 7653 PetscFunctionReturn(0); 7654 } 7655 7656 #undef __FUNCT__ 7657 #define __FUNCT__ "DMPlexCreateSection" 7658 /*@C 7659 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7660 7661 Not Collective 7662 7663 Input Parameters: 7664 + dm - The DMPlex object 7665 . dim - The spatial dimension of the problem 7666 . numFields - The number of fields in the problem 7667 . numComp - An array of size numFields that holds the number of components for each field 7668 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7669 . numBC - The number of boundary conditions 7670 . bcField - An array of size numBC giving the field number for each boundry condition 7671 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7672 7673 Output Parameter: 7674 . section - The PetscSection object 7675 7676 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 7677 nubmer of dof for field 0 on each edge. 7678 7679 Level: developer 7680 7681 .keywords: mesh, elements 7682 .seealso: DMPlexCreate(), PetscSectionCreate() 7683 @*/ 7684 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 7685 { 7686 PetscErrorCode ierr; 7687 7688 PetscFunctionBegin; 7689 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7690 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7691 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7692 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7693 { 7694 PetscBool view = PETSC_FALSE; 7695 7696 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7697 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7698 } 7699 PetscFunctionReturn(0); 7700 } 7701 7702 #undef __FUNCT__ 7703 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7704 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7705 { 7706 PetscSection section; 7707 PetscErrorCode ierr; 7708 7709 PetscFunctionBegin; 7710 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7711 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7712 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7713 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7714 PetscFunctionReturn(0); 7715 } 7716 7717 #undef __FUNCT__ 7718 #define __FUNCT__ "DMPlexGetCoordinateSection" 7719 /*@ 7720 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7721 7722 Not Collective 7723 7724 Input Parameter: 7725 . dm - The DMPlex object 7726 7727 Output Parameter: 7728 . section - The PetscSection object 7729 7730 Level: intermediate 7731 7732 .keywords: mesh, coordinates 7733 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7734 @*/ 7735 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7736 { 7737 DM cdm; 7738 PetscErrorCode ierr; 7739 7740 PetscFunctionBegin; 7741 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7742 PetscValidPointer(section, 2); 7743 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7744 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7745 PetscFunctionReturn(0); 7746 } 7747 7748 #undef __FUNCT__ 7749 #define __FUNCT__ "DMPlexSetCoordinateSection" 7750 /*@ 7751 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7752 7753 Not Collective 7754 7755 Input Parameters: 7756 + dm - The DMPlex object 7757 - section - The PetscSection object 7758 7759 Level: intermediate 7760 7761 .keywords: mesh, coordinates 7762 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7763 @*/ 7764 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7765 { 7766 DM cdm; 7767 PetscErrorCode ierr; 7768 7769 PetscFunctionBegin; 7770 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7771 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 7772 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7773 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7774 PetscFunctionReturn(0); 7775 } 7776 7777 #undef __FUNCT__ 7778 #define __FUNCT__ "DMPlexGetConeSection" 7779 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7780 { 7781 DM_Plex *mesh = (DM_Plex*) dm->data; 7782 7783 PetscFunctionBegin; 7784 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7785 if (section) *section = mesh->coneSection; 7786 PetscFunctionReturn(0); 7787 } 7788 7789 #undef __FUNCT__ 7790 #define __FUNCT__ "DMPlexGetCones" 7791 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 7792 { 7793 DM_Plex *mesh = (DM_Plex*) dm->data; 7794 7795 PetscFunctionBegin; 7796 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7797 if (cones) *cones = mesh->cones; 7798 PetscFunctionReturn(0); 7799 } 7800 7801 #undef __FUNCT__ 7802 #define __FUNCT__ "DMPlexGetConeOrientations" 7803 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 7804 { 7805 DM_Plex *mesh = (DM_Plex*) dm->data; 7806 7807 PetscFunctionBegin; 7808 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7809 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7810 PetscFunctionReturn(0); 7811 } 7812 7813 #undef __FUNCT__ 7814 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7815 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7816 { 7817 const PetscInt embedDim = 2; 7818 PetscReal x = PetscRealPart(point[0]); 7819 PetscReal y = PetscRealPart(point[1]); 7820 PetscReal v0[2], J[4], invJ[4], detJ; 7821 PetscReal xi, eta; 7822 PetscErrorCode ierr; 7823 7824 PetscFunctionBegin; 7825 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7826 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7827 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7828 7829 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 7830 else *cell = -1; 7831 PetscFunctionReturn(0); 7832 } 7833 7834 #undef __FUNCT__ 7835 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7836 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7837 { 7838 PetscSection coordSection; 7839 Vec coordsLocal; 7840 const PetscScalar *coords; 7841 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7842 PetscReal x = PetscRealPart(point[0]); 7843 PetscReal y = PetscRealPart(point[1]); 7844 PetscInt crossings = 0, f; 7845 PetscErrorCode ierr; 7846 7847 PetscFunctionBegin; 7848 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7849 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7850 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7851 for (f = 0; f < 4; ++f) { 7852 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7853 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7854 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7855 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7856 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7857 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7858 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7859 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7860 if ((cond1 || cond2) && above) ++crossings; 7861 } 7862 if (crossings % 2) *cell = c; 7863 else *cell = -1; 7864 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7865 PetscFunctionReturn(0); 7866 } 7867 7868 #undef __FUNCT__ 7869 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7870 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7871 { 7872 const PetscInt embedDim = 3; 7873 PetscReal v0[3], J[9], invJ[9], detJ; 7874 PetscReal x = PetscRealPart(point[0]); 7875 PetscReal y = PetscRealPart(point[1]); 7876 PetscReal z = PetscRealPart(point[2]); 7877 PetscReal xi, eta, zeta; 7878 PetscErrorCode ierr; 7879 7880 PetscFunctionBegin; 7881 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7882 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7883 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7884 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7885 7886 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 7887 else *cell = -1; 7888 PetscFunctionReturn(0); 7889 } 7890 7891 #undef __FUNCT__ 7892 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7893 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7894 { 7895 PetscSection coordSection; 7896 Vec coordsLocal; 7897 const PetscScalar *coords; 7898 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7899 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7900 PetscBool found = PETSC_TRUE; 7901 PetscInt f; 7902 PetscErrorCode ierr; 7903 7904 PetscFunctionBegin; 7905 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7906 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7907 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7908 for (f = 0; f < 6; ++f) { 7909 /* Check the point is under plane */ 7910 /* Get face normal */ 7911 PetscReal v_i[3]; 7912 PetscReal v_j[3]; 7913 PetscReal normal[3]; 7914 PetscReal pp[3]; 7915 PetscReal dot; 7916 7917 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 7918 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 7919 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 7920 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 7921 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 7922 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 7923 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 7924 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 7925 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 7926 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 7927 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 7928 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 7929 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7930 7931 /* Check that projected point is in face (2D location problem) */ 7932 if (dot < 0.0) { 7933 found = PETSC_FALSE; 7934 break; 7935 } 7936 } 7937 if (found) *cell = c; 7938 else *cell = -1; 7939 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7940 PetscFunctionReturn(0); 7941 } 7942 7943 #undef __FUNCT__ 7944 #define __FUNCT__ "DMLocatePoints_Plex" 7945 /* 7946 Need to implement using the guess 7947 */ 7948 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7949 { 7950 PetscInt cell = -1 /*, guess = -1*/; 7951 PetscInt bs, numPoints, p; 7952 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7953 PetscInt *cells; 7954 PetscScalar *a; 7955 PetscErrorCode ierr; 7956 7957 PetscFunctionBegin; 7958 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7959 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7960 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7961 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7962 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7963 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7964 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7965 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); 7966 numPoints /= bs; 7967 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7968 for (p = 0; p < numPoints; ++p) { 7969 const PetscScalar *point = &a[p*bs]; 7970 7971 switch (dim) { 7972 case 2: 7973 for (c = cStart; c < cEnd; ++c) { 7974 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7975 switch (coneSize) { 7976 case 3: 7977 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7978 break; 7979 case 4: 7980 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7981 break; 7982 default: 7983 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7984 } 7985 if (cell >= 0) break; 7986 } 7987 break; 7988 case 3: 7989 for (c = cStart; c < cEnd; ++c) { 7990 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7991 switch (coneSize) { 7992 case 4: 7993 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7994 break; 7995 case 8: 7996 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7997 break; 7998 default: 7999 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8000 } 8001 if (cell >= 0) break; 8002 } 8003 break; 8004 default: 8005 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8006 } 8007 cells[p] = cell; 8008 } 8009 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8010 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8011 PetscFunctionReturn(0); 8012 } 8013 8014 /******************************** FEM Support **********************************/ 8015 8016 #undef __FUNCT__ 8017 #define __FUNCT__ "DMPlexVecGetClosure" 8018 /*@C 8019 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8020 8021 Not collective 8022 8023 Input Parameters: 8024 + dm - The DM 8025 . section - The section describing the layout in v, or NULL to use the default section 8026 . v - The local vector 8027 - point - The sieve point in the DM 8028 8029 Output Parameters: 8030 + csize - The number of values in the closure, or NULL 8031 - values - The array of values, which is a borrowed array and should not be freed 8032 8033 Level: intermediate 8034 8035 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8036 @*/ 8037 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8038 { 8039 PetscScalar *array, *vArray; 8040 PetscInt *points = NULL; 8041 PetscInt offsets[32]; 8042 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8043 PetscErrorCode ierr; 8044 8045 PetscFunctionBegin; 8046 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8047 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8048 if (!section) { 8049 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8050 } 8051 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8052 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8053 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8054 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8055 /* Compress out points not in the section */ 8056 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8057 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8058 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8059 points[q*2] = points[p]; 8060 points[q*2+1] = points[p+1]; 8061 ++q; 8062 } 8063 } 8064 numPoints = q; 8065 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8066 PetscInt dof, fdof; 8067 8068 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8069 for (f = 0; f < numFields; ++f) { 8070 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8071 offsets[f+1] += fdof; 8072 } 8073 size += dof; 8074 } 8075 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8076 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8077 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8078 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8079 for (p = 0; p < numPoints*2; p += 2) { 8080 PetscInt o = points[p+1]; 8081 PetscInt dof, off, d; 8082 PetscScalar *varr; 8083 8084 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8085 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8086 varr = &vArray[off]; 8087 if (numFields) { 8088 PetscInt fdof, foff, fcomp, f, c; 8089 8090 for (f = 0, foff = 0; f < numFields; ++f) { 8091 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8092 if (o >= 0) { 8093 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8094 array[offsets[f]] = varr[foff+d]; 8095 } 8096 } else { 8097 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8098 for (d = fdof/fcomp-1; d >= 0; --d) { 8099 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8100 array[offsets[f]] = varr[foff+d*fcomp+c]; 8101 } 8102 } 8103 } 8104 foff += fdof; 8105 } 8106 } else { 8107 if (o >= 0) { 8108 for (d = 0; d < dof; ++d, ++offsets[0]) { 8109 array[offsets[0]] = varr[d]; 8110 } 8111 } else { 8112 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8113 array[offsets[0]] = varr[d]; 8114 } 8115 } 8116 } 8117 } 8118 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8119 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8120 if (csize) *csize = size; 8121 *values = array; 8122 PetscFunctionReturn(0); 8123 } 8124 8125 #undef __FUNCT__ 8126 #define __FUNCT__ "DMPlexVecRestoreClosure" 8127 /*@C 8128 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8129 8130 Not collective 8131 8132 Input Parameters: 8133 + dm - The DM 8134 . section - The section describing the layout in v, or NULL to use the default section 8135 . v - The local vector 8136 . point - The sieve point in the DM 8137 . csize - The number of values in the closure, or NULL 8138 - values - The array of values, which is a borrowed array and should not be freed 8139 8140 Level: intermediate 8141 8142 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8143 @*/ 8144 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8145 { 8146 PetscInt size = 0; 8147 PetscErrorCode ierr; 8148 8149 PetscFunctionBegin; 8150 /* Should work without recalculating size */ 8151 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8152 PetscFunctionReturn(0); 8153 } 8154 8155 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8156 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8157 8158 #undef __FUNCT__ 8159 #define __FUNCT__ "updatePoint_private" 8160 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8161 { 8162 PetscInt cdof; /* The number of constraints on this point */ 8163 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8164 PetscScalar *a; 8165 PetscInt off, cind = 0, k; 8166 PetscErrorCode ierr; 8167 8168 PetscFunctionBegin; 8169 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8170 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8171 a = &array[off]; 8172 if (!cdof || setBC) { 8173 if (orientation >= 0) { 8174 for (k = 0; k < dof; ++k) { 8175 fuse(&a[k], values[k]); 8176 } 8177 } else { 8178 for (k = 0; k < dof; ++k) { 8179 fuse(&a[k], values[dof-k-1]); 8180 } 8181 } 8182 } else { 8183 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8184 if (orientation >= 0) { 8185 for (k = 0; k < dof; ++k) { 8186 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8187 fuse(&a[k], values[k]); 8188 } 8189 } else { 8190 for (k = 0; k < dof; ++k) { 8191 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8192 fuse(&a[k], values[dof-k-1]); 8193 } 8194 } 8195 } 8196 PetscFunctionReturn(0); 8197 } 8198 8199 #undef __FUNCT__ 8200 #define __FUNCT__ "updatePointFields_private" 8201 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8202 { 8203 PetscScalar *a; 8204 PetscInt numFields, off, foff, f; 8205 PetscErrorCode ierr; 8206 8207 PetscFunctionBegin; 8208 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8209 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8210 a = &array[off]; 8211 for (f = 0, foff = 0; f < numFields; ++f) { 8212 PetscInt fdof, fcomp, fcdof; 8213 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8214 PetscInt cind = 0, k, c; 8215 8216 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8217 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8218 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8219 if (!fcdof || setBC) { 8220 if (orientation >= 0) { 8221 for (k = 0; k < fdof; ++k) { 8222 fuse(&a[foff+k], values[foffs[f]+k]); 8223 } 8224 } else { 8225 for (k = fdof/fcomp-1; k >= 0; --k) { 8226 for (c = 0; c < fcomp; ++c) { 8227 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8228 } 8229 } 8230 } 8231 } else { 8232 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8233 if (orientation >= 0) { 8234 for (k = 0; k < fdof; ++k) { 8235 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8236 fuse(&a[foff+k], values[foffs[f]+k]); 8237 } 8238 } else { 8239 for (k = fdof/fcomp-1; k >= 0; --k) { 8240 for (c = 0; c < fcomp; ++c) { 8241 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8242 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8243 } 8244 } 8245 } 8246 } 8247 foff += fdof; 8248 foffs[f] += fdof; 8249 } 8250 PetscFunctionReturn(0); 8251 } 8252 8253 #undef __FUNCT__ 8254 #define __FUNCT__ "DMPlexVecSetClosure" 8255 /*@C 8256 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8257 8258 Not collective 8259 8260 Input Parameters: 8261 + dm - The DM 8262 . section - The section describing the layout in v, or NULL to use the default sectionw 8263 . v - The local vector 8264 . point - The sieve point in the DM 8265 . values - The array of values, which is a borrowed array and should not be freed 8266 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8267 8268 Level: intermediate 8269 8270 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8271 @*/ 8272 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8273 { 8274 PetscScalar *array; 8275 PetscInt *points = NULL; 8276 PetscInt offsets[32]; 8277 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8278 PetscErrorCode ierr; 8279 8280 PetscFunctionBegin; 8281 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8282 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8283 if (!section) { 8284 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8285 } 8286 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8287 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8288 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8289 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8290 /* Compress out points not in the section */ 8291 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8292 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8293 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8294 points[q*2] = points[p]; 8295 points[q*2+1] = points[p+1]; 8296 ++q; 8297 } 8298 } 8299 numPoints = q; 8300 for (p = 0; p < numPoints*2; p += 2) { 8301 PetscInt fdof; 8302 8303 for (f = 0; f < numFields; ++f) { 8304 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8305 offsets[f+1] += fdof; 8306 } 8307 } 8308 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8309 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8310 if (numFields) { 8311 switch (mode) { 8312 case INSERT_VALUES: 8313 for (p = 0; p < numPoints*2; p += 2) { 8314 PetscInt o = points[p+1]; 8315 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8316 } break; 8317 case INSERT_ALL_VALUES: 8318 for (p = 0; p < numPoints*2; p += 2) { 8319 PetscInt o = points[p+1]; 8320 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8321 } break; 8322 case ADD_VALUES: 8323 for (p = 0; p < numPoints*2; p += 2) { 8324 PetscInt o = points[p+1]; 8325 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8326 } break; 8327 case ADD_ALL_VALUES: 8328 for (p = 0; p < numPoints*2; p += 2) { 8329 PetscInt o = points[p+1]; 8330 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8331 } break; 8332 default: 8333 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8334 } 8335 } else { 8336 switch (mode) { 8337 case INSERT_VALUES: 8338 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8339 PetscInt o = points[p+1]; 8340 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8341 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8342 } break; 8343 case INSERT_ALL_VALUES: 8344 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8345 PetscInt o = points[p+1]; 8346 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8347 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8348 } break; 8349 case ADD_VALUES: 8350 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8351 PetscInt o = points[p+1]; 8352 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8353 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8354 } break; 8355 case ADD_ALL_VALUES: 8356 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8357 PetscInt o = points[p+1]; 8358 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8359 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8360 } break; 8361 default: 8362 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8363 } 8364 } 8365 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8366 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8367 PetscFunctionReturn(0); 8368 } 8369 8370 #undef __FUNCT__ 8371 #define __FUNCT__ "DMPlexPrintMatSetValues" 8372 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8373 { 8374 PetscMPIInt rank; 8375 PetscInt i, j; 8376 PetscErrorCode ierr; 8377 8378 PetscFunctionBegin; 8379 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8380 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8381 for (i = 0; i < numIndices; i++) { 8382 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8383 } 8384 for (i = 0; i < numIndices; i++) { 8385 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8386 for (j = 0; j < numIndices; j++) { 8387 #if defined(PETSC_USE_COMPLEX) 8388 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8389 #else 8390 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8391 #endif 8392 } 8393 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8394 } 8395 PetscFunctionReturn(0); 8396 } 8397 8398 #undef __FUNCT__ 8399 #define __FUNCT__ "indicesPoint_private" 8400 /* . off - The global offset of this point */ 8401 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8402 { 8403 PetscInt dof; /* The number of unknowns on this point */ 8404 PetscInt cdof; /* The number of constraints on this point */ 8405 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8406 PetscInt cind = 0, k; 8407 PetscErrorCode ierr; 8408 8409 PetscFunctionBegin; 8410 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8411 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8412 if (!cdof || setBC) { 8413 if (orientation >= 0) { 8414 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8415 } else { 8416 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8417 } 8418 } else { 8419 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8420 if (orientation >= 0) { 8421 for (k = 0; k < dof; ++k) { 8422 if ((cind < cdof) && (k == cdofs[cind])) { 8423 /* Insert check for returning constrained indices */ 8424 indices[*loff+k] = -(off+k+1); 8425 ++cind; 8426 } else { 8427 indices[*loff+k] = off+k-cind; 8428 } 8429 } 8430 } else { 8431 for (k = 0; k < dof; ++k) { 8432 if ((cind < cdof) && (k == cdofs[cind])) { 8433 /* Insert check for returning constrained indices */ 8434 indices[*loff+dof-k-1] = -(off+k+1); 8435 ++cind; 8436 } else { 8437 indices[*loff+dof-k-1] = off+k-cind; 8438 } 8439 } 8440 } 8441 } 8442 *loff += dof; 8443 PetscFunctionReturn(0); 8444 } 8445 8446 #undef __FUNCT__ 8447 #define __FUNCT__ "indicesPointFields_private" 8448 /* . off - The global offset of this point */ 8449 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8450 { 8451 PetscInt numFields, foff, f; 8452 PetscErrorCode ierr; 8453 8454 PetscFunctionBegin; 8455 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8456 for (f = 0, foff = 0; f < numFields; ++f) { 8457 PetscInt fdof, fcomp, cfdof; 8458 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8459 PetscInt cind = 0, k, c; 8460 8461 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8462 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8463 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8464 if (!cfdof || setBC) { 8465 if (orientation >= 0) { 8466 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8467 } else { 8468 for (k = fdof/fcomp-1; k >= 0; --k) { 8469 for (c = 0; c < fcomp; ++c) { 8470 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8471 } 8472 } 8473 } 8474 } else { 8475 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8476 if (orientation >= 0) { 8477 for (k = 0; k < fdof; ++k) { 8478 if ((cind < cfdof) && (k == fcdofs[cind])) { 8479 indices[foffs[f]+k] = -(off+foff+k+1); 8480 ++cind; 8481 } else { 8482 indices[foffs[f]+k] = off+foff+k-cind; 8483 } 8484 } 8485 } else { 8486 for (k = fdof/fcomp-1; k >= 0; --k) { 8487 for (c = 0; c < fcomp; ++c) { 8488 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8489 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8490 ++cind; 8491 } else { 8492 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8493 } 8494 } 8495 } 8496 } 8497 } 8498 foff += fdof - cfdof; 8499 foffs[f] += fdof; 8500 } 8501 PetscFunctionReturn(0); 8502 } 8503 8504 #undef __FUNCT__ 8505 #define __FUNCT__ "DMPlexMatSetClosure" 8506 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8507 { 8508 DM_Plex *mesh = (DM_Plex*) dm->data; 8509 PetscInt *points = NULL; 8510 PetscInt *indices; 8511 PetscInt offsets[32]; 8512 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8513 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8514 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8515 PetscErrorCode ierr; 8516 8517 PetscFunctionBegin; 8518 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8519 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8520 if (useDefault) { 8521 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8522 } 8523 if (useGlobalDefault) { 8524 if (useDefault) { 8525 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8526 } else { 8527 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8528 } 8529 } 8530 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8531 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8532 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8533 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8534 /* Compress out points not in the section */ 8535 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8536 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8537 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8538 points[q*2] = points[p]; 8539 points[q*2+1] = points[p+1]; 8540 ++q; 8541 } 8542 } 8543 numPoints = q; 8544 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8545 PetscInt fdof; 8546 8547 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8548 for (f = 0; f < numFields; ++f) { 8549 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8550 offsets[f+1] += fdof; 8551 } 8552 numIndices += dof; 8553 } 8554 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8555 8556 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8557 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8558 if (numFields) { 8559 for (p = 0; p < numPoints*2; p += 2) { 8560 PetscInt o = points[p+1]; 8561 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8562 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8563 } 8564 } else { 8565 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8566 PetscInt o = points[p+1]; 8567 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8568 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8569 } 8570 } 8571 if (useGlobalDefault && !useDefault) { 8572 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8573 } 8574 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8575 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8576 if (ierr) { 8577 PetscMPIInt rank; 8578 PetscErrorCode ierr2; 8579 8580 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8581 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8582 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8583 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8584 CHKERRQ(ierr); 8585 } 8586 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8587 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8588 PetscFunctionReturn(0); 8589 } 8590 8591 #undef __FUNCT__ 8592 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8593 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8594 { 8595 PetscSection coordSection; 8596 Vec coordinates; 8597 const PetscScalar *coords; 8598 const PetscInt dim = 2; 8599 PetscInt d, f; 8600 PetscErrorCode ierr; 8601 8602 PetscFunctionBegin; 8603 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8604 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8605 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8606 if (v0) { 8607 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8608 } 8609 if (J) { 8610 for (d = 0; d < dim; d++) { 8611 for (f = 0; f < dim; f++) { 8612 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8613 } 8614 } 8615 *detJ = J[0]*J[3] - J[1]*J[2]; 8616 #if 0 8617 if (detJ < 0.0) { 8618 const PetscReal xLength = mesh->periodicity[0]; 8619 8620 if (xLength != 0.0) { 8621 PetscReal v0x = coords[0*dim+0]; 8622 8623 if (v0x == 0.0) v0x = v0[0] = xLength; 8624 for (f = 0; f < dim; f++) { 8625 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8626 8627 J[0*dim+f] = 0.5*(px - v0x); 8628 } 8629 } 8630 detJ = J[0]*J[3] - J[1]*J[2]; 8631 } 8632 #endif 8633 PetscLogFlops(8.0 + 3.0); 8634 } 8635 if (invJ) { 8636 const PetscReal invDet = 1.0/(*detJ); 8637 8638 invJ[0] = invDet*J[3]; 8639 invJ[1] = -invDet*J[1]; 8640 invJ[2] = -invDet*J[2]; 8641 invJ[3] = invDet*J[0]; 8642 PetscLogFlops(5.0); 8643 } 8644 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8645 PetscFunctionReturn(0); 8646 } 8647 8648 #undef __FUNCT__ 8649 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8650 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8651 { 8652 PetscSection coordSection; 8653 Vec coordinates; 8654 const PetscScalar *coords; 8655 const PetscInt dim = 2; 8656 PetscInt d, f; 8657 PetscErrorCode ierr; 8658 8659 PetscFunctionBegin; 8660 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8661 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8662 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8663 if (v0) { 8664 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8665 } 8666 if (J) { 8667 for (d = 0; d < dim; d++) { 8668 for (f = 0; f < dim; f++) { 8669 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8670 } 8671 } 8672 *detJ = J[0]*J[3] - J[1]*J[2]; 8673 PetscLogFlops(8.0 + 3.0); 8674 } 8675 if (invJ) { 8676 const PetscReal invDet = 1.0/(*detJ); 8677 8678 invJ[0] = invDet*J[3]; 8679 invJ[1] = -invDet*J[1]; 8680 invJ[2] = -invDet*J[2]; 8681 invJ[3] = invDet*J[0]; 8682 PetscLogFlops(5.0); 8683 } 8684 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8685 PetscFunctionReturn(0); 8686 } 8687 8688 #undef __FUNCT__ 8689 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8690 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8691 { 8692 PetscSection coordSection; 8693 Vec coordinates; 8694 const PetscScalar *coords; 8695 const PetscInt dim = 3; 8696 PetscInt d, f; 8697 PetscErrorCode ierr; 8698 8699 PetscFunctionBegin; 8700 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8701 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8702 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8703 if (v0) { 8704 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8705 } 8706 if (J) { 8707 for (d = 0; d < dim; d++) { 8708 for (f = 0; f < dim; f++) { 8709 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8710 } 8711 } 8712 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8713 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8714 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8715 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8716 PetscLogFlops(18.0 + 12.0); 8717 } 8718 if (invJ) { 8719 const PetscReal invDet = 1.0/(*detJ); 8720 8721 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8722 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8723 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8724 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8725 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8726 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8727 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8728 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8729 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8730 PetscLogFlops(37.0); 8731 } 8732 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8733 PetscFunctionReturn(0); 8734 } 8735 8736 #undef __FUNCT__ 8737 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8738 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8739 { 8740 PetscSection coordSection; 8741 Vec coordinates; 8742 const PetscScalar *coords; 8743 const PetscInt dim = 3; 8744 PetscInt d; 8745 PetscErrorCode ierr; 8746 8747 PetscFunctionBegin; 8748 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8749 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8750 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8751 if (v0) { 8752 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8753 } 8754 if (J) { 8755 for (d = 0; d < dim; d++) { 8756 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8757 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8758 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8759 } 8760 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8761 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8762 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8763 PetscLogFlops(18.0 + 12.0); 8764 } 8765 if (invJ) { 8766 const PetscReal invDet = -1.0/(*detJ); 8767 8768 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8769 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8770 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8771 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8772 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8773 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8774 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8775 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8776 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8777 PetscLogFlops(37.0); 8778 } 8779 *detJ *= 8.0; 8780 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8781 PetscFunctionReturn(0); 8782 } 8783 8784 #undef __FUNCT__ 8785 #define __FUNCT__ "DMPlexComputeCellGeometry" 8786 /*@C 8787 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8788 8789 Collective on DM 8790 8791 Input Arguments: 8792 + dm - the DM 8793 - cell - the cell 8794 8795 Output Arguments: 8796 + v0 - the translation part of this affine transform 8797 . J - the Jacobian of the transform to the reference element 8798 . invJ - the inverse of the Jacobian 8799 - detJ - the Jacobian determinant 8800 8801 Level: advanced 8802 8803 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8804 @*/ 8805 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8806 { 8807 PetscInt dim, coneSize; 8808 PetscErrorCode ierr; 8809 8810 PetscFunctionBegin; 8811 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8812 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8813 switch (dim) { 8814 case 2: 8815 switch (coneSize) { 8816 case 3: 8817 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8818 break; 8819 case 4: 8820 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8821 break; 8822 default: 8823 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8824 } 8825 break; 8826 case 3: 8827 switch (coneSize) { 8828 case 4: 8829 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8830 break; 8831 case 8: 8832 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8833 break; 8834 default: 8835 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8836 } 8837 break; 8838 default: 8839 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8840 } 8841 PetscFunctionReturn(0); 8842 } 8843 8844 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8845 { 8846 switch (i) { 8847 case 0: 8848 switch (j) { 8849 case 0: return 0; 8850 case 1: 8851 switch (k) { 8852 case 0: return 0; 8853 case 1: return 0; 8854 case 2: return 1; 8855 } 8856 case 2: 8857 switch (k) { 8858 case 0: return 0; 8859 case 1: return -1; 8860 case 2: return 0; 8861 } 8862 } 8863 case 1: 8864 switch (j) { 8865 case 0: 8866 switch (k) { 8867 case 0: return 0; 8868 case 1: return 0; 8869 case 2: return -1; 8870 } 8871 case 1: return 0; 8872 case 2: 8873 switch (k) { 8874 case 0: return 1; 8875 case 1: return 0; 8876 case 2: return 0; 8877 } 8878 } 8879 case 2: 8880 switch (j) { 8881 case 0: 8882 switch (k) { 8883 case 0: return 0; 8884 case 1: return 1; 8885 case 2: return 0; 8886 } 8887 case 1: 8888 switch (k) { 8889 case 0: return -1; 8890 case 1: return 0; 8891 case 2: return 0; 8892 } 8893 case 2: return 0; 8894 } 8895 } 8896 return 0; 8897 } 8898 8899 #undef __FUNCT__ 8900 #define __FUNCT__ "DMPlexCreateRigidBody" 8901 /*@C 8902 DMPlexCreateRigidBody - create rigid body modes from coordinates 8903 8904 Collective on DM 8905 8906 Input Arguments: 8907 + dm - the DM 8908 . section - the local section associated with the rigid field, or NULL for the default section 8909 - globalSection - the global section associated with the rigid field, or NULL for the default section 8910 8911 Output Argument: 8912 . sp - the null space 8913 8914 Note: This is necessary to take account of Dirichlet conditions on the displacements 8915 8916 Level: advanced 8917 8918 .seealso: MatNullSpaceCreate() 8919 @*/ 8920 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8921 { 8922 MPI_Comm comm; 8923 Vec coordinates, localMode, mode[6]; 8924 PetscSection coordSection; 8925 PetscScalar *coords; 8926 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8927 PetscErrorCode ierr; 8928 8929 PetscFunctionBegin; 8930 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 8931 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8932 if (dim == 1) { 8933 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 8934 PetscFunctionReturn(0); 8935 } 8936 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8937 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8938 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8939 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8940 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8941 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8942 m = (dim*(dim+1))/2; 8943 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8944 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8945 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8946 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8947 /* Assume P1 */ 8948 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8949 for (d = 0; d < dim; ++d) { 8950 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8951 8952 values[d] = 1.0; 8953 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8954 for (v = vStart; v < vEnd; ++v) { 8955 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8956 } 8957 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8958 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8959 } 8960 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8961 for (d = dim; d < dim*(dim+1)/2; ++d) { 8962 PetscInt i, j, k = dim > 2 ? d - dim : d; 8963 8964 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8965 for (v = vStart; v < vEnd; ++v) { 8966 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8967 PetscInt off; 8968 8969 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8970 for (i = 0; i < dim; ++i) { 8971 for (j = 0; j < dim; ++j) { 8972 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8973 } 8974 } 8975 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8976 } 8977 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8978 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8979 } 8980 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8981 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8982 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 8983 /* Orthonormalize system */ 8984 for (i = dim; i < m; ++i) { 8985 PetscScalar dots[6]; 8986 8987 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8988 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8989 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8990 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 8991 } 8992 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8993 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8994 PetscFunctionReturn(0); 8995 } 8996 8997 #undef __FUNCT__ 8998 #define __FUNCT__ "DMPlexGetHybridBounds" 8999 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9000 { 9001 DM_Plex *mesh = (DM_Plex*) dm->data; 9002 PetscInt dim; 9003 PetscErrorCode ierr; 9004 9005 PetscFunctionBegin; 9006 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9007 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9008 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9009 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9010 if (eMax) *eMax = mesh->hybridPointMax[1]; 9011 if (vMax) *vMax = mesh->hybridPointMax[0]; 9012 PetscFunctionReturn(0); 9013 } 9014 9015 #undef __FUNCT__ 9016 #define __FUNCT__ "DMPlexSetHybridBounds" 9017 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9018 { 9019 DM_Plex *mesh = (DM_Plex*) dm->data; 9020 PetscInt dim; 9021 PetscErrorCode ierr; 9022 9023 PetscFunctionBegin; 9024 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9025 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9026 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9027 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9028 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9029 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9030 PetscFunctionReturn(0); 9031 } 9032 9033 #undef __FUNCT__ 9034 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9035 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9036 { 9037 DM_Plex *mesh = (DM_Plex*) dm->data; 9038 9039 PetscFunctionBegin; 9040 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9041 PetscValidPointer(cellHeight, 2); 9042 *cellHeight = mesh->vtkCellHeight; 9043 PetscFunctionReturn(0); 9044 } 9045 9046 #undef __FUNCT__ 9047 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9048 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9049 { 9050 DM_Plex *mesh = (DM_Plex*) dm->data; 9051 9052 PetscFunctionBegin; 9053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9054 mesh->vtkCellHeight = cellHeight; 9055 PetscFunctionReturn(0); 9056 } 9057 9058 #undef __FUNCT__ 9059 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9060 /* We can easily have a form that takes an IS instead */ 9061 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9062 { 9063 PetscSection section, globalSection; 9064 PetscInt *numbers, p; 9065 PetscErrorCode ierr; 9066 9067 PetscFunctionBegin; 9068 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 9069 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9070 for (p = pStart; p < pEnd; ++p) { 9071 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9072 } 9073 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9074 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9075 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9076 for (p = pStart; p < pEnd; ++p) { 9077 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9078 } 9079 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9080 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9081 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9082 PetscFunctionReturn(0); 9083 } 9084 9085 #undef __FUNCT__ 9086 #define __FUNCT__ "DMPlexGetCellNumbering" 9087 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9088 { 9089 DM_Plex *mesh = (DM_Plex*) dm->data; 9090 PetscInt cellHeight, cStart, cEnd, cMax; 9091 PetscErrorCode ierr; 9092 9093 PetscFunctionBegin; 9094 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9095 if (!mesh->globalCellNumbers) { 9096 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9097 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9098 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 9099 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9100 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9101 } 9102 *globalCellNumbers = mesh->globalCellNumbers; 9103 PetscFunctionReturn(0); 9104 } 9105 9106 #undef __FUNCT__ 9107 #define __FUNCT__ "DMPlexGetVertexNumbering" 9108 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9109 { 9110 DM_Plex *mesh = (DM_Plex*) dm->data; 9111 PetscInt vStart, vEnd, vMax; 9112 PetscErrorCode ierr; 9113 9114 PetscFunctionBegin; 9115 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9116 if (!mesh->globalVertexNumbers) { 9117 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9118 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9119 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9120 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9121 } 9122 *globalVertexNumbers = mesh->globalVertexNumbers; 9123 PetscFunctionReturn(0); 9124 } 9125 9126 #undef __FUNCT__ 9127 #define __FUNCT__ "DMPlexGetScale" 9128 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9129 { 9130 DM_Plex *mesh = (DM_Plex*) dm->data; 9131 9132 PetscFunctionBegin; 9133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9134 PetscValidPointer(scale, 3); 9135 *scale = mesh->scale[unit]; 9136 PetscFunctionReturn(0); 9137 } 9138 9139 #undef __FUNCT__ 9140 #define __FUNCT__ "DMPlexSetScale" 9141 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9142 { 9143 DM_Plex *mesh = (DM_Plex*) dm->data; 9144 9145 PetscFunctionBegin; 9146 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9147 mesh->scale[unit] = scale; 9148 PetscFunctionReturn(0); 9149 } 9150 9151 9152 /******************************************************************************* 9153 This should be in a separate Discretization object, but I am not sure how to lay 9154 it out yet, so I am stuffing things here while I experiment. 9155 *******************************************************************************/ 9156 #undef __FUNCT__ 9157 #define __FUNCT__ "DMPlexSetFEMIntegration" 9158 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9159 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9160 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9161 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9162 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9163 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9164 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9165 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9166 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9167 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9168 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9169 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9170 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9171 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9172 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9173 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9174 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9175 { 9176 DM_Plex *mesh = (DM_Plex*) dm->data; 9177 9178 PetscFunctionBegin; 9179 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9180 mesh->integrateResidualFEM = integrateResidualFEM; 9181 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9182 mesh->integrateJacobianFEM = integrateJacobianFEM; 9183 PetscFunctionReturn(0); 9184 } 9185 9186 #undef __FUNCT__ 9187 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9188 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9189 { 9190 Vec coordinates; 9191 PetscSection section, cSection; 9192 PetscInt dim, vStart, vEnd, v, c, d; 9193 PetscScalar *values, *cArray; 9194 PetscReal *coords; 9195 PetscErrorCode ierr; 9196 9197 PetscFunctionBegin; 9198 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9199 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9200 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9201 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9202 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9203 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9204 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9205 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9206 for (v = vStart; v < vEnd; ++v) { 9207 PetscInt dof, off; 9208 9209 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9210 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9211 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9212 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9213 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9214 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9215 } 9216 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9217 /* Temporary, must be replaced by a projection on the finite element basis */ 9218 { 9219 PetscInt eStart = 0, eEnd = 0, e, depth; 9220 9221 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9222 --depth; 9223 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9224 for (e = eStart; e < eEnd; ++e) { 9225 const PetscInt *cone = NULL; 9226 PetscInt coneSize, d; 9227 PetscScalar *coordsA, *coordsB; 9228 9229 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9230 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9231 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9232 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9233 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9234 for (d = 0; d < dim; ++d) { 9235 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9236 } 9237 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9238 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9239 } 9240 } 9241 9242 ierr = PetscFree(coords);CHKERRQ(ierr); 9243 ierr = PetscFree(values);CHKERRQ(ierr); 9244 #if 0 9245 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9246 PetscReal detJ; 9247 9248 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9249 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9250 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9251 9252 for (PetscInt c = cStart; c < cEnd; ++c) { 9253 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9254 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9255 const int oSize = pV.getSize(); 9256 int v = 0; 9257 9258 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9259 for (PetscInt cl = 0; cl < oSize; ++cl) { 9260 const PetscInt fDim; 9261 9262 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9263 if (pointDim) { 9264 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9265 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9266 } 9267 } 9268 } 9269 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9270 pV.clear(); 9271 } 9272 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9273 ierr = PetscFree(values);CHKERRQ(ierr); 9274 #endif 9275 PetscFunctionReturn(0); 9276 } 9277 9278 #undef __FUNCT__ 9279 #define __FUNCT__ "DMPlexProjectFunction" 9280 /*@C 9281 DMPlexProjectFunction - This projects the given function into the function space provided. 9282 9283 Input Parameters: 9284 + dm - The DM 9285 . numComp - The number of components (functions) 9286 . funcs - The coordinate functions to evaluate 9287 - mode - The insertion mode for values 9288 9289 Output Parameter: 9290 . X - vector 9291 9292 Level: developer 9293 9294 Note: 9295 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9296 We will eventually fix it. 9297 9298 ,seealso: DMPlexComputeL2Diff() 9299 */ 9300 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9301 { 9302 Vec localX; 9303 PetscErrorCode ierr; 9304 9305 PetscFunctionBegin; 9306 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9307 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9308 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9309 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9310 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9311 PetscFunctionReturn(0); 9312 } 9313 9314 #undef __FUNCT__ 9315 #define __FUNCT__ "DMPlexComputeL2Diff" 9316 /*@C 9317 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9318 9319 Input Parameters: 9320 + dm - The DM 9321 . quad - The PetscQuadrature object for each field 9322 . funcs - The functions to evaluate for each field component 9323 - X - The coefficient vector u_h 9324 9325 Output Parameter: 9326 . diff - The diff ||u - u_h||_2 9327 9328 Level: developer 9329 9330 .seealso: DMPlexProjectFunction() 9331 */ 9332 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9333 { 9334 const PetscInt debug = 0; 9335 PetscSection section; 9336 Vec localX; 9337 PetscReal *coords, *v0, *J, *invJ, detJ; 9338 PetscReal localDiff = 0.0; 9339 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9340 PetscErrorCode ierr; 9341 9342 PetscFunctionBegin; 9343 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9344 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9345 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9346 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9347 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9348 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9349 for (field = 0; field < numFields; ++field) { 9350 numComponents += quad[field].numComponents; 9351 } 9352 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9353 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9354 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9355 for (c = cStart; c < cEnd; ++c) { 9356 const PetscScalar *x; 9357 PetscReal elemDiff = 0.0; 9358 9359 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9360 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9361 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9362 9363 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9364 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9365 const PetscReal *quadPoints = quad[field].quadPoints; 9366 const PetscReal *quadWeights = quad[field].quadWeights; 9367 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9368 const PetscInt numBasisComps = quad[field].numComponents; 9369 const PetscReal *basis = quad[field].basis; 9370 PetscInt q, d, e, fc, f; 9371 9372 if (debug) { 9373 char title[1024]; 9374 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9375 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9376 } 9377 for (q = 0; q < numQuadPoints; ++q) { 9378 for (d = 0; d < dim; d++) { 9379 coords[d] = v0[d]; 9380 for (e = 0; e < dim; e++) { 9381 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9382 } 9383 } 9384 for (fc = 0; fc < numBasisComps; ++fc) { 9385 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9386 PetscReal interpolant = 0.0; 9387 for (f = 0; f < numBasisFuncs; ++f) { 9388 const PetscInt fidx = f*numBasisComps+fc; 9389 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9390 } 9391 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9392 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9393 } 9394 } 9395 comp += numBasisComps; 9396 fieldOffset += numBasisFuncs*numBasisComps; 9397 } 9398 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9399 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9400 localDiff += elemDiff; 9401 } 9402 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9403 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9404 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9405 *diff = PetscSqrtReal(*diff); 9406 PetscFunctionReturn(0); 9407 } 9408 9409 #undef __FUNCT__ 9410 #define __FUNCT__ "DMPlexComputeResidualFEM" 9411 /*@ 9412 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9413 9414 Input Parameters: 9415 + dm - The mesh 9416 . X - Local input vector 9417 - user - The user context 9418 9419 Output Parameter: 9420 . F - Local output vector 9421 9422 Note: 9423 The second member of the user context must be an FEMContext. 9424 9425 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9426 like a GPU, or vectorize on a multicore machine. 9427 9428 .seealso: DMPlexComputeJacobianActionFEM() 9429 */ 9430 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9431 { 9432 DM_Plex *mesh = (DM_Plex*) dm->data; 9433 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9434 PetscQuadrature *quad = fem->quad; 9435 PetscSection section; 9436 PetscReal *v0, *J, *invJ, *detJ; 9437 PetscScalar *elemVec, *u; 9438 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9439 PetscInt cellDof = 0, numComponents = 0; 9440 PetscErrorCode ierr; 9441 9442 PetscFunctionBegin; 9443 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9444 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9445 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9446 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9447 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9448 numCells = cEnd - cStart; 9449 for (field = 0; field < numFields; ++field) { 9450 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9451 numComponents += quad[field].numComponents; 9452 } 9453 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9454 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9455 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); 9456 for (c = cStart; c < cEnd; ++c) { 9457 const PetscScalar *x; 9458 PetscInt i; 9459 9460 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9461 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9462 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9463 9464 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9465 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9466 } 9467 for (field = 0; field < numFields; ++field) { 9468 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9469 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9470 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9471 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9472 /* Conforming batches */ 9473 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9474 PetscInt numBlocks = 1; 9475 PetscInt batchSize = numBlocks * blockSize; 9476 PetscInt numBatches = numBatchesTmp; 9477 PetscInt numChunks = numCells / (numBatches*batchSize); 9478 /* Remainder */ 9479 PetscInt numRemainder = numCells % (numBatches * batchSize); 9480 PetscInt offset = numCells - numRemainder; 9481 9482 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9483 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9484 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9485 } 9486 for (c = cStart; c < cEnd; ++c) { 9487 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9488 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9489 } 9490 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9491 if (mesh->printFEM) { 9492 PetscMPIInt rank, numProcs; 9493 PetscInt p; 9494 9495 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9496 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9497 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9498 for (p = 0; p < numProcs; ++p) { 9499 if (p == rank) { 9500 Vec f; 9501 9502 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9503 ierr = VecCopy(F, f);CHKERRQ(ierr); 9504 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9505 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9506 ierr = VecDestroy(&f);CHKERRQ(ierr); 9507 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9508 } 9509 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9510 } 9511 } 9512 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9513 PetscFunctionReturn(0); 9514 } 9515 9516 #undef __FUNCT__ 9517 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9518 /*@C 9519 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9520 9521 Input Parameters: 9522 + dm - The mesh 9523 . J - The Jacobian shell matrix 9524 . X - Local input vector 9525 - user - The user context 9526 9527 Output Parameter: 9528 . F - Local output vector 9529 9530 Note: 9531 The second member of the user context must be an FEMContext. 9532 9533 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9534 like a GPU, or vectorize on a multicore machine. 9535 9536 .seealso: DMPlexComputeResidualFEM() 9537 */ 9538 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9539 { 9540 DM_Plex *mesh = (DM_Plex*) dm->data; 9541 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9542 PetscQuadrature *quad = fem->quad; 9543 PetscSection section; 9544 JacActionCtx *jctx; 9545 PetscReal *v0, *J, *invJ, *detJ; 9546 PetscScalar *elemVec, *u, *a; 9547 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9548 PetscInt cellDof = 0; 9549 PetscErrorCode ierr; 9550 9551 PetscFunctionBegin; 9552 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9553 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9554 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9555 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9556 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9557 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9558 numCells = cEnd - cStart; 9559 for (field = 0; field < numFields; ++field) { 9560 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9561 } 9562 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9563 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); 9564 for (c = cStart; c < cEnd; ++c) { 9565 const PetscScalar *x; 9566 PetscInt i; 9567 9568 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9569 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9570 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9571 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9572 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9573 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9574 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9575 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9576 } 9577 for (field = 0; field < numFields; ++field) { 9578 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9579 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9580 /* Conforming batches */ 9581 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9582 PetscInt numBlocks = 1; 9583 PetscInt batchSize = numBlocks * blockSize; 9584 PetscInt numBatches = numBatchesTmp; 9585 PetscInt numChunks = numCells / (numBatches*batchSize); 9586 /* Remainder */ 9587 PetscInt numRemainder = numCells % (numBatches * batchSize); 9588 PetscInt offset = numCells - numRemainder; 9589 9590 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); 9591 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], 9592 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9593 } 9594 for (c = cStart; c < cEnd; ++c) { 9595 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9596 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9597 } 9598 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9599 if (mesh->printFEM) { 9600 PetscMPIInt rank, numProcs; 9601 PetscInt p; 9602 9603 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9604 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9605 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9606 for (p = 0; p < numProcs; ++p) { 9607 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9608 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9609 } 9610 } 9611 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9612 PetscFunctionReturn(0); 9613 } 9614 9615 #undef __FUNCT__ 9616 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9617 /*@ 9618 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9619 9620 Input Parameters: 9621 + dm - The mesh 9622 . X - Local input vector 9623 - user - The user context 9624 9625 Output Parameter: 9626 . Jac - Jacobian matrix 9627 9628 Note: 9629 The second member of the user context must be an FEMContext. 9630 9631 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9632 like a GPU, or vectorize on a multicore machine. 9633 9634 .seealso: FormFunctionLocal() 9635 */ 9636 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9637 { 9638 DM_Plex *mesh = (DM_Plex*) dm->data; 9639 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9640 PetscQuadrature *quad = fem->quad; 9641 PetscSection section; 9642 PetscReal *v0, *J, *invJ, *detJ; 9643 PetscScalar *elemMat, *u; 9644 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9645 PetscInt cellDof = 0, numComponents = 0; 9646 PetscBool isShell; 9647 PetscErrorCode ierr; 9648 9649 PetscFunctionBegin; 9650 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9651 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9652 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9653 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9654 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9655 numCells = cEnd - cStart; 9656 for (field = 0; field < numFields; ++field) { 9657 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9658 numComponents += quad[field].numComponents; 9659 } 9660 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9661 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9662 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); 9663 for (c = cStart; c < cEnd; ++c) { 9664 const PetscScalar *x; 9665 PetscInt i; 9666 9667 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9668 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9669 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9670 9671 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9672 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9673 } 9674 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9675 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9676 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9677 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9678 PetscInt fieldJ; 9679 9680 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9681 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9682 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9683 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9684 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9685 /* Conforming batches */ 9686 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9687 PetscInt numBlocks = 1; 9688 PetscInt batchSize = numBlocks * blockSize; 9689 PetscInt numBatches = numBatchesTmp; 9690 PetscInt numChunks = numCells / (numBatches*batchSize); 9691 /* Remainder */ 9692 PetscInt numRemainder = numCells % (numBatches * batchSize); 9693 PetscInt offset = numCells - numRemainder; 9694 9695 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9696 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9697 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9698 } 9699 } 9700 for (c = cStart; c < cEnd; ++c) { 9701 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9702 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9703 } 9704 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9705 9706 /* Assemble matrix, using the 2-step process: 9707 MatAssemblyBegin(), MatAssemblyEnd(). */ 9708 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9709 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9710 9711 if (mesh->printFEM) { 9712 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9713 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9714 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9715 } 9716 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9717 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9718 if (isShell) { 9719 JacActionCtx *jctx; 9720 9721 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9722 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9723 } 9724 *str = SAME_NONZERO_PATTERN; 9725 PetscFunctionReturn(0); 9726 } 9727 9728 9729 #undef __FUNCT__ 9730 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9731 /*@C 9732 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9733 the local section and an SF describing the section point overlap. 9734 9735 Input Parameters: 9736 + s - The PetscSection for the local field layout 9737 . sf - The SF describing parallel layout of the section points 9738 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9739 . label - The label specifying the points 9740 - labelValue - The label stratum specifying the points 9741 9742 Output Parameter: 9743 . gsection - The PetscSection for the global field layout 9744 9745 Note: This gives negative sizes and offsets to points not owned by this process 9746 9747 Level: developer 9748 9749 .seealso: PetscSectionCreate() 9750 @*/ 9751 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9752 { 9753 PetscInt *neg; 9754 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9755 PetscErrorCode ierr; 9756 9757 PetscFunctionBegin; 9758 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9759 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9760 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9761 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9762 /* Mark ghost points with negative dof */ 9763 for (p = pStart; p < pEnd; ++p) { 9764 PetscInt value; 9765 9766 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9767 if (value != labelValue) continue; 9768 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9769 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9770 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9771 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9772 neg[p-pStart] = -(dof+1); 9773 } 9774 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9775 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 9776 if (nroots >= 0) { 9777 if (nroots > pEnd - pStart) { 9778 PetscInt *tmpDof; 9779 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9780 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9781 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9782 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9783 for (p = pStart; p < pEnd; ++p) { 9784 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 9785 } 9786 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9787 } else { 9788 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9789 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9790 } 9791 } 9792 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9793 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9794 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9795 9796 (*gsection)->atlasOff[p] = off; 9797 9798 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9799 } 9800 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9801 globalOff -= off; 9802 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9803 (*gsection)->atlasOff[p] += globalOff; 9804 9805 neg[p] = -((*gsection)->atlasOff[p]+1); 9806 } 9807 /* Put in negative offsets for ghost points */ 9808 if (nroots >= 0) { 9809 if (nroots > pEnd - pStart) { 9810 PetscInt *tmpOff; 9811 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9812 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9813 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9814 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9815 for (p = pStart; p < pEnd; ++p) { 9816 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 9817 } 9818 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9819 } else { 9820 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9821 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9822 } 9823 } 9824 ierr = PetscFree(neg);CHKERRQ(ierr); 9825 PetscFunctionReturn(0); 9826 } 9827