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__ "DMPlexGetFaces" 1700 /* 1701 DMPlexGetFaces - 1702 1703 Note: This will only work for cell-vertex meshes. 1704 */ 1705 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1706 { 1707 DM_Plex *mesh = (DM_Plex*) dm->data; 1708 const PetscInt *cone = NULL; 1709 PetscInt depth = 0, dim, coneSize; 1710 PetscErrorCode ierr; 1711 1712 PetscFunctionBegin; 1713 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1714 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1715 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1716 if (depth > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1717 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1718 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1719 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1720 switch (dim) { 1721 case 2: 1722 switch (coneSize) { 1723 case 3: 1724 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1725 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1726 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1727 *numFaces = 3; 1728 *faceSize = 2; 1729 *faces = mesh->facesTmp; 1730 break; 1731 case 4: 1732 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1733 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1734 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1735 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1736 *numFaces = 4; 1737 *faceSize = 2; 1738 *faces = mesh->facesTmp; 1739 break; 1740 default: 1741 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1742 } 1743 break; 1744 case 3: 1745 switch (coneSize) { 1746 case 3: 1747 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1748 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1749 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1750 *numFaces = 3; 1751 *faceSize = 2; 1752 *faces = mesh->facesTmp; 1753 break; 1754 case 4: 1755 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1756 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1757 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1758 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1759 *numFaces = 4; 1760 *faceSize = 3; 1761 *faces = mesh->facesTmp; 1762 break; 1763 default: 1764 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1765 } 1766 break; 1767 default: 1768 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1769 } 1770 PetscFunctionReturn(0); 1771 } 1772 1773 #undef __FUNCT__ 1774 #define __FUNCT__ "DMPlexGetMaxSizes" 1775 /*@ 1776 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1777 1778 Not collective 1779 1780 Input Parameter: 1781 . mesh - The DMPlex 1782 1783 Output Parameters: 1784 + maxConeSize - The maximum number of in-edges 1785 - maxSupportSize - The maximum number of out-edges 1786 1787 Level: beginner 1788 1789 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1790 @*/ 1791 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1792 { 1793 DM_Plex *mesh = (DM_Plex*) dm->data; 1794 1795 PetscFunctionBegin; 1796 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1797 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1798 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1799 PetscFunctionReturn(0); 1800 } 1801 1802 #undef __FUNCT__ 1803 #define __FUNCT__ "DMSetUp_Plex" 1804 PetscErrorCode DMSetUp_Plex(DM dm) 1805 { 1806 DM_Plex *mesh = (DM_Plex*) dm->data; 1807 PetscInt size; 1808 PetscErrorCode ierr; 1809 1810 PetscFunctionBegin; 1811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1812 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1813 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1814 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1815 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1816 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1817 if (mesh->maxSupportSize) { 1818 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1819 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1820 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1821 } 1822 PetscFunctionReturn(0); 1823 } 1824 1825 #undef __FUNCT__ 1826 #define __FUNCT__ "DMCreateSubDM_Plex" 1827 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1828 { 1829 PetscSection section, sectionGlobal; 1830 PetscInt *subIndices; 1831 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1832 PetscErrorCode ierr; 1833 1834 PetscFunctionBegin; 1835 if (!numFields) PetscFunctionReturn(0); 1836 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1837 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1838 if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1839 if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1840 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1841 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); 1842 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1843 for (p = pStart; p < pEnd; ++p) { 1844 PetscInt gdof; 1845 1846 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1847 if (gdof > 0) { 1848 for (f = 0; f < numFields; ++f) { 1849 PetscInt fdof, fcdof; 1850 1851 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1852 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1853 subSize += fdof-fcdof; 1854 } 1855 } 1856 } 1857 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1858 for (p = pStart; p < pEnd; ++p) { 1859 PetscInt gdof, goff; 1860 1861 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1862 if (gdof > 0) { 1863 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1864 for (f = 0; f < numFields; ++f) { 1865 PetscInt fdof, fcdof, fc, f2, poff = 0; 1866 1867 /* Can get rid of this loop by storing field information in the global section */ 1868 for (f2 = 0; f2 < fields[f]; ++f2) { 1869 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1870 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1871 poff += fdof-fcdof; 1872 } 1873 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1874 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1875 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1876 subIndices[subOff] = goff+poff+fc; 1877 } 1878 } 1879 } 1880 } 1881 if (is) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1882 if (subdm) { 1883 PetscSection subsection; 1884 PetscBool haveNull = PETSC_FALSE; 1885 PetscInt f, nf = 0; 1886 1887 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1888 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1889 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1890 for (f = 0; f < numFields; ++f) { 1891 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1892 if ((*subdm)->nullspaceConstructors[f]) { 1893 haveNull = PETSC_TRUE; 1894 nf = f; 1895 } 1896 } 1897 if (haveNull) { 1898 MatNullSpace nullSpace; 1899 1900 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1901 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1902 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1903 } 1904 if (dm->fields) { 1905 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); 1906 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1907 for (f = 0; f < numFields; ++f) { 1908 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1909 } 1910 if (numFields == 1) { 1911 MatNullSpace space; 1912 Mat pmat; 1913 1914 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1915 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1916 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1917 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1918 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1919 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1920 } 1921 } 1922 } 1923 PetscFunctionReturn(0); 1924 } 1925 1926 #undef __FUNCT__ 1927 #define __FUNCT__ "DMPlexSymmetrize" 1928 /*@ 1929 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1930 1931 Not collective 1932 1933 Input Parameter: 1934 . mesh - The DMPlex 1935 1936 Output Parameter: 1937 1938 Note: 1939 This should be called after all calls to DMPlexSetCone() 1940 1941 Level: beginner 1942 1943 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1944 @*/ 1945 PetscErrorCode DMPlexSymmetrize(DM dm) 1946 { 1947 DM_Plex *mesh = (DM_Plex*) dm->data; 1948 PetscInt *offsets; 1949 PetscInt supportSize; 1950 PetscInt pStart, pEnd, p; 1951 PetscErrorCode ierr; 1952 1953 PetscFunctionBegin; 1954 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1955 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1956 /* Calculate support sizes */ 1957 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1958 for (p = pStart; p < pEnd; ++p) { 1959 PetscInt dof, off, c; 1960 1961 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1962 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1963 for (c = off; c < off+dof; ++c) { 1964 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1965 } 1966 } 1967 for (p = pStart; p < pEnd; ++p) { 1968 PetscInt dof; 1969 1970 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1971 1972 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1973 } 1974 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1975 /* Calculate supports */ 1976 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1977 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1978 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1979 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1980 for (p = pStart; p < pEnd; ++p) { 1981 PetscInt dof, off, c; 1982 1983 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1984 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1985 for (c = off; c < off+dof; ++c) { 1986 const PetscInt q = mesh->cones[c]; 1987 PetscInt offS; 1988 1989 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1990 1991 mesh->supports[offS+offsets[q]] = p; 1992 ++offsets[q]; 1993 } 1994 } 1995 ierr = PetscFree(offsets);CHKERRQ(ierr); 1996 PetscFunctionReturn(0); 1997 } 1998 1999 #undef __FUNCT__ 2000 #define __FUNCT__ "DMPlexSetDepth_Private" 2001 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 2002 { 2003 PetscInt d; 2004 PetscErrorCode ierr; 2005 2006 PetscFunctionBegin; 2007 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 2008 if (d < 0) { 2009 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2010 const PetscInt *cone = NULL; 2011 PetscInt dCone; 2012 2013 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2014 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2015 d = dCone+1; 2016 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2017 } 2018 *depth = d; 2019 PetscFunctionReturn(0); 2020 } 2021 2022 #undef __FUNCT__ 2023 #define __FUNCT__ "DMPlexStratify" 2024 /*@ 2025 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2026 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2027 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2028 the DAG. 2029 2030 Not collective 2031 2032 Input Parameter: 2033 . mesh - The DMPlex 2034 2035 Output Parameter: 2036 2037 Notes: 2038 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2039 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2040 2041 This should be called after all calls to DMPlexSymmetrize() 2042 2043 Level: beginner 2044 2045 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2046 @*/ 2047 PetscErrorCode DMPlexStratify(DM dm) 2048 { 2049 DM_Plex *mesh = (DM_Plex*) dm->data; 2050 PetscInt pStart, pEnd, p; 2051 PetscInt numRoots = 0, numLeaves = 0; 2052 PetscErrorCode ierr; 2053 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2056 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2057 /* Calculate depth */ 2058 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2059 /* Initialize roots and count leaves */ 2060 for (p = pStart; p < pEnd; ++p) { 2061 PetscInt coneSize, supportSize; 2062 2063 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2064 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2065 if (!coneSize && supportSize) { 2066 ++numRoots; 2067 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2068 } else if (!supportSize && coneSize) { 2069 ++numLeaves; 2070 } else if (!supportSize && !coneSize) { 2071 /* Isolated points */ 2072 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2073 } 2074 } 2075 if (numRoots + numLeaves == (pEnd - pStart)) { 2076 for (p = pStart; p < pEnd; ++p) { 2077 PetscInt coneSize, supportSize; 2078 2079 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2080 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2081 if (!supportSize && coneSize) { 2082 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2083 } 2084 } 2085 } else { 2086 /* This might be slow since lookup is not fast */ 2087 for (p = pStart; p < pEnd; ++p) { 2088 PetscInt depth; 2089 2090 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2091 } 2092 } 2093 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2094 PetscFunctionReturn(0); 2095 } 2096 2097 #undef __FUNCT__ 2098 #define __FUNCT__ "DMPlexGetJoin" 2099 /*@C 2100 DMPlexGetJoin - Get an array for the join of the set of points 2101 2102 Not Collective 2103 2104 Input Parameters: 2105 + dm - The DMPlex object 2106 . numPoints - The number of input points for the join 2107 - points - The input points 2108 2109 Output Parameters: 2110 + numCoveredPoints - The number of points in the join 2111 - coveredPoints - The points in the join 2112 2113 Level: intermediate 2114 2115 Note: Currently, this is restricted to a single level join 2116 2117 .keywords: mesh 2118 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2119 @*/ 2120 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2121 { 2122 DM_Plex *mesh = (DM_Plex*) dm->data; 2123 PetscInt *join[2]; 2124 PetscInt joinSize, i = 0; 2125 PetscInt dof, off, p, c, m; 2126 PetscErrorCode ierr; 2127 2128 PetscFunctionBegin; 2129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2130 PetscValidPointer(points, 2); 2131 PetscValidPointer(numCoveredPoints, 3); 2132 PetscValidPointer(coveredPoints, 4); 2133 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2134 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2135 /* Copy in support of first point */ 2136 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2137 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2138 for (joinSize = 0; joinSize < dof; ++joinSize) { 2139 join[i][joinSize] = mesh->supports[off+joinSize]; 2140 } 2141 /* Check each successive support */ 2142 for (p = 1; p < numPoints; ++p) { 2143 PetscInt newJoinSize = 0; 2144 2145 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2146 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2147 for (c = 0; c < dof; ++c) { 2148 const PetscInt point = mesh->supports[off+c]; 2149 2150 for (m = 0; m < joinSize; ++m) { 2151 if (point == join[i][m]) { 2152 join[1-i][newJoinSize++] = point; 2153 break; 2154 } 2155 } 2156 } 2157 joinSize = newJoinSize; 2158 i = 1-i; 2159 } 2160 *numCoveredPoints = joinSize; 2161 *coveredPoints = join[i]; 2162 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2163 PetscFunctionReturn(0); 2164 } 2165 2166 #undef __FUNCT__ 2167 #define __FUNCT__ "DMPlexRestoreJoin" 2168 /*@C 2169 DMPlexRestoreJoin - Restore an array for the join of the set of points 2170 2171 Not Collective 2172 2173 Input Parameters: 2174 + dm - The DMPlex object 2175 . numPoints - The number of input points for the join 2176 - points - The input points 2177 2178 Output Parameters: 2179 + numCoveredPoints - The number of points in the join 2180 - coveredPoints - The points in the join 2181 2182 Level: intermediate 2183 2184 .keywords: mesh 2185 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2186 @*/ 2187 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2188 { 2189 PetscErrorCode ierr; 2190 2191 PetscFunctionBegin; 2192 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2193 PetscValidPointer(coveredPoints, 4); 2194 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2195 PetscFunctionReturn(0); 2196 } 2197 2198 #undef __FUNCT__ 2199 #define __FUNCT__ "DMPlexGetFullJoin" 2200 /*@C 2201 DMPlexGetFullJoin - Get an array for the join of the set of points 2202 2203 Not Collective 2204 2205 Input Parameters: 2206 + dm - The DMPlex object 2207 . numPoints - The number of input points for the join 2208 - points - The input points 2209 2210 Output Parameters: 2211 + numCoveredPoints - The number of points in the join 2212 - coveredPoints - The points in the join 2213 2214 Level: intermediate 2215 2216 .keywords: mesh 2217 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2218 @*/ 2219 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2220 { 2221 DM_Plex *mesh = (DM_Plex*) dm->data; 2222 PetscInt *offsets, **closures; 2223 PetscInt *join[2]; 2224 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2225 PetscInt p, d, c, m; 2226 PetscErrorCode ierr; 2227 2228 PetscFunctionBegin; 2229 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2230 PetscValidPointer(points, 2); 2231 PetscValidPointer(numCoveredPoints, 3); 2232 PetscValidPointer(coveredPoints, 4); 2233 2234 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2235 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2236 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2237 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2238 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2239 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2240 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2241 2242 for (p = 0; p < numPoints; ++p) { 2243 PetscInt closureSize; 2244 2245 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2246 2247 offsets[p*(depth+2)+0] = 0; 2248 for (d = 0; d < depth+1; ++d) { 2249 PetscInt pStart, pEnd, i; 2250 2251 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2252 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2253 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2254 offsets[p*(depth+2)+d+1] = i; 2255 break; 2256 } 2257 } 2258 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2259 } 2260 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); 2261 } 2262 for (d = 0; d < depth+1; ++d) { 2263 PetscInt dof; 2264 2265 /* Copy in support of first point */ 2266 dof = offsets[d+1] - offsets[d]; 2267 for (joinSize = 0; joinSize < dof; ++joinSize) { 2268 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2269 } 2270 /* Check each successive cone */ 2271 for (p = 1; p < numPoints && joinSize; ++p) { 2272 PetscInt newJoinSize = 0; 2273 2274 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2275 for (c = 0; c < dof; ++c) { 2276 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2277 2278 for (m = 0; m < joinSize; ++m) { 2279 if (point == join[i][m]) { 2280 join[1-i][newJoinSize++] = point; 2281 break; 2282 } 2283 } 2284 } 2285 joinSize = newJoinSize; 2286 i = 1-i; 2287 } 2288 if (joinSize) break; 2289 } 2290 *numCoveredPoints = joinSize; 2291 *coveredPoints = join[i]; 2292 for (p = 0; p < numPoints; ++p) { 2293 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2294 } 2295 ierr = PetscFree(closures);CHKERRQ(ierr); 2296 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2297 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2298 PetscFunctionReturn(0); 2299 } 2300 2301 #undef __FUNCT__ 2302 #define __FUNCT__ "DMPlexGetMeet" 2303 /*@C 2304 DMPlexGetMeet - Get an array for the meet of the set of points 2305 2306 Not Collective 2307 2308 Input Parameters: 2309 + dm - The DMPlex object 2310 . numPoints - The number of input points for the meet 2311 - points - The input points 2312 2313 Output Parameters: 2314 + numCoveredPoints - The number of points in the meet 2315 - coveredPoints - The points in the meet 2316 2317 Level: intermediate 2318 2319 Note: Currently, this is restricted to a single level meet 2320 2321 .keywords: mesh 2322 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2323 @*/ 2324 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2325 { 2326 DM_Plex *mesh = (DM_Plex*) dm->data; 2327 PetscInt *meet[2]; 2328 PetscInt meetSize, i = 0; 2329 PetscInt dof, off, p, c, m; 2330 PetscErrorCode ierr; 2331 2332 PetscFunctionBegin; 2333 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2334 PetscValidPointer(points, 2); 2335 PetscValidPointer(numCoveringPoints, 3); 2336 PetscValidPointer(coveringPoints, 4); 2337 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2338 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2339 /* Copy in cone of first point */ 2340 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2341 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2342 for (meetSize = 0; meetSize < dof; ++meetSize) { 2343 meet[i][meetSize] = mesh->cones[off+meetSize]; 2344 } 2345 /* Check each successive cone */ 2346 for (p = 1; p < numPoints; ++p) { 2347 PetscInt newMeetSize = 0; 2348 2349 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2350 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2351 for (c = 0; c < dof; ++c) { 2352 const PetscInt point = mesh->cones[off+c]; 2353 2354 for (m = 0; m < meetSize; ++m) { 2355 if (point == meet[i][m]) { 2356 meet[1-i][newMeetSize++] = point; 2357 break; 2358 } 2359 } 2360 } 2361 meetSize = newMeetSize; 2362 i = 1-i; 2363 } 2364 *numCoveringPoints = meetSize; 2365 *coveringPoints = meet[i]; 2366 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2367 PetscFunctionReturn(0); 2368 } 2369 2370 #undef __FUNCT__ 2371 #define __FUNCT__ "DMPlexRestoreMeet" 2372 /*@C 2373 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2374 2375 Not Collective 2376 2377 Input Parameters: 2378 + dm - The DMPlex object 2379 . numPoints - The number of input points for the meet 2380 - points - The input points 2381 2382 Output Parameters: 2383 + numCoveredPoints - The number of points in the meet 2384 - coveredPoints - The points in the meet 2385 2386 Level: intermediate 2387 2388 .keywords: mesh 2389 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2390 @*/ 2391 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2392 { 2393 PetscErrorCode ierr; 2394 2395 PetscFunctionBegin; 2396 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2397 PetscValidPointer(coveredPoints, 4); 2398 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2399 PetscFunctionReturn(0); 2400 } 2401 2402 #undef __FUNCT__ 2403 #define __FUNCT__ "DMPlexGetFullMeet" 2404 /*@C 2405 DMPlexGetFullMeet - Get an array for the meet of the set of points 2406 2407 Not Collective 2408 2409 Input Parameters: 2410 + dm - The DMPlex object 2411 . numPoints - The number of input points for the meet 2412 - points - The input points 2413 2414 Output Parameters: 2415 + numCoveredPoints - The number of points in the meet 2416 - coveredPoints - The points in the meet 2417 2418 Level: intermediate 2419 2420 .keywords: mesh 2421 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2422 @*/ 2423 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2424 { 2425 DM_Plex *mesh = (DM_Plex*) dm->data; 2426 PetscInt *offsets, **closures; 2427 PetscInt *meet[2]; 2428 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2429 PetscInt p, h, c, m; 2430 PetscErrorCode ierr; 2431 2432 PetscFunctionBegin; 2433 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2434 PetscValidPointer(points, 2); 2435 PetscValidPointer(numCoveredPoints, 3); 2436 PetscValidPointer(coveredPoints, 4); 2437 2438 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2439 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2440 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2441 maxSize = PetscPowInt(mesh->maxConeSize,height); 2442 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2443 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2444 2445 for (p = 0; p < numPoints; ++p) { 2446 PetscInt closureSize; 2447 2448 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2449 2450 offsets[p*(height+2)+0] = 0; 2451 for (h = 0; h < height+1; ++h) { 2452 PetscInt pStart, pEnd, i; 2453 2454 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2455 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2456 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2457 offsets[p*(height+2)+h+1] = i; 2458 break; 2459 } 2460 } 2461 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2462 } 2463 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); 2464 } 2465 for (h = 0; h < height+1; ++h) { 2466 PetscInt dof; 2467 2468 /* Copy in cone of first point */ 2469 dof = offsets[h+1] - offsets[h]; 2470 for (meetSize = 0; meetSize < dof; ++meetSize) { 2471 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2472 } 2473 /* Check each successive cone */ 2474 for (p = 1; p < numPoints && meetSize; ++p) { 2475 PetscInt newMeetSize = 0; 2476 2477 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2478 for (c = 0; c < dof; ++c) { 2479 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2480 2481 for (m = 0; m < meetSize; ++m) { 2482 if (point == meet[i][m]) { 2483 meet[1-i][newMeetSize++] = point; 2484 break; 2485 } 2486 } 2487 } 2488 meetSize = newMeetSize; 2489 i = 1-i; 2490 } 2491 if (meetSize) break; 2492 } 2493 *numCoveredPoints = meetSize; 2494 *coveredPoints = meet[i]; 2495 for (p = 0; p < numPoints; ++p) { 2496 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2497 } 2498 ierr = PetscFree(closures);CHKERRQ(ierr); 2499 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2500 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2501 PetscFunctionReturn(0); 2502 } 2503 2504 #undef __FUNCT__ 2505 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2506 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2507 { 2508 MPI_Comm comm; 2509 PetscInt cellDim; 2510 PetscErrorCode ierr; 2511 2512 PetscFunctionBegin; 2513 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2514 PetscValidPointer(numFaceVertices,3); 2515 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2516 switch (cellDim) { 2517 case 0: 2518 *numFaceVertices = 0; 2519 break; 2520 case 1: 2521 *numFaceVertices = 1; 2522 break; 2523 case 2: 2524 switch (numCorners) { 2525 case 3: /* triangle */ 2526 *numFaceVertices = 2; /* Edge has 2 vertices */ 2527 break; 2528 case 4: /* quadrilateral */ 2529 *numFaceVertices = 2; /* Edge has 2 vertices */ 2530 break; 2531 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2532 *numFaceVertices = 3; /* Edge has 3 vertices */ 2533 break; 2534 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2535 *numFaceVertices = 3; /* Edge has 3 vertices */ 2536 break; 2537 default: 2538 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2539 } 2540 break; 2541 case 3: 2542 switch (numCorners) { 2543 case 4: /* tetradehdron */ 2544 *numFaceVertices = 3; /* Face has 3 vertices */ 2545 break; 2546 case 6: /* tet cohesive cells */ 2547 *numFaceVertices = 4; /* Face has 4 vertices */ 2548 break; 2549 case 8: /* hexahedron */ 2550 *numFaceVertices = 4; /* Face has 4 vertices */ 2551 break; 2552 case 9: /* tet cohesive Lagrange cells */ 2553 *numFaceVertices = 6; /* Face has 6 vertices */ 2554 break; 2555 case 10: /* quadratic tetrahedron */ 2556 *numFaceVertices = 6; /* Face has 6 vertices */ 2557 break; 2558 case 12: /* hex cohesive Lagrange cells */ 2559 *numFaceVertices = 6; /* Face has 6 vertices */ 2560 break; 2561 case 18: /* quadratic tet cohesive Lagrange cells */ 2562 *numFaceVertices = 6; /* Face has 6 vertices */ 2563 break; 2564 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2565 *numFaceVertices = 9; /* Face has 9 vertices */ 2566 break; 2567 default: 2568 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2569 } 2570 break; 2571 default: 2572 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2573 } 2574 PetscFunctionReturn(0); 2575 } 2576 2577 #undef __FUNCT__ 2578 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2579 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2580 { 2581 const PetscInt maxFaceCases = 30; 2582 PetscInt numFaceCases = 0; 2583 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2584 PetscInt *off, *adj; 2585 PetscInt *neighborCells, *tmpClosure; 2586 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2587 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2588 PetscErrorCode ierr; 2589 2590 PetscFunctionBegin; 2591 /* For parallel partitioning, I think you have to communicate supports */ 2592 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2593 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2594 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2595 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2596 if (cEnd - cStart == 0) { 2597 if (numVertices) *numVertices = 0; 2598 if (offsets) *offsets = NULL; 2599 if (adjacency) *adjacency = NULL; 2600 PetscFunctionReturn(0); 2601 } 2602 numCells = cEnd - cStart; 2603 /* Setup face recognition */ 2604 if (depth == 1) { 2605 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 */ 2606 2607 for (c = cStart; c < cEnd; ++c) { 2608 PetscInt corners; 2609 2610 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2611 if (!cornersSeen[corners]) { 2612 PetscInt nFV; 2613 2614 if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2615 cornersSeen[corners] = 1; 2616 2617 ierr = DMPlexGetNumFaceVertices_Internal(dm, corners, &nFV);CHKERRQ(ierr); 2618 2619 numFaceVertices[numFaceCases++] = nFV; 2620 } 2621 } 2622 } 2623 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2624 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2625 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2626 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2627 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2628 /* Count neighboring cells */ 2629 for (cell = cStart; cell < cEnd; ++cell) { 2630 PetscInt numNeighbors = maxNeighbors, n; 2631 2632 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2633 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2634 for (n = 0; n < numNeighbors; ++n) { 2635 PetscInt cellPair[2]; 2636 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2637 PetscInt meetSize = 0; 2638 const PetscInt *meet = NULL; 2639 2640 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2641 if (cellPair[0] == cellPair[1]) continue; 2642 if (!found) { 2643 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2644 if (meetSize) { 2645 PetscInt f; 2646 2647 for (f = 0; f < numFaceCases; ++f) { 2648 if (numFaceVertices[f] == meetSize) { 2649 found = PETSC_TRUE; 2650 break; 2651 } 2652 } 2653 } 2654 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2655 } 2656 if (found) ++off[cell-cStart+1]; 2657 } 2658 } 2659 /* Prefix sum */ 2660 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2661 2662 if (adjacency) { 2663 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2664 /* Get neighboring cells */ 2665 for (cell = cStart; cell < cEnd; ++cell) { 2666 PetscInt numNeighbors = maxNeighbors, n; 2667 PetscInt cellOffset = 0; 2668 2669 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2670 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2671 for (n = 0; n < numNeighbors; ++n) { 2672 PetscInt cellPair[2]; 2673 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2674 PetscInt meetSize = 0; 2675 const PetscInt *meet = NULL; 2676 2677 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2678 if (cellPair[0] == cellPair[1]) continue; 2679 if (!found) { 2680 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2681 if (meetSize) { 2682 PetscInt f; 2683 2684 for (f = 0; f < numFaceCases; ++f) { 2685 if (numFaceVertices[f] == meetSize) { 2686 found = PETSC_TRUE; 2687 break; 2688 } 2689 } 2690 } 2691 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2692 } 2693 if (found) { 2694 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2695 ++cellOffset; 2696 } 2697 } 2698 } 2699 } 2700 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2701 if (numVertices) *numVertices = numCells; 2702 if (offsets) *offsets = off; 2703 if (adjacency) *adjacency = adj; 2704 PetscFunctionReturn(0); 2705 } 2706 2707 #if defined(PETSC_HAVE_CHACO) 2708 #if defined(PETSC_HAVE_UNISTD_H) 2709 #include <unistd.h> 2710 #endif 2711 /* Chaco does not have an include file */ 2712 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2713 float *ewgts, float *x, float *y, float *z, char *outassignname, 2714 char *outfilename, short *assignment, int architecture, int ndims_tot, 2715 int mesh_dims[3], double *goal, int global_method, int local_method, 2716 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2717 2718 extern int FREE_GRAPH; 2719 2720 #undef __FUNCT__ 2721 #define __FUNCT__ "DMPlexPartition_Chaco" 2722 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2723 { 2724 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2725 MPI_Comm comm; 2726 int nvtxs = numVertices; /* number of vertices in full graph */ 2727 int *vwgts = NULL; /* weights for all vertices */ 2728 float *ewgts = NULL; /* weights for all edges */ 2729 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2730 char *outassignname = NULL; /* name of assignment output file */ 2731 char *outfilename = NULL; /* output file name */ 2732 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2733 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2734 int mesh_dims[3]; /* dimensions of mesh of processors */ 2735 double *goal = NULL; /* desired set sizes for each set */ 2736 int global_method = 1; /* global partitioning algorithm */ 2737 int local_method = 1; /* local partitioning algorithm */ 2738 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2739 int vmax = 200; /* how many vertices to coarsen down to? */ 2740 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2741 double eigtol = 0.001; /* tolerance on eigenvectors */ 2742 long seed = 123636512; /* for random graph mutations */ 2743 short int *assignment; /* Output partition */ 2744 int fd_stdout, fd_pipe[2]; 2745 PetscInt *points; 2746 PetscMPIInt commSize; 2747 int i, v, p; 2748 PetscErrorCode ierr; 2749 2750 PetscFunctionBegin; 2751 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2752 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2753 if (!numVertices) { 2754 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2755 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2756 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2757 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2758 PetscFunctionReturn(0); 2759 } 2760 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2761 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2762 2763 if (global_method == INERTIAL_METHOD) { 2764 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2765 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2766 } 2767 mesh_dims[0] = commSize; 2768 mesh_dims[1] = 1; 2769 mesh_dims[2] = 1; 2770 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2771 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2772 /* TODO: check error codes for UNIX calls */ 2773 #if defined(PETSC_HAVE_UNISTD_H) 2774 { 2775 int piperet; 2776 piperet = pipe(fd_pipe); 2777 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2778 fd_stdout = dup(1); 2779 close(1); 2780 dup2(fd_pipe[1], 1); 2781 } 2782 #endif 2783 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2784 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2785 vmax, ndims, eigtol, seed); 2786 #if defined(PETSC_HAVE_UNISTD_H) 2787 { 2788 char msgLog[10000]; 2789 int count; 2790 2791 fflush(stdout); 2792 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2793 if (count < 0) count = 0; 2794 msgLog[count] = 0; 2795 close(1); 2796 dup2(fd_stdout, 1); 2797 close(fd_stdout); 2798 close(fd_pipe[0]); 2799 close(fd_pipe[1]); 2800 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2801 } 2802 #endif 2803 /* Convert to PetscSection+IS */ 2804 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2805 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2806 for (v = 0; v < nvtxs; ++v) { 2807 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2808 } 2809 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2810 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2811 for (p = 0, i = 0; p < commSize; ++p) { 2812 for (v = 0; v < nvtxs; ++v) { 2813 if (assignment[v] == p) points[i++] = v; 2814 } 2815 } 2816 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2817 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2818 if (global_method == INERTIAL_METHOD) { 2819 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2820 } 2821 ierr = PetscFree(assignment);CHKERRQ(ierr); 2822 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2823 PetscFunctionReturn(0); 2824 } 2825 #endif 2826 2827 #if defined(PETSC_HAVE_PARMETIS) 2828 #undef __FUNCT__ 2829 #define __FUNCT__ "DMPlexPartition_ParMetis" 2830 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2831 { 2832 PetscFunctionBegin; 2833 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ParMetis not yet supported"); 2834 PetscFunctionReturn(0); 2835 } 2836 #endif 2837 2838 #undef __FUNCT__ 2839 #define __FUNCT__ "DMPlexEnlargePartition" 2840 /* Expand the partition by BFS on the adjacency graph */ 2841 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2842 { 2843 PetscHashI h; 2844 const PetscInt *points; 2845 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2846 PetscInt pStart, pEnd, part, q; 2847 PetscErrorCode ierr; 2848 2849 PetscFunctionBegin; 2850 PetscHashICreate(h); 2851 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2852 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2853 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2854 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2855 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2856 for (part = pStart; part < pEnd; ++part) { 2857 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2858 2859 PetscHashIClear(h); 2860 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2861 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2862 /* Add all existing points to h */ 2863 for (p = 0; p < numPoints; ++p) { 2864 const PetscInt point = points[off+p]; 2865 PetscHashIAdd(h, point, 1); 2866 } 2867 PetscHashISize(h, nP); 2868 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2869 /* Add all points in next BFS level */ 2870 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2871 for (p = 0; p < numPoints; ++p) { 2872 const PetscInt point = points[off+p]; 2873 PetscInt s = start[point], e = start[point+1], a; 2874 2875 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2876 } 2877 PetscHashISize(h, numNewPoints); 2878 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2879 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2880 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2881 totPoints += numNewPoints; 2882 } 2883 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2884 PetscHashIDestroy(h); 2885 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2886 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2887 for (part = pStart, q = 0; part < pEnd; ++part) { 2888 PetscInt numPoints, p; 2889 2890 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2891 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2892 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2893 } 2894 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2895 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2896 PetscFunctionReturn(0); 2897 } 2898 2899 #undef __FUNCT__ 2900 #define __FUNCT__ "DMPlexCreatePartition" 2901 /* 2902 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2903 2904 Collective on DM 2905 2906 Input Parameters: 2907 + dm - The DM 2908 . height - The height for points in the partition 2909 - enlarge - Expand each partition with neighbors 2910 2911 Output Parameters: 2912 + partSection - The PetscSection giving the division of points by partition 2913 . partition - The list of points by partition 2914 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2915 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2916 2917 Level: developer 2918 2919 .seealso DMPlexDistribute() 2920 */ 2921 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2922 { 2923 PetscMPIInt size; 2924 PetscErrorCode ierr; 2925 2926 PetscFunctionBegin; 2927 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2928 2929 *origPartSection = NULL; 2930 *origPartition = NULL; 2931 if (size == 1) { 2932 PetscInt *points; 2933 PetscInt cStart, cEnd, c; 2934 2935 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2936 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2937 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2938 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2939 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2940 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2941 for (c = cStart; c < cEnd; ++c) points[c] = c; 2942 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2943 PetscFunctionReturn(0); 2944 } 2945 if (height == 0) { 2946 PetscInt numVertices; 2947 PetscInt *start = NULL; 2948 PetscInt *adjacency = NULL; 2949 2950 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2951 if (1) { 2952 #if defined(PETSC_HAVE_CHACO) 2953 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2954 #endif 2955 } else { 2956 #if defined(PETSC_HAVE_PARMETIS) 2957 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2958 #endif 2959 } 2960 if (enlarge) { 2961 *origPartSection = *partSection; 2962 *origPartition = *partition; 2963 2964 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2965 } 2966 ierr = PetscFree(start);CHKERRQ(ierr); 2967 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2968 # if 0 2969 } else if (height == 1) { 2970 /* Build the dual graph for faces and partition the hypergraph */ 2971 PetscInt numEdges; 2972 2973 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2974 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2975 destroyCSR(numEdges, start, adjacency); 2976 #endif 2977 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2978 PetscFunctionReturn(0); 2979 } 2980 2981 #undef __FUNCT__ 2982 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2983 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2984 { 2985 /* const PetscInt height = 0; */ 2986 const PetscInt *partArray; 2987 PetscInt *allPoints, *partPoints = NULL; 2988 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2989 PetscErrorCode ierr; 2990 2991 PetscFunctionBegin; 2992 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2993 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2994 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2995 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2996 for (rank = rStart; rank < rEnd; ++rank) { 2997 PetscInt partSize = 0; 2998 PetscInt numPoints, offset, p; 2999 3000 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3001 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3002 for (p = 0; p < numPoints; ++p) { 3003 PetscInt point = partArray[offset+p], closureSize, c; 3004 PetscInt *closure = NULL; 3005 3006 /* TODO Include support for height > 0 case */ 3007 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3008 /* Merge into existing points */ 3009 if (partSize+closureSize > maxPartSize) { 3010 PetscInt *tmpPoints; 3011 3012 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 3013 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 3014 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3015 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3016 3017 partPoints = tmpPoints; 3018 } 3019 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3020 partSize += closureSize; 3021 3022 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3023 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3024 } 3025 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3026 } 3027 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3028 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3029 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3030 3031 for (rank = rStart; rank < rEnd; ++rank) { 3032 PetscInt partSize = 0, newOffset; 3033 PetscInt numPoints, offset, p; 3034 3035 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3036 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3037 for (p = 0; p < numPoints; ++p) { 3038 PetscInt point = partArray[offset+p], closureSize, c; 3039 PetscInt *closure = NULL; 3040 3041 /* TODO Include support for height > 0 case */ 3042 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3043 /* Merge into existing points */ 3044 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3045 partSize += closureSize; 3046 3047 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3048 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3049 } 3050 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3051 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3052 } 3053 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3054 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3055 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3056 PetscFunctionReturn(0); 3057 } 3058 3059 #undef __FUNCT__ 3060 #define __FUNCT__ "DMPlexDistributeField" 3061 /* 3062 Input Parameters: 3063 . originalSection 3064 , originalVec 3065 3066 Output Parameters: 3067 . newSection 3068 . newVec 3069 */ 3070 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3071 { 3072 PetscSF fieldSF; 3073 PetscInt *remoteOffsets, fieldSize; 3074 PetscScalar *originalValues, *newValues; 3075 PetscErrorCode ierr; 3076 3077 PetscFunctionBegin; 3078 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3079 3080 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3081 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3082 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3083 3084 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3085 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3086 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3087 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3088 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3089 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3090 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3091 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3092 PetscFunctionReturn(0); 3093 } 3094 3095 #undef __FUNCT__ 3096 #define __FUNCT__ "DMPlexDistribute" 3097 /*@C 3098 DMPlexDistribute - Distributes the mesh and any associated sections. 3099 3100 Not Collective 3101 3102 Input Parameter: 3103 + dm - The original DMPlex object 3104 . partitioner - The partitioning package, or NULL for the default 3105 - overlap - The overlap of partitions, 0 is the default 3106 3107 Output Parameter: 3108 . parallelMesh - The distributed DMPlex object, or NULL 3109 3110 Note: If the mesh was not distributed, the return value is NULL 3111 3112 Level: intermediate 3113 3114 .keywords: mesh, elements 3115 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3116 @*/ 3117 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3118 { 3119 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3120 MPI_Comm comm; 3121 const PetscInt height = 0; 3122 PetscInt dim, numRemoteRanks; 3123 IS origCellPart, cellPart, part; 3124 PetscSection origCellPartSection, cellPartSection, partSection; 3125 PetscSFNode *remoteRanks; 3126 PetscSF partSF, pointSF, coneSF; 3127 ISLocalToGlobalMapping renumbering; 3128 PetscSection originalConeSection, newConeSection; 3129 PetscInt *remoteOffsets; 3130 PetscInt *cones, *newCones, newConesSize; 3131 PetscBool flg; 3132 PetscMPIInt rank, numProcs, p; 3133 PetscErrorCode ierr; 3134 3135 PetscFunctionBegin; 3136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3137 PetscValidPointer(dmParallel,4); 3138 3139 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3140 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3141 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3142 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3143 3144 *dmParallel = NULL; 3145 if (numProcs == 1) PetscFunctionReturn(0); 3146 3147 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3148 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3149 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3150 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3151 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3152 if (!rank) numRemoteRanks = numProcs; 3153 else numRemoteRanks = 0; 3154 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3155 for (p = 0; p < numRemoteRanks; ++p) { 3156 remoteRanks[p].rank = p; 3157 remoteRanks[p].index = 0; 3158 } 3159 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3160 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3161 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3162 if (flg) { 3163 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3164 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3165 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3166 if (origCellPart) { 3167 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3168 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3169 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3170 } 3171 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3172 } 3173 /* Close the partition over the mesh */ 3174 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3175 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3176 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3177 /* Create new mesh */ 3178 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3179 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3180 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3181 pmesh = (DM_Plex*) (*dmParallel)->data; 3182 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3183 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3184 if (flg) { 3185 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3186 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3187 ierr = ISView(part, NULL);CHKERRQ(ierr); 3188 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3189 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3190 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3191 } 3192 /* Distribute cone section */ 3193 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3194 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3195 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3196 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3197 { 3198 PetscInt pStart, pEnd, p; 3199 3200 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3201 for (p = pStart; p < pEnd; ++p) { 3202 PetscInt coneSize; 3203 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3204 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3205 } 3206 } 3207 /* Communicate and renumber cones */ 3208 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3209 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3210 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3211 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3212 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3213 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3214 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3215 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3216 if (flg) { 3217 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3218 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3219 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3220 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3221 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3222 } 3223 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3224 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3225 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3226 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3227 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3228 /* Create supports and stratify sieve */ 3229 { 3230 PetscInt pStart, pEnd; 3231 3232 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3233 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3234 } 3235 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3236 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3237 /* Distribute Coordinates */ 3238 { 3239 PetscSection originalCoordSection, newCoordSection; 3240 Vec originalCoordinates, newCoordinates; 3241 const char *name; 3242 3243 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3244 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3245 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3246 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3247 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3248 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3249 3250 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3251 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3252 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3253 } 3254 /* Distribute labels */ 3255 { 3256 DMLabel next = mesh->labels, newNext = pmesh->labels; 3257 PetscInt numLabels = 0, l; 3258 3259 /* Bcast number of labels */ 3260 while (next) { 3261 ++numLabels; next = next->next; 3262 } 3263 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3264 next = mesh->labels; 3265 for (l = 0; l < numLabels; ++l) { 3266 DMLabel newLabel; 3267 const PetscInt *partArray; 3268 char *name; 3269 PetscInt *stratumSizes = NULL, *points = NULL; 3270 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3271 PetscInt nameSize, s, p; 3272 PetscBool isdepth; 3273 size_t len = 0; 3274 3275 /* Bcast name (could filter for no points) */ 3276 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3277 nameSize = len; 3278 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3279 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3280 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3281 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3282 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3283 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3284 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3285 newLabel->name = name; 3286 /* Bcast numStrata (could filter for no points in stratum) */ 3287 if (!rank) newLabel->numStrata = next->numStrata; 3288 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3289 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3290 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3291 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3292 /* Bcast stratumValues (could filter for no points in stratum) */ 3293 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3294 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3295 /* Find size on each process and Scatter */ 3296 if (!rank) { 3297 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3298 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3299 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3300 for (s = 0; s < next->numStrata; ++s) { 3301 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3302 const PetscInt point = next->points[p]; 3303 PetscInt proc; 3304 3305 for (proc = 0; proc < numProcs; ++proc) { 3306 PetscInt dof, off, pPart; 3307 3308 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3309 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3310 for (pPart = off; pPart < off+dof; ++pPart) { 3311 if (partArray[pPart] == point) { 3312 ++stratumSizes[proc*next->numStrata+s]; 3313 break; 3314 } 3315 } 3316 } 3317 } 3318 } 3319 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3320 } 3321 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3322 /* Calculate stratumOffsets */ 3323 newLabel->stratumOffsets[0] = 0; 3324 for (s = 0; s < newLabel->numStrata; ++s) { 3325 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3326 } 3327 /* Pack points and Scatter */ 3328 if (!rank) { 3329 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3330 displs[0] = 0; 3331 for (p = 0; p < numProcs; ++p) { 3332 sendcnts[p] = 0; 3333 for (s = 0; s < next->numStrata; ++s) { 3334 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3335 } 3336 offsets[p] = displs[p]; 3337 displs[p+1] = displs[p] + sendcnts[p]; 3338 } 3339 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3340 for (s = 0; s < next->numStrata; ++s) { 3341 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3342 const PetscInt point = next->points[p]; 3343 PetscInt proc; 3344 3345 for (proc = 0; proc < numProcs; ++proc) { 3346 PetscInt dof, off, pPart; 3347 3348 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3349 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3350 for (pPart = off; pPart < off+dof; ++pPart) { 3351 if (partArray[pPart] == point) { 3352 points[offsets[proc]++] = point; 3353 break; 3354 } 3355 } 3356 } 3357 } 3358 } 3359 } 3360 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3361 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3362 ierr = PetscFree(points);CHKERRQ(ierr); 3363 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3364 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3365 /* Renumber points */ 3366 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3367 /* Sort points */ 3368 for (s = 0; s < newLabel->numStrata; ++s) { 3369 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3370 } 3371 /* Insert into list */ 3372 if (newNext) newNext->next = newLabel; 3373 else pmesh->labels = newLabel; 3374 newNext = newLabel; 3375 if (!rank) next = next->next; 3376 } 3377 } 3378 /* Cleanup Partition */ 3379 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3380 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3381 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3382 ierr = ISDestroy(&part);CHKERRQ(ierr); 3383 /* Create point SF for parallel mesh */ 3384 { 3385 const PetscInt *leaves; 3386 PetscSFNode *remotePoints, *rowners, *lowners; 3387 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3388 PetscInt pStart, pEnd; 3389 3390 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3391 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3392 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3393 for (p=0; p<numRoots; p++) { 3394 rowners[p].rank = -1; 3395 rowners[p].index = -1; 3396 } 3397 if (origCellPart) { 3398 /* Make sure cells in the original partition are not assigned to other procs */ 3399 const PetscInt *origCells; 3400 3401 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3402 for (p = 0; p < numProcs; ++p) { 3403 PetscInt dof, off, d; 3404 3405 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3406 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3407 for (d = off; d < off+dof; ++d) { 3408 rowners[origCells[d]].rank = p; 3409 } 3410 } 3411 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3412 } 3413 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3414 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3415 3416 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3417 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3418 for (p = 0; p < numLeaves; ++p) { 3419 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3420 lowners[p].rank = rank; 3421 lowners[p].index = leaves ? leaves[p] : p; 3422 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3423 lowners[p].rank = -2; 3424 lowners[p].index = -2; 3425 } 3426 } 3427 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3428 rowners[p].rank = -3; 3429 rowners[p].index = -3; 3430 } 3431 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3432 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3433 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3434 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3435 for (p = 0; p < numLeaves; ++p) { 3436 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3437 if (lowners[p].rank != rank) ++numGhostPoints; 3438 } 3439 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3440 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3441 for (p = 0, gp = 0; p < numLeaves; ++p) { 3442 if (lowners[p].rank != rank) { 3443 ghostPoints[gp] = leaves ? leaves[p] : p; 3444 remotePoints[gp].rank = lowners[p].rank; 3445 remotePoints[gp].index = lowners[p].index; 3446 ++gp; 3447 } 3448 } 3449 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3450 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3451 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3452 } 3453 /* Cleanup */ 3454 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3455 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3456 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3457 PetscFunctionReturn(0); 3458 } 3459 3460 #undef __FUNCT__ 3461 #define __FUNCT__ "DMPlexRenumber_Private" 3462 /* 3463 Reasons to renumber: 3464 3465 1) Permute points, e.g. bandwidth reduction (Renumber) 3466 3467 a) Must not mix strata 3468 3469 2) Shift numbers for point insertion (Shift) 3470 3471 a) Want operation brken into parts so that insertion can be interleaved 3472 3473 renumbering - An IS which provides the new numbering 3474 */ 3475 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3476 { 3477 PetscFunctionBegin; 3478 PetscFunctionReturn(0); 3479 } 3480 3481 #undef __FUNCT__ 3482 #define __FUNCT__ "DMPlexShiftPoint_Private" 3483 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3484 { 3485 if (depth < 0) return p; 3486 /* Cells */ if (p < depthEnd[depth]) return p; 3487 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3488 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3489 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3490 } 3491 3492 #undef __FUNCT__ 3493 #define __FUNCT__ "DMPlexShiftSizes_Private" 3494 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3495 { 3496 PetscInt *depthEnd; 3497 PetscInt depth = 0, d, pStart, pEnd, p; 3498 PetscErrorCode ierr; 3499 3500 PetscFunctionBegin; 3501 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3502 if (depth < 0) PetscFunctionReturn(0); 3503 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3504 /* Step 1: Expand chart */ 3505 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3506 for (d = 0; d <= depth; ++d) { 3507 pEnd += depthShift[d]; 3508 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3509 } 3510 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3511 /* Step 2: Set cone and support sizes */ 3512 for (d = 0; d <= depth; ++d) { 3513 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3514 for (p = pStart; p < pEnd; ++p) { 3515 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3516 PetscInt size; 3517 3518 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3519 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3520 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3521 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3522 } 3523 } 3524 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3525 PetscFunctionReturn(0); 3526 } 3527 3528 #undef __FUNCT__ 3529 #define __FUNCT__ "DMPlexShiftPoints_Private" 3530 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3531 { 3532 PetscInt *depthEnd, *newpoints; 3533 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3534 PetscErrorCode ierr; 3535 3536 PetscFunctionBegin; 3537 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3538 if (depth < 0) PetscFunctionReturn(0); 3539 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3540 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3541 for (d = 0; d <= depth; ++d) { 3542 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3543 } 3544 /* Step 5: Set cones and supports */ 3545 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3546 for (p = pStart; p < pEnd; ++p) { 3547 const PetscInt *points = NULL, *orientations = NULL; 3548 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3549 3550 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3551 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3552 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3553 for (i = 0; i < size; ++i) { 3554 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3555 } 3556 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3557 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3558 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3559 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3560 for (i = 0; i < size; ++i) { 3561 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3562 } 3563 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3564 } 3565 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3566 PetscFunctionReturn(0); 3567 } 3568 3569 #undef __FUNCT__ 3570 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3571 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3572 { 3573 PetscSection coordSection, newCoordSection; 3574 Vec coordinates, newCoordinates; 3575 PetscScalar *coords, *newCoords; 3576 PetscInt *depthEnd, coordSize; 3577 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3578 PetscErrorCode ierr; 3579 3580 PetscFunctionBegin; 3581 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3582 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3583 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3584 for (d = 0; d <= depth; ++d) { 3585 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3586 } 3587 /* Step 8: Convert coordinates */ 3588 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3589 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3590 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3591 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);CHKERRQ(ierr); 3592 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3593 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3594 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3595 for (v = vStartNew; v < vEndNew; ++v) { 3596 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3597 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3598 } 3599 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3600 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3601 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3602 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &newCoordinates);CHKERRQ(ierr); 3603 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3604 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3605 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3606 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3607 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3608 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3609 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3610 for (v = vStart; v < vEnd; ++v) { 3611 PetscInt dof, off, noff, d; 3612 3613 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3614 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3615 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3616 for (d = 0; d < dof; ++d) { 3617 newCoords[noff+d] = coords[off+d]; 3618 } 3619 } 3620 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3621 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3622 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3623 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3624 PetscFunctionReturn(0); 3625 } 3626 3627 #undef __FUNCT__ 3628 #define __FUNCT__ "DMPlexShiftSF_Private" 3629 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3630 { 3631 PetscInt *depthEnd; 3632 PetscInt depth = 0, d; 3633 PetscSF sfPoint, sfPointNew; 3634 const PetscSFNode *remotePoints; 3635 PetscSFNode *gremotePoints; 3636 const PetscInt *localPoints; 3637 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3638 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3639 PetscMPIInt numProcs; 3640 PetscErrorCode ierr; 3641 3642 PetscFunctionBegin; 3643 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3644 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3645 for (d = 0; d <= depth; ++d) { 3646 totShift += depthShift[d]; 3647 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3648 } 3649 /* Step 9: Convert pointSF */ 3650 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 3651 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3652 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3653 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3654 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3655 if (numRoots >= 0) { 3656 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3657 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3658 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3659 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3660 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3661 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3662 for (l = 0; l < numLeaves; ++l) { 3663 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3664 gremotePoints[l].rank = remotePoints[l].rank; 3665 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3666 } 3667 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3668 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3669 } 3670 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3671 PetscFunctionReturn(0); 3672 } 3673 3674 #undef __FUNCT__ 3675 #define __FUNCT__ "DMPlexShiftLabels_Private" 3676 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3677 { 3678 PetscSF sfPoint; 3679 DMLabel vtkLabel, ghostLabel; 3680 PetscInt *depthEnd; 3681 const PetscSFNode *leafRemote; 3682 const PetscInt *leafLocal; 3683 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3684 PetscMPIInt rank; 3685 PetscErrorCode ierr; 3686 3687 PetscFunctionBegin; 3688 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3689 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3690 for (d = 0; d <= depth; ++d) { 3691 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3692 } 3693 /* Step 10: Convert labels */ 3694 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3695 for (l = 0; l < numLabels; ++l) { 3696 DMLabel label, newlabel; 3697 const char *lname; 3698 PetscBool isDepth; 3699 IS valueIS; 3700 const PetscInt *values; 3701 PetscInt numValues, val; 3702 3703 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3704 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3705 if (isDepth) continue; 3706 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3707 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3708 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3709 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3710 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3711 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3712 for (val = 0; val < numValues; ++val) { 3713 IS pointIS; 3714 const PetscInt *points; 3715 PetscInt numPoints, p; 3716 3717 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3718 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3719 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3720 for (p = 0; p < numPoints; ++p) { 3721 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3722 3723 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3724 } 3725 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3726 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3727 } 3728 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3729 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3730 } 3731 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3732 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3733 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 3734 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3735 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3736 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3737 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3738 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3739 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3740 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3741 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3742 for (; c < leafLocal[l] && c < cEnd; ++c) { 3743 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3744 } 3745 if (leafLocal[l] >= cEnd) break; 3746 if (leafRemote[l].rank == rank) { 3747 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3748 } else { 3749 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3750 } 3751 } 3752 for (; c < cEnd; ++c) { 3753 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3754 } 3755 if (0) { 3756 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3757 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3758 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3759 } 3760 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3761 for (f = fStart; f < fEnd; ++f) { 3762 PetscInt numCells; 3763 3764 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3765 if (numCells < 2) { 3766 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3767 } else { 3768 const PetscInt *cells = NULL; 3769 PetscInt vA, vB; 3770 3771 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3772 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3773 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3774 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3775 } 3776 } 3777 if (0) { 3778 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3779 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3780 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3781 } 3782 PetscFunctionReturn(0); 3783 } 3784 3785 #undef __FUNCT__ 3786 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3787 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3788 { 3789 DMLabel label; 3790 IS valueIS; 3791 const PetscInt *values; 3792 PetscInt *depthShift; 3793 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3794 PetscErrorCode ierr; 3795 3796 PetscFunctionBegin; 3797 /* Count ghost cells */ 3798 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3799 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3800 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3801 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3802 3803 *numGhostCells = 0; 3804 for (fs = 0; fs < numFS; ++fs) { 3805 PetscInt numBdFaces; 3806 3807 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3808 3809 *numGhostCells += numBdFaces; 3810 } 3811 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3812 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3813 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3814 if (depth >= 0) depthShift[depth] = *numGhostCells; 3815 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3816 /* Step 3: Set cone/support sizes for new points */ 3817 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3818 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3819 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3820 } 3821 for (fs = 0; fs < numFS; ++fs) { 3822 IS faceIS; 3823 const PetscInt *faces; 3824 PetscInt numFaces, f; 3825 3826 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3827 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3828 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3829 for (f = 0; f < numFaces; ++f) { 3830 PetscInt size; 3831 3832 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3833 if (size != 1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3834 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3835 } 3836 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3837 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3838 } 3839 /* Step 4: Setup ghosted DM */ 3840 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3841 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3842 /* Step 6: Set cones and supports for new points */ 3843 ghostCell = cEnd; 3844 for (fs = 0; fs < numFS; ++fs) { 3845 IS faceIS; 3846 const PetscInt *faces; 3847 PetscInt numFaces, f; 3848 3849 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3850 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3851 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3852 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3853 PetscInt newFace = faces[f] + *numGhostCells; 3854 3855 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3856 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3857 } 3858 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3859 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3860 } 3861 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3862 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3863 /* Step 7: Stratify */ 3864 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3865 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3866 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3867 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3868 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3869 PetscFunctionReturn(0); 3870 } 3871 3872 #undef __FUNCT__ 3873 #define __FUNCT__ "DMPlexConstructGhostCells" 3874 /*@C 3875 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3876 3877 Collective on dm 3878 3879 Input Parameters: 3880 + dm - The original DM 3881 - labelName - The label specifying the boundary faces (this could be auto-generated) 3882 3883 Output Parameters: 3884 + numGhostCells - The number of ghost cells added to the DM 3885 - dmGhosted - The new DM 3886 3887 Level: developer 3888 3889 .seealso: DMCreate() 3890 */ 3891 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3892 { 3893 DM gdm; 3894 PetscInt dim; 3895 PetscErrorCode ierr; 3896 3897 PetscFunctionBegin; 3898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3899 PetscValidPointer(numGhostCells, 3); 3900 PetscValidPointer(dmGhosted, 4); 3901 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &gdm);CHKERRQ(ierr); 3902 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3903 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3904 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3905 switch (dim) { 3906 case 2: 3907 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3908 break; 3909 default: 3910 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3911 } 3912 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3913 *dmGhosted = gdm; 3914 PetscFunctionReturn(0); 3915 } 3916 3917 #undef __FUNCT__ 3918 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3919 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3920 { 3921 MPI_Comm comm; 3922 IS valueIS, *pointIS; 3923 const PetscInt *values, **splitPoints; 3924 PetscSection coordSection; 3925 Vec coordinates; 3926 PetscScalar *coords; 3927 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3928 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3929 PetscErrorCode ierr; 3930 3931 PetscFunctionBegin; 3932 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3933 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3934 /* Count split points and add cohesive cells */ 3935 if (label) { 3936 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3937 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3938 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3939 } 3940 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3941 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3942 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3943 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3944 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3945 for (d = 0; d <= depth; ++d) { 3946 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3947 numSplitPoints[d] = 0; 3948 splitPoints[d] = NULL; 3949 pointIS[d] = NULL; 3950 } 3951 for (sp = 0; sp < numSP; ++sp) { 3952 const PetscInt dep = values[sp]; 3953 3954 if ((dep < 0) || (dep > depth)) continue; 3955 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3956 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3957 if (pointIS[dep]) { 3958 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3959 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3960 } 3961 } 3962 if (depth >= 0) { 3963 /* Calculate number of additional points */ 3964 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3965 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3966 /* Calculate hybrid bound for each dimension */ 3967 pMaxNew[0] += depthShift[depth]; 3968 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3969 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3970 3971 /* Calculate point offset for each dimension */ 3972 depthOffset[depth] = 0; 3973 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3974 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3975 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3976 } 3977 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3978 /* Step 3: Set cone/support sizes for new points */ 3979 for (dep = 0; dep <= depth; ++dep) { 3980 for (p = 0; p < numSplitPoints[dep]; ++p) { 3981 const PetscInt oldp = splitPoints[dep][p]; 3982 const PetscInt newp = depthOffset[dep] + oldp; 3983 const PetscInt splitp = pMaxNew[dep] + p; 3984 const PetscInt *support; 3985 PetscInt coneSize, supportSize, q, e; 3986 3987 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3988 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3989 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3990 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3991 if (dep == depth-1) { 3992 const PetscInt ccell = pMaxNew[depth] + p; 3993 /* Add cohesive cells, they are prisms */ 3994 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3995 } else if (dep == 0) { 3996 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3997 3998 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3999 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4000 for (e = 0, q = 0; e < supportSize; ++e) { 4001 PetscInt val; 4002 4003 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4004 if ((val == 1) || (val == (shift + 1))) ++q; 4005 } 4006 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 4007 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4008 for (e = 0, q = 0; e < supportSize; ++e) { 4009 PetscInt val; 4010 4011 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4012 if ((val == 1) || (val == -(shift + 1))) ++q; 4013 } 4014 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 4015 /* Add cohesive edges */ 4016 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 4017 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4018 } else if (dep == dim-2) { 4019 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4020 /* Split old edge: Faces in positive side cells and old split faces */ 4021 for (e = 0, q = 0; e < supportSize; ++e) { 4022 PetscInt val; 4023 4024 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4025 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4026 } 4027 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4028 /* Split new edge: Faces in negative side cells and new split faces */ 4029 for (e = 0, q = 0; e < supportSize; ++e) { 4030 PetscInt val; 4031 4032 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4033 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4034 } 4035 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4036 } 4037 } 4038 } 4039 /* Step 4: Setup split DM */ 4040 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4041 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4042 /* Step 6: Set cones and supports for new points */ 4043 for (dep = 0; dep <= depth; ++dep) { 4044 for (p = 0; p < numSplitPoints[dep]; ++p) { 4045 const PetscInt oldp = splitPoints[dep][p]; 4046 const PetscInt newp = depthOffset[dep] + oldp; 4047 const PetscInt splitp = pMaxNew[dep] + p; 4048 const PetscInt *cone, *support, *ornt; 4049 PetscInt coneSize, supportSize, q, v, e, s; 4050 4051 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4052 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4053 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4054 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4055 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4056 if (dep == depth-1) { 4057 const PetscInt ccell = pMaxNew[depth] + p; 4058 const PetscInt *supportF; 4059 4060 /* Split face: copy in old face to new face to start */ 4061 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4062 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4063 /* Split old face: old vertices/edges in cone so no change */ 4064 /* Split new face: new vertices/edges in cone */ 4065 for (q = 0; q < coneSize; ++q) { 4066 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4067 4068 coneNew[2+q] = pMaxNew[dim-2] + v; 4069 } 4070 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4071 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4072 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4073 coneNew[0] = newp; 4074 coneNew[1] = splitp; 4075 for (q = 0; q < coneSize; ++q) { 4076 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4077 } 4078 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4079 4080 4081 for (s = 0; s < supportSize; ++s) { 4082 PetscInt val; 4083 4084 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4085 if (val < 0) { 4086 /* Split old face: Replace negative side cell with cohesive cell */ 4087 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4088 } else { 4089 /* Split new face: Replace positive side cell with cohesive cell */ 4090 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4091 } 4092 } 4093 } else if (dep == 0) { 4094 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4095 4096 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4097 for (e = 0, q = 0; e < supportSize; ++e) { 4098 PetscInt val; 4099 4100 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4101 if ((val == 1) || (val == (shift + 1))) { 4102 supportNew[q++] = depthOffset[1] + support[e]; 4103 } 4104 } 4105 supportNew[q] = cedge; 4106 4107 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4108 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4109 for (e = 0, q = 0; e < supportSize; ++e) { 4110 PetscInt val, edge; 4111 4112 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4113 if (val == 1) { 4114 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4115 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4116 supportNew[q++] = pMaxNew[1] + edge; 4117 } else if (val == -(shift + 1)) { 4118 supportNew[q++] = depthOffset[1] + support[e]; 4119 } 4120 } 4121 supportNew[q] = cedge; 4122 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4123 /* Cohesive edge: Old and new split vertex, punting on support */ 4124 coneNew[0] = newp; 4125 coneNew[1] = splitp; 4126 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4127 } else if (dep == dim-2) { 4128 /* Split old edge: old vertices in cone so no change */ 4129 /* Split new edge: new vertices in cone */ 4130 for (q = 0; q < coneSize; ++q) { 4131 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4132 4133 coneNew[q] = pMaxNew[dim-3] + v; 4134 } 4135 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4136 /* Split old edge: Faces in positive side cells and old split faces */ 4137 for (e = 0, q = 0; e < supportSize; ++e) { 4138 PetscInt val; 4139 4140 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4141 if ((val == dim-1) || (val == (shift + dim-1))) { 4142 supportNew[q++] = depthOffset[dim-1] + support[e]; 4143 } 4144 } 4145 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4146 /* Split new edge: Faces in negative side cells and new split faces */ 4147 for (e = 0, q = 0; e < supportSize; ++e) { 4148 PetscInt val, face; 4149 4150 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4151 if (val == dim-1) { 4152 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4153 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4154 supportNew[q++] = pMaxNew[dim-1] + face; 4155 } else if (val == -(shift + dim-1)) { 4156 supportNew[q++] = depthOffset[dim-1] + support[e]; 4157 } 4158 } 4159 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4160 } 4161 } 4162 } 4163 /* Step 6b: Replace split points in negative side cones */ 4164 for (sp = 0; sp < numSP; ++sp) { 4165 PetscInt dep = values[sp]; 4166 IS pIS; 4167 PetscInt numPoints; 4168 const PetscInt *points; 4169 4170 if (dep >= 0) continue; 4171 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4172 if (!pIS) continue; 4173 dep = -dep - shift; 4174 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4175 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4176 for (p = 0; p < numPoints; ++p) { 4177 const PetscInt oldp = points[p]; 4178 const PetscInt newp = depthOffset[dep] + oldp; 4179 const PetscInt *cone; 4180 PetscInt coneSize, c; 4181 PetscBool replaced = PETSC_FALSE; 4182 4183 /* Negative edge: replace split vertex */ 4184 /* Negative cell: replace split face */ 4185 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4186 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4187 for (c = 0; c < coneSize; ++c) { 4188 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4189 PetscInt csplitp, cp, val; 4190 4191 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4192 if (val == dep-1) { 4193 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4194 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4195 csplitp = pMaxNew[dep-1] + cp; 4196 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4197 replaced = PETSC_TRUE; 4198 } 4199 } 4200 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4201 } 4202 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4203 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4204 } 4205 /* Step 7: Stratify */ 4206 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4207 /* Step 8: Coordinates */ 4208 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4209 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4210 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4211 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4212 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4213 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4214 const PetscInt splitp = pMaxNew[0] + v; 4215 PetscInt dof, off, soff, d; 4216 4217 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4218 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4219 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4220 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4221 } 4222 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4223 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4224 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4225 /* Step 10: Labels */ 4226 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4227 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4228 for (dep = 0; dep <= depth; ++dep) { 4229 for (p = 0; p < numSplitPoints[dep]; ++p) { 4230 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4231 const PetscInt splitp = pMaxNew[dep] + p; 4232 PetscInt l; 4233 4234 for (l = 0; l < numLabels; ++l) { 4235 DMLabel mlabel; 4236 const char *lname; 4237 PetscInt val; 4238 4239 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4240 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4241 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4242 if (val >= 0) { 4243 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4244 if (dep == 0) { 4245 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4246 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4247 } 4248 } 4249 } 4250 } 4251 } 4252 for (sp = 0; sp < numSP; ++sp) { 4253 const PetscInt dep = values[sp]; 4254 4255 if ((dep < 0) || (dep > depth)) continue; 4256 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4257 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4258 } 4259 if (label) { 4260 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4261 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4262 } 4263 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4264 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4265 PetscFunctionReturn(0); 4266 } 4267 4268 #undef __FUNCT__ 4269 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4270 /*@C 4271 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4272 4273 Collective on dm 4274 4275 Input Parameters: 4276 + dm - The original DM 4277 - labelName - The label specifying the boundary faces (this could be auto-generated) 4278 4279 Output Parameters: 4280 - dmSplit - The new DM 4281 4282 Level: developer 4283 4284 .seealso: DMCreate() 4285 */ 4286 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4287 { 4288 DM sdm; 4289 PetscInt dim; 4290 PetscErrorCode ierr; 4291 4292 PetscFunctionBegin; 4293 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4294 PetscValidPointer(dmSplit, 4); 4295 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 4296 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4297 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4298 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4299 switch (dim) { 4300 case 2: 4301 case 3: 4302 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4303 break; 4304 default: 4305 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4306 } 4307 *dmSplit = sdm; 4308 PetscFunctionReturn(0); 4309 } 4310 4311 #undef __FUNCT__ 4312 #define __FUNCT__ "DMLabelCohesiveComplete" 4313 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4314 { 4315 IS dimIS; 4316 const PetscInt *points; 4317 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4318 PetscErrorCode ierr; 4319 4320 PetscFunctionBegin; 4321 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4322 /* Cell orientation for face gives the side of the fault */ 4323 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4324 if (!dimIS) PetscFunctionReturn(0); 4325 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4326 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4327 for (p = 0; p < numPoints; ++p) { 4328 const PetscInt *support; 4329 PetscInt supportSize, s; 4330 4331 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4332 if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4333 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4334 for (s = 0; s < supportSize; ++s) { 4335 const PetscInt *cone, *ornt; 4336 PetscInt coneSize, c; 4337 PetscBool pos = PETSC_TRUE; 4338 4339 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4340 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4341 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4342 for (c = 0; c < coneSize; ++c) { 4343 if (cone[c] == points[p]) { 4344 if (ornt[c] >= 0) { 4345 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4346 } else { 4347 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4348 pos = PETSC_FALSE; 4349 } 4350 break; 4351 } 4352 } 4353 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]); 4354 /* Put faces touching the fault in the label */ 4355 for (c = 0; c < coneSize; ++c) { 4356 const PetscInt point = cone[c]; 4357 4358 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4359 if (val == -1) { 4360 PetscInt *closure = NULL; 4361 PetscInt closureSize, cl; 4362 4363 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4364 for (cl = 0; cl < closureSize*2; cl += 2) { 4365 const PetscInt clp = closure[cl]; 4366 4367 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4368 if ((val >= 0) && (val < dim-1)) { 4369 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4370 break; 4371 } 4372 } 4373 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4374 } 4375 } 4376 } 4377 } 4378 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4379 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4380 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4381 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4382 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4383 if (!dimIS) PetscFunctionReturn(0); 4384 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4385 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4386 for (p = 0; p < numPoints; ++p) { 4387 PetscInt *star = NULL; 4388 PetscInt starSize, s; 4389 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4390 4391 /* First mark cells connected to the fault */ 4392 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4393 while (again) { 4394 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4395 again = 0; 4396 for (s = 0; s < starSize*2; s += 2) { 4397 const PetscInt point = star[s]; 4398 const PetscInt *cone; 4399 PetscInt coneSize, c; 4400 4401 if ((point < cStart) || (point >= cEnd)) continue; 4402 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4403 if (val != -1) continue; 4404 again = 2; 4405 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4406 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4407 for (c = 0; c < coneSize; ++c) { 4408 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4409 if (val != -1) { 4410 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); 4411 if (val > 0) { 4412 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4413 } else { 4414 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4415 } 4416 again = 1; 4417 break; 4418 } 4419 } 4420 } 4421 } 4422 /* Classify the rest by cell membership */ 4423 for (s = 0; s < starSize*2; s += 2) { 4424 const PetscInt point = star[s]; 4425 4426 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4427 if (val == -1) { 4428 PetscInt *sstar = NULL; 4429 PetscInt sstarSize, ss; 4430 PetscBool marked = PETSC_FALSE; 4431 4432 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4433 for (ss = 0; ss < sstarSize*2; ss += 2) { 4434 const PetscInt spoint = sstar[ss]; 4435 4436 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4437 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4438 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4439 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4440 if (val > 0) { 4441 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4442 } else { 4443 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4444 } 4445 marked = PETSC_TRUE; 4446 break; 4447 } 4448 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4449 if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 4450 } 4451 } 4452 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4453 } 4454 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4455 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4456 PetscFunctionReturn(0); 4457 } 4458 4459 #undef __FUNCT__ 4460 #define __FUNCT__ "DMPlexInterpolate_2D" 4461 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4462 { 4463 DM idm; 4464 DM_Plex *mesh; 4465 PetscHashIJ edgeTable; 4466 PetscInt *off; 4467 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4468 PetscInt numEdges, firstEdge, edge, e; 4469 PetscErrorCode ierr; 4470 4471 PetscFunctionBegin; 4472 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4473 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4474 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4475 numCells = cEnd - cStart; 4476 numVertices = vEnd - vStart; 4477 firstEdge = numCells + numVertices; 4478 numEdges = 0; 4479 /* Count edges using algorithm from CreateNeighborCSR */ 4480 ierr = DMPlexCreateNeighborCSR(dm, NULL, &off, NULL);CHKERRQ(ierr); 4481 if (off) { 4482 PetscInt numCorners = 0; 4483 4484 numEdges = off[numCells]/2; 4485 #if 0 4486 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4487 numEdges += 3*numCells - off[numCells]; 4488 #else 4489 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4490 for (c = cStart; c < cEnd; ++c) { 4491 PetscInt coneSize; 4492 4493 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4494 numCorners += coneSize; 4495 } 4496 numEdges += numCorners - off[numCells]; 4497 #endif 4498 } 4499 #if 0 4500 /* Check Euler characteristic V - E + F = 1 */ 4501 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4502 #endif 4503 /* Create interpolated mesh */ 4504 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 4505 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4506 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4507 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4508 for (c = 0; c < numCells; ++c) { 4509 PetscInt numCorners; 4510 4511 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4512 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4513 } 4514 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4515 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4516 } 4517 ierr = DMSetUp(idm);CHKERRQ(ierr); 4518 /* Get edge cones from subsets of cell vertices */ 4519 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4520 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4521 4522 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4523 const PetscInt *cellFaces; 4524 PetscInt numCellFaces, faceSize, cf; 4525 4526 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4527 if (faceSize != 2) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4528 for (cf = 0; cf < numCellFaces; ++cf) { 4529 #if 1 4530 PetscHashIJKey key; 4531 4532 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4533 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4534 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4535 if (e < 0) { 4536 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4537 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4538 e = edge++; 4539 } 4540 #else 4541 PetscBool found = PETSC_FALSE; 4542 4543 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4544 for (e = firstEdge; e < edge; ++e) { 4545 const PetscInt *cone; 4546 4547 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4548 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4549 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4550 found = PETSC_TRUE; 4551 break; 4552 } 4553 } 4554 if (!found) { 4555 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4556 ++edge; 4557 } 4558 #endif 4559 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4560 } 4561 } 4562 if (edge != firstEdge+numEdges) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4563 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4564 ierr = PetscFree(off);CHKERRQ(ierr); 4565 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4566 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4567 mesh = (DM_Plex*) (idm)->data; 4568 /* Orient edges */ 4569 for (c = 0; c < numCells; ++c) { 4570 const PetscInt *cone = NULL, *cellFaces; 4571 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4572 4573 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4574 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4575 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4576 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4577 if (coneSize != numCellFaces) SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4578 for (cf = 0; cf < numCellFaces; ++cf) { 4579 const PetscInt *econe = NULL; 4580 PetscInt esize; 4581 4582 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4583 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4584 if (esize != 2) SETERRQ2(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4585 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4586 /* Correctly oriented */ 4587 mesh->coneOrientations[coff+cf] = 0; 4588 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4589 /* Start at index 1, and reverse orientation */ 4590 mesh->coneOrientations[coff+cf] = -(1+1); 4591 } 4592 } 4593 } 4594 *dmInt = idm; 4595 PetscFunctionReturn(0); 4596 } 4597 4598 #undef __FUNCT__ 4599 #define __FUNCT__ "DMPlexInterpolate_3D" 4600 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4601 { 4602 DM idm, fdm; 4603 DM_Plex *mesh; 4604 PetscInt *off; 4605 const PetscInt numCorners = 4; 4606 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4607 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4608 PetscErrorCode ierr; 4609 4610 PetscFunctionBegin; 4611 { 4612 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4613 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4614 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4615 } 4616 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4617 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4618 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4619 numCells = cEnd - cStart; 4620 numVertices = vEnd - vStart; 4621 firstFace = numCells + numVertices; 4622 numFaces = 0; 4623 /* Count faces using algorithm from CreateNeighborCSR */ 4624 ierr = DMPlexCreateNeighborCSR(dm, NULL, &off, NULL);CHKERRQ(ierr); 4625 if (off) { 4626 numFaces = off[numCells]/2; 4627 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4628 numFaces += 4*numCells - off[numCells]; 4629 } 4630 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4631 firstEdge = firstFace + numFaces; 4632 numEdges = numVertices + numFaces - numCells - 1; 4633 /* Create interpolated mesh */ 4634 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 4635 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4636 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4637 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4638 for (c = 0; c < numCells; ++c) { 4639 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4640 } 4641 for (f = firstFace; f < firstFace+numFaces; ++f) { 4642 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4643 } 4644 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4645 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4646 } 4647 ierr = DMSetUp(idm);CHKERRQ(ierr); 4648 /* Get face cones from subsets of cell vertices */ 4649 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &fdm);CHKERRQ(ierr); 4650 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4651 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4652 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4653 for (f = firstFace; f < firstFace+numFaces; ++f) { 4654 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4655 } 4656 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4657 for (c = 0, face = firstFace; c < numCells; ++c) { 4658 const PetscInt *cellFaces; 4659 PetscInt numCellFaces, faceSize, cf; 4660 4661 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4662 if (faceSize != 3) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4663 for (cf = 0; cf < numCellFaces; ++cf) { 4664 PetscBool found = PETSC_FALSE; 4665 4666 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4667 for (f = firstFace; f < face; ++f) { 4668 const PetscInt *cone = NULL; 4669 4670 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4671 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4672 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4673 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4674 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4675 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4676 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4677 found = PETSC_TRUE; 4678 break; 4679 } 4680 } 4681 if (!found) { 4682 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4683 /* Save the vertices for orientation calculation */ 4684 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4685 ++face; 4686 } 4687 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4688 } 4689 } 4690 if (face != firstFace+numFaces) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4691 /* Get edge cones from subsets of face vertices */ 4692 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4693 const PetscInt *cellFaces; 4694 PetscInt numCellFaces, faceSize, cf; 4695 4696 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4697 if (faceSize != 2) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4698 for (cf = 0; cf < numCellFaces; ++cf) { 4699 PetscBool found = PETSC_FALSE; 4700 4701 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4702 for (e = firstEdge; e < edge; ++e) { 4703 const PetscInt *cone = NULL; 4704 4705 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4706 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4707 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4708 found = PETSC_TRUE; 4709 break; 4710 } 4711 } 4712 if (!found) { 4713 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4714 ++edge; 4715 } 4716 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4717 } 4718 } 4719 if (edge != firstEdge+numEdges) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4720 ierr = PetscFree(off);CHKERRQ(ierr); 4721 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4722 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4723 mesh = (DM_Plex*) (idm)->data; 4724 /* Orient edges */ 4725 for (f = firstFace; f < firstFace+numFaces; ++f) { 4726 const PetscInt *cone, *cellFaces; 4727 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4728 4729 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4730 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4731 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4732 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4733 if (coneSize != numCellFaces) SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4734 for (cf = 0; cf < numCellFaces; ++cf) { 4735 const PetscInt *econe; 4736 PetscInt esize; 4737 4738 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4739 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4740 if (esize != 2) SETERRQ2(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4741 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4742 /* Correctly oriented */ 4743 mesh->coneOrientations[coff+cf] = 0; 4744 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4745 /* Start at index 1, and reverse orientation */ 4746 mesh->coneOrientations[coff+cf] = -(1+1); 4747 } 4748 } 4749 } 4750 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4751 /* Orient faces */ 4752 for (c = 0; c < numCells; ++c) { 4753 const PetscInt *cone, *cellFaces; 4754 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4755 4756 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4757 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4758 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4759 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4760 if (coneSize != numCellFaces) SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4761 for (cf = 0; cf < numCellFaces; ++cf) { 4762 PetscInt *origClosure = NULL, *closure; 4763 PetscInt closureSize, i; 4764 4765 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4766 if (closureSize != 7) SETERRQ2(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4767 for (i = 4; i < 7; ++i) { 4768 if ((origClosure[i*2] < vStart) || (origClosure[i*2] >= vEnd)) SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid closure point %D should be a vertex in [%D, %D)", origClosure[i*2], vStart, vEnd); 4769 } 4770 closure = &origClosure[4*2]; 4771 /* Remember that this is the orientation for edges, not vertices */ 4772 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4773 /* Correctly oriented */ 4774 mesh->coneOrientations[coff+cf] = 0; 4775 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4776 /* Shifted by 1 */ 4777 mesh->coneOrientations[coff+cf] = 1; 4778 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4779 /* Shifted by 2 */ 4780 mesh->coneOrientations[coff+cf] = 2; 4781 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4782 /* Start at edge 1, and reverse orientation */ 4783 mesh->coneOrientations[coff+cf] = -(1+1); 4784 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4785 /* Start at index 0, and reverse orientation */ 4786 mesh->coneOrientations[coff+cf] = -(0+1); 4787 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4788 /* Start at index 2, and reverse orientation */ 4789 mesh->coneOrientations[coff+cf] = -(2+1); 4790 } else SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Face %D did not match local face %D in cell %D for any orientation", cone[cf], cf, c); 4791 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4792 } 4793 } 4794 { 4795 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4796 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4797 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4798 } 4799 *dmInt = idm; 4800 PetscFunctionReturn(0); 4801 } 4802 4803 #undef __FUNCT__ 4804 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4805 /* 4806 This takes as input the common mesh generator output, a list of the vertices for each cell 4807 */ 4808 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4809 { 4810 PetscInt *cone, c, p; 4811 PetscErrorCode ierr; 4812 4813 PetscFunctionBegin; 4814 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4815 for (c = 0; c < numCells; ++c) { 4816 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4817 } 4818 ierr = DMSetUp(dm);CHKERRQ(ierr); 4819 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4820 for (c = 0; c < numCells; ++c) { 4821 for (p = 0; p < numCorners; ++p) { 4822 cone[p] = cells[c*numCorners+p]+numCells; 4823 } 4824 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4825 } 4826 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4827 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4828 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4829 PetscFunctionReturn(0); 4830 } 4831 4832 #undef __FUNCT__ 4833 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4834 /* 4835 This takes as input the coordinates for each vertex 4836 */ 4837 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4838 { 4839 PetscSection coordSection; 4840 Vec coordinates; 4841 PetscScalar *coords; 4842 PetscInt coordSize, v, d; 4843 PetscErrorCode ierr; 4844 4845 PetscFunctionBegin; 4846 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4847 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4848 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4849 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4850 for (v = numCells; v < numCells+numVertices; ++v) { 4851 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4852 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4853 } 4854 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4855 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4856 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4857 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4858 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4859 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4860 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4861 for (v = 0; v < numVertices; ++v) { 4862 for (d = 0; d < spaceDim; ++d) { 4863 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4864 } 4865 } 4866 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4867 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4868 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4869 PetscFunctionReturn(0); 4870 } 4871 4872 #undef __FUNCT__ 4873 #define __FUNCT__ "DMPlexCreateFromCellList" 4874 /* 4875 This takes as input the common mesh generator output, a list of the vertices for each cell 4876 */ 4877 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4878 { 4879 PetscErrorCode ierr; 4880 4881 PetscFunctionBegin; 4882 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4883 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4884 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4885 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4886 if (interpolate) { 4887 DM idm; 4888 4889 switch (dim) { 4890 case 2: 4891 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4892 case 3: 4893 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4894 default: 4895 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4896 } 4897 ierr = DMDestroy(dm);CHKERRQ(ierr); 4898 *dm = idm; 4899 } 4900 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4901 PetscFunctionReturn(0); 4902 } 4903 4904 #if defined(PETSC_HAVE_TRIANGLE) 4905 #include <triangle.h> 4906 4907 #undef __FUNCT__ 4908 #define __FUNCT__ "InitInput_Triangle" 4909 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4910 { 4911 PetscFunctionBegin; 4912 inputCtx->numberofpoints = 0; 4913 inputCtx->numberofpointattributes = 0; 4914 inputCtx->pointlist = NULL; 4915 inputCtx->pointattributelist = NULL; 4916 inputCtx->pointmarkerlist = NULL; 4917 inputCtx->numberofsegments = 0; 4918 inputCtx->segmentlist = NULL; 4919 inputCtx->segmentmarkerlist = NULL; 4920 inputCtx->numberoftriangleattributes = 0; 4921 inputCtx->trianglelist = NULL; 4922 inputCtx->numberofholes = 0; 4923 inputCtx->holelist = NULL; 4924 inputCtx->numberofregions = 0; 4925 inputCtx->regionlist = NULL; 4926 PetscFunctionReturn(0); 4927 } 4928 4929 #undef __FUNCT__ 4930 #define __FUNCT__ "InitOutput_Triangle" 4931 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4932 { 4933 PetscFunctionBegin; 4934 outputCtx->numberofpoints = 0; 4935 outputCtx->pointlist = NULL; 4936 outputCtx->pointattributelist = NULL; 4937 outputCtx->pointmarkerlist = NULL; 4938 outputCtx->numberoftriangles = 0; 4939 outputCtx->trianglelist = NULL; 4940 outputCtx->triangleattributelist = NULL; 4941 outputCtx->neighborlist = NULL; 4942 outputCtx->segmentlist = NULL; 4943 outputCtx->segmentmarkerlist = NULL; 4944 outputCtx->numberofedges = 0; 4945 outputCtx->edgelist = NULL; 4946 outputCtx->edgemarkerlist = NULL; 4947 PetscFunctionReturn(0); 4948 } 4949 4950 #undef __FUNCT__ 4951 #define __FUNCT__ "FiniOutput_Triangle" 4952 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4953 { 4954 PetscFunctionBegin; 4955 free(outputCtx->pointmarkerlist); 4956 free(outputCtx->edgelist); 4957 free(outputCtx->edgemarkerlist); 4958 free(outputCtx->trianglelist); 4959 free(outputCtx->neighborlist); 4960 PetscFunctionReturn(0); 4961 } 4962 4963 #undef __FUNCT__ 4964 #define __FUNCT__ "DMPlexGenerate_Triangle" 4965 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4966 { 4967 MPI_Comm comm; 4968 PetscInt dim = 2; 4969 const PetscBool createConvexHull = PETSC_FALSE; 4970 const PetscBool constrained = PETSC_FALSE; 4971 struct triangulateio in; 4972 struct triangulateio out; 4973 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4974 PetscMPIInt rank; 4975 PetscErrorCode ierr; 4976 4977 PetscFunctionBegin; 4978 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4979 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4980 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4981 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4982 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4983 4984 in.numberofpoints = vEnd - vStart; 4985 if (in.numberofpoints > 0) { 4986 PetscSection coordSection; 4987 Vec coordinates; 4988 PetscScalar *array; 4989 4990 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4991 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4992 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4993 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4994 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4995 for (v = vStart; v < vEnd; ++v) { 4996 const PetscInt idx = v - vStart; 4997 PetscInt off, d; 4998 4999 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5000 for (d = 0; d < dim; ++d) { 5001 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5002 } 5003 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5004 } 5005 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5006 } 5007 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 5008 in.numberofsegments = eEnd - eStart; 5009 if (in.numberofsegments > 0) { 5010 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 5011 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 5012 for (e = eStart; e < eEnd; ++e) { 5013 const PetscInt idx = e - eStart; 5014 const PetscInt *cone; 5015 5016 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 5017 5018 in.segmentlist[idx*2+0] = cone[0] - vStart; 5019 in.segmentlist[idx*2+1] = cone[1] - vStart; 5020 5021 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5022 } 5023 } 5024 #if 0 /* Do not currently support holes */ 5025 PetscReal *holeCoords; 5026 PetscInt h, d; 5027 5028 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5029 if (in.numberofholes > 0) { 5030 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5031 for (h = 0; h < in.numberofholes; ++h) { 5032 for (d = 0; d < dim; ++d) { 5033 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5034 } 5035 } 5036 } 5037 #endif 5038 if (!rank) { 5039 char args[32]; 5040 5041 /* Take away 'Q' for verbose output */ 5042 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5043 if (createConvexHull) { 5044 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5045 } 5046 if (constrained) { 5047 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5048 } 5049 triangulate(args, &in, &out, NULL); 5050 } 5051 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5052 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5053 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5054 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5055 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5056 5057 { 5058 const PetscInt numCorners = 3; 5059 const PetscInt numCells = out.numberoftriangles; 5060 const PetscInt numVertices = out.numberofpoints; 5061 const int *cells = out.trianglelist; 5062 const double *meshCoords = out.pointlist; 5063 5064 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5065 /* Set labels */ 5066 for (v = 0; v < numVertices; ++v) { 5067 if (out.pointmarkerlist[v]) { 5068 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5069 } 5070 } 5071 if (interpolate) { 5072 for (e = 0; e < out.numberofedges; e++) { 5073 if (out.edgemarkerlist[e]) { 5074 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5075 const PetscInt *edges; 5076 PetscInt numEdges; 5077 5078 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5079 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5080 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5081 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5082 } 5083 } 5084 } 5085 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5086 } 5087 #if 0 /* Do not currently support holes */ 5088 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5089 #endif 5090 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5091 PetscFunctionReturn(0); 5092 } 5093 5094 #undef __FUNCT__ 5095 #define __FUNCT__ "DMPlexRefine_Triangle" 5096 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5097 { 5098 MPI_Comm comm; 5099 PetscInt dim = 2; 5100 struct triangulateio in; 5101 struct triangulateio out; 5102 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5103 PetscMPIInt rank; 5104 PetscErrorCode ierr; 5105 5106 PetscFunctionBegin; 5107 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5108 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5109 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5110 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5111 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5112 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5113 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5114 5115 in.numberofpoints = vEnd - vStart; 5116 if (in.numberofpoints > 0) { 5117 PetscSection coordSection; 5118 Vec coordinates; 5119 PetscScalar *array; 5120 5121 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5122 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5123 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5124 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5125 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5126 for (v = vStart; v < vEnd; ++v) { 5127 const PetscInt idx = v - vStart; 5128 PetscInt off, d; 5129 5130 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5131 for (d = 0; d < dim; ++d) { 5132 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5133 } 5134 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5135 } 5136 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5137 } 5138 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5139 5140 in.numberofcorners = 3; 5141 in.numberoftriangles = cEnd - cStart; 5142 5143 in.trianglearealist = (double*) maxVolumes; 5144 if (in.numberoftriangles > 0) { 5145 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5146 for (c = cStart; c < cEnd; ++c) { 5147 const PetscInt idx = c - cStart; 5148 PetscInt *closure = NULL; 5149 PetscInt closureSize; 5150 5151 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5152 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5153 for (v = 0; v < 3; ++v) { 5154 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5155 } 5156 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5157 } 5158 } 5159 /* TODO: Segment markers are missing on input */ 5160 #if 0 /* Do not currently support holes */ 5161 PetscReal *holeCoords; 5162 PetscInt h, d; 5163 5164 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5165 if (in.numberofholes > 0) { 5166 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5167 for (h = 0; h < in.numberofholes; ++h) { 5168 for (d = 0; d < dim; ++d) { 5169 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5170 } 5171 } 5172 } 5173 #endif 5174 if (!rank) { 5175 char args[32]; 5176 5177 /* Take away 'Q' for verbose output */ 5178 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5179 triangulate(args, &in, &out, NULL); 5180 } 5181 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5182 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5183 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5184 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5185 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5186 5187 { 5188 const PetscInt numCorners = 3; 5189 const PetscInt numCells = out.numberoftriangles; 5190 const PetscInt numVertices = out.numberofpoints; 5191 const int *cells = out.trianglelist; 5192 const double *meshCoords = out.pointlist; 5193 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5194 5195 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5196 /* Set labels */ 5197 for (v = 0; v < numVertices; ++v) { 5198 if (out.pointmarkerlist[v]) { 5199 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5200 } 5201 } 5202 if (interpolate) { 5203 PetscInt e; 5204 5205 for (e = 0; e < out.numberofedges; e++) { 5206 if (out.edgemarkerlist[e]) { 5207 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5208 const PetscInt *edges; 5209 PetscInt numEdges; 5210 5211 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5212 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5213 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5214 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5215 } 5216 } 5217 } 5218 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5219 } 5220 #if 0 /* Do not currently support holes */ 5221 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5222 #endif 5223 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5224 PetscFunctionReturn(0); 5225 } 5226 #endif 5227 5228 #if defined(PETSC_HAVE_TETGEN) 5229 #include <tetgen.h> 5230 #undef __FUNCT__ 5231 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5232 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5233 { 5234 MPI_Comm comm; 5235 const PetscInt dim = 3; 5236 ::tetgenio in; 5237 ::tetgenio out; 5238 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5239 PetscMPIInt rank; 5240 PetscErrorCode ierr; 5241 5242 PetscFunctionBegin; 5243 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5244 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5245 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5246 in.numberofpoints = vEnd - vStart; 5247 if (in.numberofpoints > 0) { 5248 PetscSection coordSection; 5249 Vec coordinates; 5250 PetscScalar *array; 5251 5252 in.pointlist = new double[in.numberofpoints*dim]; 5253 in.pointmarkerlist = new int[in.numberofpoints]; 5254 5255 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5256 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5257 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5258 for (v = vStart; v < vEnd; ++v) { 5259 const PetscInt idx = v - vStart; 5260 PetscInt off, d; 5261 5262 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5263 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5264 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5265 } 5266 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5267 } 5268 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5269 5270 in.numberoffacets = fEnd - fStart; 5271 if (in.numberoffacets > 0) { 5272 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5273 in.facetmarkerlist = new int[in.numberoffacets]; 5274 for (f = fStart; f < fEnd; ++f) { 5275 const PetscInt idx = f - fStart; 5276 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 5277 5278 in.facetlist[idx].numberofpolygons = 1; 5279 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5280 in.facetlist[idx].numberofholes = 0; 5281 in.facetlist[idx].holelist = NULL; 5282 5283 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5284 for (p = 0; p < numPoints*2; p += 2) { 5285 const PetscInt point = points[p]; 5286 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5287 } 5288 5289 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5290 poly->numberofvertices = numVertices; 5291 poly->vertexlist = new int[poly->numberofvertices]; 5292 for (v = 0; v < numVertices; ++v) { 5293 const PetscInt vIdx = points[v] - vStart; 5294 poly->vertexlist[v] = vIdx; 5295 } 5296 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5297 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5298 } 5299 } 5300 if (!rank) { 5301 char args[32]; 5302 5303 /* Take away 'Q' for verbose output */ 5304 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5305 ::tetrahedralize(args, &in, &out); 5306 } 5307 { 5308 const PetscInt numCorners = 4; 5309 const PetscInt numCells = out.numberoftetrahedra; 5310 const PetscInt numVertices = out.numberofpoints; 5311 const int *cells = out.tetrahedronlist; 5312 const double *meshCoords = out.pointlist; 5313 5314 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5315 /* Set labels */ 5316 for (v = 0; v < numVertices; ++v) { 5317 if (out.pointmarkerlist[v]) { 5318 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5319 } 5320 } 5321 if (interpolate) { 5322 PetscInt e; 5323 5324 for (e = 0; e < out.numberofedges; e++) { 5325 if (out.edgemarkerlist[e]) { 5326 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5327 const PetscInt *edges; 5328 PetscInt numEdges; 5329 5330 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5331 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5332 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5333 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5334 } 5335 } 5336 for (f = 0; f < out.numberoftrifaces; f++) { 5337 if (out.trifacemarkerlist[f]) { 5338 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5339 const PetscInt *faces; 5340 PetscInt numFaces; 5341 5342 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5343 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5344 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5345 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5346 } 5347 } 5348 } 5349 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5350 } 5351 PetscFunctionReturn(0); 5352 } 5353 5354 #undef __FUNCT__ 5355 #define __FUNCT__ "DMPlexRefine_Tetgen" 5356 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5357 { 5358 MPI_Comm comm; 5359 const PetscInt dim = 3; 5360 ::tetgenio in; 5361 ::tetgenio out; 5362 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5363 PetscMPIInt rank; 5364 PetscErrorCode ierr; 5365 5366 PetscFunctionBegin; 5367 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5368 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5369 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5370 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5371 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5372 5373 in.numberofpoints = vEnd - vStart; 5374 if (in.numberofpoints > 0) { 5375 PetscSection coordSection; 5376 Vec coordinates; 5377 PetscScalar *array; 5378 5379 in.pointlist = new double[in.numberofpoints*dim]; 5380 in.pointmarkerlist = new int[in.numberofpoints]; 5381 5382 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5383 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5384 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5385 for (v = vStart; v < vEnd; ++v) { 5386 const PetscInt idx = v - vStart; 5387 PetscInt off, d; 5388 5389 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5390 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5391 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5392 } 5393 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5394 } 5395 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5396 5397 in.numberofcorners = 4; 5398 in.numberoftetrahedra = cEnd - cStart; 5399 in.tetrahedronvolumelist = (double*) maxVolumes; 5400 if (in.numberoftetrahedra > 0) { 5401 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5402 for (c = cStart; c < cEnd; ++c) { 5403 const PetscInt idx = c - cStart; 5404 PetscInt *closure = NULL; 5405 PetscInt closureSize; 5406 5407 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5408 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5409 for (v = 0; v < 4; ++v) { 5410 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5411 } 5412 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5413 } 5414 } 5415 /* TODO: Put in boundary faces with markers */ 5416 if (!rank) { 5417 char args[32]; 5418 5419 /* Take away 'Q' for verbose output */ 5420 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5421 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5422 ::tetrahedralize(args, &in, &out); 5423 } 5424 in.tetrahedronvolumelist = NULL; 5425 5426 { 5427 const PetscInt numCorners = 4; 5428 const PetscInt numCells = out.numberoftetrahedra; 5429 const PetscInt numVertices = out.numberofpoints; 5430 const int *cells = out.tetrahedronlist; 5431 const double *meshCoords = out.pointlist; 5432 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5433 5434 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5435 /* Set labels */ 5436 for (v = 0; v < numVertices; ++v) { 5437 if (out.pointmarkerlist[v]) { 5438 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5439 } 5440 } 5441 if (interpolate) { 5442 PetscInt e, f; 5443 5444 for (e = 0; e < out.numberofedges; e++) { 5445 if (out.edgemarkerlist[e]) { 5446 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5447 const PetscInt *edges; 5448 PetscInt numEdges; 5449 5450 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5451 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5452 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5453 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5454 } 5455 } 5456 for (f = 0; f < out.numberoftrifaces; f++) { 5457 if (out.trifacemarkerlist[f]) { 5458 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5459 const PetscInt *faces; 5460 PetscInt numFaces; 5461 5462 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5463 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5464 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5465 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5466 } 5467 } 5468 } 5469 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5470 } 5471 PetscFunctionReturn(0); 5472 } 5473 #endif 5474 5475 #if defined(PETSC_HAVE_CTETGEN) 5476 #include "ctetgen.h" 5477 5478 #undef __FUNCT__ 5479 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5480 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5481 { 5482 MPI_Comm comm; 5483 const PetscInt dim = 3; 5484 PLC *in, *out; 5485 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5486 PetscMPIInt rank; 5487 PetscErrorCode ierr; 5488 5489 PetscFunctionBegin; 5490 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5491 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5492 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5493 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5494 ierr = PLCCreate(&in);CHKERRQ(ierr); 5495 ierr = PLCCreate(&out);CHKERRQ(ierr); 5496 5497 in->numberofpoints = vEnd - vStart; 5498 if (in->numberofpoints > 0) { 5499 PetscSection coordSection; 5500 Vec coordinates; 5501 PetscScalar *array; 5502 5503 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5504 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5505 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5506 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5507 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5508 for (v = vStart; v < vEnd; ++v) { 5509 const PetscInt idx = v - vStart; 5510 PetscInt off, d, m; 5511 5512 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5513 for (d = 0; d < dim; ++d) { 5514 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5515 } 5516 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5517 5518 in->pointmarkerlist[idx] = (int) m; 5519 } 5520 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5521 } 5522 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5523 5524 in->numberoffacets = fEnd - fStart; 5525 if (in->numberoffacets > 0) { 5526 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5527 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5528 for (f = fStart; f < fEnd; ++f) { 5529 const PetscInt idx = f - fStart; 5530 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5531 polygon *poly; 5532 5533 in->facetlist[idx].numberofpolygons = 1; 5534 5535 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5536 5537 in->facetlist[idx].numberofholes = 0; 5538 in->facetlist[idx].holelist = NULL; 5539 5540 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5541 for (p = 0; p < numPoints*2; p += 2) { 5542 const PetscInt point = points[p]; 5543 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5544 } 5545 5546 poly = in->facetlist[idx].polygonlist; 5547 poly->numberofvertices = numVertices; 5548 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5549 for (v = 0; v < numVertices; ++v) { 5550 const PetscInt vIdx = points[v] - vStart; 5551 poly->vertexlist[v] = vIdx; 5552 } 5553 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5554 in->facetmarkerlist[idx] = (int) m; 5555 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5556 } 5557 } 5558 if (!rank) { 5559 TetGenOpts t; 5560 5561 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5562 t.in = boundary; /* Should go away */ 5563 t.plc = 1; 5564 t.quality = 1; 5565 t.edgesout = 1; 5566 t.zeroindex = 1; 5567 t.quiet = 1; 5568 t.verbose = verbose; 5569 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5570 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5571 } 5572 { 5573 const PetscInt numCorners = 4; 5574 const PetscInt numCells = out->numberoftetrahedra; 5575 const PetscInt numVertices = out->numberofpoints; 5576 const int *cells = out->tetrahedronlist; 5577 const double *meshCoords = out->pointlist; 5578 5579 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5580 /* Set labels */ 5581 for (v = 0; v < numVertices; ++v) { 5582 if (out->pointmarkerlist[v]) { 5583 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5584 } 5585 } 5586 if (interpolate) { 5587 PetscInt e; 5588 5589 for (e = 0; e < out->numberofedges; e++) { 5590 if (out->edgemarkerlist[e]) { 5591 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5592 const PetscInt *edges; 5593 PetscInt numEdges; 5594 5595 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5596 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5597 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5598 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5599 } 5600 } 5601 for (f = 0; f < out->numberoftrifaces; f++) { 5602 if (out->trifacemarkerlist[f]) { 5603 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5604 const PetscInt *faces; 5605 PetscInt numFaces; 5606 5607 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5608 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5609 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5610 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5611 } 5612 } 5613 } 5614 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5615 } 5616 5617 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5618 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5619 PetscFunctionReturn(0); 5620 } 5621 5622 #undef __FUNCT__ 5623 #define __FUNCT__ "DMPlexRefine_CTetgen" 5624 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5625 { 5626 MPI_Comm comm; 5627 const PetscInt dim = 3; 5628 PLC *in, *out; 5629 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5630 PetscMPIInt rank; 5631 PetscErrorCode ierr; 5632 5633 PetscFunctionBegin; 5634 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5635 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5636 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5637 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5638 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5639 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5640 ierr = PLCCreate(&in);CHKERRQ(ierr); 5641 ierr = PLCCreate(&out);CHKERRQ(ierr); 5642 5643 in->numberofpoints = vEnd - vStart; 5644 if (in->numberofpoints > 0) { 5645 PetscSection coordSection; 5646 Vec coordinates; 5647 PetscScalar *array; 5648 5649 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5650 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5651 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5652 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5653 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5654 for (v = vStart; v < vEnd; ++v) { 5655 const PetscInt idx = v - vStart; 5656 PetscInt off, d, m; 5657 5658 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5659 for (d = 0; d < dim; ++d) { 5660 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5661 } 5662 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5663 5664 in->pointmarkerlist[idx] = (int) m; 5665 } 5666 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5667 } 5668 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5669 5670 in->numberofcorners = 4; 5671 in->numberoftetrahedra = cEnd - cStart; 5672 in->tetrahedronvolumelist = maxVolumes; 5673 if (in->numberoftetrahedra > 0) { 5674 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5675 for (c = cStart; c < cEnd; ++c) { 5676 const PetscInt idx = c - cStart; 5677 PetscInt *closure = NULL; 5678 PetscInt closureSize; 5679 5680 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5681 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5682 for (v = 0; v < 4; ++v) { 5683 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5684 } 5685 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5686 } 5687 } 5688 if (!rank) { 5689 TetGenOpts t; 5690 5691 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5692 5693 t.in = dm; /* Should go away */ 5694 t.refine = 1; 5695 t.varvolume = 1; 5696 t.quality = 1; 5697 t.edgesout = 1; 5698 t.zeroindex = 1; 5699 t.quiet = 1; 5700 t.verbose = verbose; /* Change this */ 5701 5702 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5703 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5704 } 5705 { 5706 const PetscInt numCorners = 4; 5707 const PetscInt numCells = out->numberoftetrahedra; 5708 const PetscInt numVertices = out->numberofpoints; 5709 const int *cells = out->tetrahedronlist; 5710 const double *meshCoords = out->pointlist; 5711 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5712 5713 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5714 /* Set labels */ 5715 for (v = 0; v < numVertices; ++v) { 5716 if (out->pointmarkerlist[v]) { 5717 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5718 } 5719 } 5720 if (interpolate) { 5721 PetscInt e, f; 5722 5723 for (e = 0; e < out->numberofedges; e++) { 5724 if (out->edgemarkerlist[e]) { 5725 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5726 const PetscInt *edges; 5727 PetscInt numEdges; 5728 5729 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5730 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5731 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5732 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5733 } 5734 } 5735 for (f = 0; f < out->numberoftrifaces; f++) { 5736 if (out->trifacemarkerlist[f]) { 5737 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5738 const PetscInt *faces; 5739 PetscInt numFaces; 5740 5741 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5742 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5743 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5744 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5745 } 5746 } 5747 } 5748 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5749 } 5750 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5751 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5752 PetscFunctionReturn(0); 5753 } 5754 #endif 5755 5756 #undef __FUNCT__ 5757 #define __FUNCT__ "DMPlexGenerate" 5758 /*@C 5759 DMPlexGenerate - Generates a mesh. 5760 5761 Not Collective 5762 5763 Input Parameters: 5764 + boundary - The DMPlex boundary object 5765 . name - The mesh generation package name 5766 - interpolate - Flag to create intermediate mesh elements 5767 5768 Output Parameter: 5769 . mesh - The DMPlex object 5770 5771 Level: intermediate 5772 5773 .keywords: mesh, elements 5774 .seealso: DMPlexCreate(), DMRefine() 5775 @*/ 5776 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5777 { 5778 PetscInt dim; 5779 char genname[1024]; 5780 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5781 PetscErrorCode ierr; 5782 5783 PetscFunctionBegin; 5784 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5785 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5786 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5787 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5788 if (flg) name = genname; 5789 if (name) { 5790 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5791 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5792 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5793 } 5794 switch (dim) { 5795 case 1: 5796 if (!name || isTriangle) { 5797 #if defined(PETSC_HAVE_TRIANGLE) 5798 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5799 #else 5800 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5801 #endif 5802 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5803 break; 5804 case 2: 5805 if (!name || isCTetgen) { 5806 #if defined(PETSC_HAVE_CTETGEN) 5807 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5808 #else 5809 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5810 #endif 5811 } else if (isTetgen) { 5812 #if defined(PETSC_HAVE_TETGEN) 5813 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5814 #else 5815 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5816 #endif 5817 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5818 break; 5819 default: 5820 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5821 } 5822 PetscFunctionReturn(0); 5823 } 5824 5825 typedef PetscInt CellRefiner; 5826 5827 #undef __FUNCT__ 5828 #define __FUNCT__ "GetDepthStart_Private" 5829 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5830 { 5831 PetscFunctionBegin; 5832 if (cStart) *cStart = 0; 5833 if (vStart) *vStart = depthSize[depth]; 5834 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5835 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5836 PetscFunctionReturn(0); 5837 } 5838 5839 #undef __FUNCT__ 5840 #define __FUNCT__ "GetDepthEnd_Private" 5841 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5842 { 5843 PetscFunctionBegin; 5844 if (cEnd) *cEnd = depthSize[depth]; 5845 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5846 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5847 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5848 PetscFunctionReturn(0); 5849 } 5850 5851 #undef __FUNCT__ 5852 #define __FUNCT__ "CellRefinerGetSizes" 5853 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5854 { 5855 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5856 PetscErrorCode ierr; 5857 5858 PetscFunctionBegin; 5859 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5860 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5861 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5862 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5863 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5864 switch (refiner) { 5865 case 1: 5866 /* Simplicial 2D */ 5867 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5868 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5869 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5870 break; 5871 case 3: 5872 /* Hybrid 2D */ 5873 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5874 cMax = PetscMin(cEnd, cMax); 5875 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5876 fMax = PetscMin(fEnd, fMax); 5877 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5878 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 */ 5879 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5880 break; 5881 case 2: 5882 /* Hex 2D */ 5883 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5884 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5885 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5886 break; 5887 default: 5888 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5889 } 5890 PetscFunctionReturn(0); 5891 } 5892 5893 #undef __FUNCT__ 5894 #define __FUNCT__ "CellRefinerSetConeSizes" 5895 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5896 { 5897 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5898 PetscErrorCode ierr; 5899 5900 PetscFunctionBegin; 5901 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5902 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5903 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5904 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5905 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5906 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5907 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5908 switch (refiner) { 5909 case 1: 5910 /* Simplicial 2D */ 5911 /* All cells have 3 faces */ 5912 for (c = cStart; c < cEnd; ++c) { 5913 for (r = 0; r < 4; ++r) { 5914 const PetscInt newp = (c - cStart)*4 + r; 5915 5916 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5917 } 5918 } 5919 /* Split faces have 2 vertices and the same cells as the parent */ 5920 for (f = fStart; f < fEnd; ++f) { 5921 for (r = 0; r < 2; ++r) { 5922 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5923 PetscInt size; 5924 5925 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5926 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5927 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5928 } 5929 } 5930 /* Interior faces have 2 vertices and 2 cells */ 5931 for (c = cStart; c < cEnd; ++c) { 5932 for (r = 0; r < 3; ++r) { 5933 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5934 5935 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5936 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5937 } 5938 } 5939 /* Old vertices have identical supports */ 5940 for (v = vStart; v < vEnd; ++v) { 5941 const PetscInt newp = vStartNew + (v - vStart); 5942 PetscInt size; 5943 5944 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5945 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5946 } 5947 /* Face vertices have 2 + cells*2 supports */ 5948 for (f = fStart; f < fEnd; ++f) { 5949 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5950 PetscInt size; 5951 5952 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5953 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5954 } 5955 break; 5956 case 2: 5957 /* Hex 2D */ 5958 /* All cells have 4 faces */ 5959 for (c = cStart; c < cEnd; ++c) { 5960 for (r = 0; r < 4; ++r) { 5961 const PetscInt newp = (c - cStart)*4 + r; 5962 5963 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5964 } 5965 } 5966 /* Split faces have 2 vertices and the same cells as the parent */ 5967 for (f = fStart; f < fEnd; ++f) { 5968 for (r = 0; r < 2; ++r) { 5969 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5970 PetscInt size; 5971 5972 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5973 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5974 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5975 } 5976 } 5977 /* Interior faces have 2 vertices and 2 cells */ 5978 for (c = cStart; c < cEnd; ++c) { 5979 for (r = 0; r < 4; ++r) { 5980 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5981 5982 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5983 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5984 } 5985 } 5986 /* Old vertices have identical supports */ 5987 for (v = vStart; v < vEnd; ++v) { 5988 const PetscInt newp = vStartNew + (v - vStart); 5989 PetscInt size; 5990 5991 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5992 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5993 } 5994 /* Face vertices have 2 + cells supports */ 5995 for (f = fStart; f < fEnd; ++f) { 5996 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5997 PetscInt size; 5998 5999 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6000 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 6001 } 6002 /* Cell vertices have 4 supports */ 6003 for (c = cStart; c < cEnd; ++c) { 6004 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6005 6006 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 6007 } 6008 break; 6009 case 3: 6010 /* Hybrid 2D */ 6011 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6012 cMax = PetscMin(cEnd, cMax); 6013 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6014 fMax = PetscMin(fEnd, fMax); 6015 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6016 /* Interior cells have 3 faces */ 6017 for (c = cStart; c < cMax; ++c) { 6018 for (r = 0; r < 4; ++r) { 6019 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 6020 6021 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 6022 } 6023 } 6024 /* Hybrid cells have 4 faces */ 6025 for (c = cMax; c < cEnd; ++c) { 6026 for (r = 0; r < 2; ++r) { 6027 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6028 6029 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6030 } 6031 } 6032 /* Interior split faces have 2 vertices and the same cells as the parent */ 6033 for (f = fStart; f < fMax; ++f) { 6034 for (r = 0; r < 2; ++r) { 6035 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6036 PetscInt size; 6037 6038 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6039 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6040 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6041 } 6042 } 6043 /* Interior cell faces have 2 vertices and 2 cells */ 6044 for (c = cStart; c < cMax; ++c) { 6045 for (r = 0; r < 3; ++r) { 6046 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6047 6048 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6049 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6050 } 6051 } 6052 /* Hybrid faces have 2 vertices and the same cells */ 6053 for (f = fMax; f < fEnd; ++f) { 6054 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6055 PetscInt size; 6056 6057 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6058 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6059 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6060 } 6061 /* Hybrid cell faces have 2 vertices and 2 cells */ 6062 for (c = cMax; c < cEnd; ++c) { 6063 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6064 6065 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6066 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6067 } 6068 /* Old vertices have identical supports */ 6069 for (v = vStart; v < vEnd; ++v) { 6070 const PetscInt newp = vStartNew + (v - vStart); 6071 PetscInt size; 6072 6073 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6074 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6075 } 6076 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6077 for (f = fStart; f < fMax; ++f) { 6078 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6079 const PetscInt *support; 6080 PetscInt size, newSize = 2, s; 6081 6082 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6083 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6084 for (s = 0; s < size; ++s) { 6085 if (support[s] >= cMax) newSize += 1; 6086 else newSize += 2; 6087 } 6088 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6089 } 6090 break; 6091 default: 6092 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6093 } 6094 PetscFunctionReturn(0); 6095 } 6096 6097 #undef __FUNCT__ 6098 #define __FUNCT__ "CellRefinerSetCones" 6099 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6100 { 6101 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; 6102 PetscInt maxSupportSize, *supportRef; 6103 PetscErrorCode ierr; 6104 6105 PetscFunctionBegin; 6106 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6107 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6108 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6109 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6110 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6111 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6112 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6113 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6114 switch (refiner) { 6115 case 1: 6116 /* Simplicial 2D */ 6117 /* 6118 2 6119 |\ 6120 | \ 6121 | \ 6122 | \ 6123 | C \ 6124 | \ 6125 | \ 6126 2---1---1 6127 |\ D / \ 6128 | 2 0 \ 6129 |A \ / B \ 6130 0---0-------1 6131 */ 6132 /* All cells have 3 faces */ 6133 for (c = cStart; c < cEnd; ++c) { 6134 const PetscInt newp = cStartNew + (c - cStart)*4; 6135 const PetscInt *cone, *ornt; 6136 PetscInt coneNew[3], orntNew[3]; 6137 6138 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6139 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6140 /* A triangle */ 6141 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6142 orntNew[0] = ornt[0]; 6143 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6144 orntNew[1] = -2; 6145 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6146 orntNew[2] = ornt[2]; 6147 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6148 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6149 #if 1 6150 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); 6151 for (p = 0; p < 3; ++p) { 6152 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); 6153 } 6154 #endif 6155 /* B triangle */ 6156 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6157 orntNew[0] = ornt[0]; 6158 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6159 orntNew[1] = ornt[1]; 6160 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6161 orntNew[2] = -2; 6162 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6163 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6164 #if 1 6165 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); 6166 for (p = 0; p < 3; ++p) { 6167 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); 6168 } 6169 #endif 6170 /* C triangle */ 6171 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6172 orntNew[0] = -2; 6173 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6174 orntNew[1] = ornt[1]; 6175 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6176 orntNew[2] = ornt[2]; 6177 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6178 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6179 #if 1 6180 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); 6181 for (p = 0; p < 3; ++p) { 6182 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); 6183 } 6184 #endif 6185 /* D triangle */ 6186 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6187 orntNew[0] = 0; 6188 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6189 orntNew[1] = 0; 6190 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6191 orntNew[2] = 0; 6192 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6193 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6194 #if 1 6195 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); 6196 for (p = 0; p < 3; ++p) { 6197 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); 6198 } 6199 #endif 6200 } 6201 /* Split faces have 2 vertices and the same cells as the parent */ 6202 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6203 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6204 for (f = fStart; f < fEnd; ++f) { 6205 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6206 6207 for (r = 0; r < 2; ++r) { 6208 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6209 const PetscInt *cone, *support; 6210 PetscInt coneNew[2], coneSize, c, supportSize, s; 6211 6212 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6213 coneNew[0] = vStartNew + (cone[0] - vStart); 6214 coneNew[1] = vStartNew + (cone[1] - vStart); 6215 coneNew[(r+1)%2] = newv; 6216 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6217 #if 1 6218 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6219 for (p = 0; p < 2; ++p) { 6220 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); 6221 } 6222 #endif 6223 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6224 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6225 for (s = 0; s < supportSize; ++s) { 6226 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6227 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6228 for (c = 0; c < coneSize; ++c) { 6229 if (cone[c] == f) break; 6230 } 6231 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6232 } 6233 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6234 #if 1 6235 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6236 for (p = 0; p < supportSize; ++p) { 6237 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); 6238 } 6239 #endif 6240 } 6241 } 6242 /* Interior faces have 2 vertices and 2 cells */ 6243 for (c = cStart; c < cEnd; ++c) { 6244 const PetscInt *cone; 6245 6246 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6247 for (r = 0; r < 3; ++r) { 6248 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6249 PetscInt coneNew[2]; 6250 PetscInt supportNew[2]; 6251 6252 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6253 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6254 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6255 #if 1 6256 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6257 for (p = 0; p < 2; ++p) { 6258 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); 6259 } 6260 #endif 6261 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6262 supportNew[1] = (c - cStart)*4 + 3; 6263 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6264 #if 1 6265 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6266 for (p = 0; p < 2; ++p) { 6267 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); 6268 } 6269 #endif 6270 } 6271 } 6272 /* Old vertices have identical supports */ 6273 for (v = vStart; v < vEnd; ++v) { 6274 const PetscInt newp = vStartNew + (v - vStart); 6275 const PetscInt *support, *cone; 6276 PetscInt size, s; 6277 6278 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6279 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6280 for (s = 0; s < size; ++s) { 6281 PetscInt r = 0; 6282 6283 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6284 if (cone[1] == v) r = 1; 6285 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6286 } 6287 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6288 #if 1 6289 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6290 for (p = 0; p < size; ++p) { 6291 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); 6292 } 6293 #endif 6294 } 6295 /* Face vertices have 2 + cells*2 supports */ 6296 for (f = fStart; f < fEnd; ++f) { 6297 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6298 const PetscInt *cone, *support; 6299 PetscInt size, s; 6300 6301 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6302 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6303 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6304 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6305 for (s = 0; s < size; ++s) { 6306 PetscInt r = 0; 6307 6308 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6309 if (cone[1] == f) r = 1; 6310 else if (cone[2] == f) r = 2; 6311 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6312 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6313 } 6314 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6315 #if 1 6316 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6317 for (p = 0; p < 2+size*2; ++p) { 6318 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); 6319 } 6320 #endif 6321 } 6322 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6323 break; 6324 case 2: 6325 /* Hex 2D */ 6326 /* 6327 3---------2---------2 6328 | | | 6329 | D 2 C | 6330 | | | 6331 3----3----0----1----1 6332 | | | 6333 | A 0 B | 6334 | | | 6335 0---------0---------1 6336 */ 6337 /* All cells have 4 faces */ 6338 for (c = cStart; c < cEnd; ++c) { 6339 const PetscInt newp = (c - cStart)*4; 6340 const PetscInt *cone, *ornt; 6341 PetscInt coneNew[4], orntNew[4]; 6342 6343 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6344 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6345 /* A quad */ 6346 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6347 orntNew[0] = ornt[0]; 6348 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6349 orntNew[1] = 0; 6350 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6351 orntNew[2] = -2; 6352 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6353 orntNew[3] = ornt[3]; 6354 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6355 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6356 #if 1 6357 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); 6358 for (p = 0; p < 4; ++p) { 6359 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); 6360 } 6361 #endif 6362 /* B quad */ 6363 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6364 orntNew[0] = ornt[0]; 6365 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6366 orntNew[1] = ornt[1]; 6367 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6368 orntNew[2] = 0; 6369 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6370 orntNew[3] = -2; 6371 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6372 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6373 #if 1 6374 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); 6375 for (p = 0; p < 4; ++p) { 6376 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); 6377 } 6378 #endif 6379 /* C quad */ 6380 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6381 orntNew[0] = -2; 6382 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6383 orntNew[1] = ornt[1]; 6384 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6385 orntNew[2] = ornt[2]; 6386 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6387 orntNew[3] = 0; 6388 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6389 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6390 #if 1 6391 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); 6392 for (p = 0; p < 4; ++p) { 6393 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); 6394 } 6395 #endif 6396 /* D quad */ 6397 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6398 orntNew[0] = 0; 6399 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6400 orntNew[1] = -2; 6401 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6402 orntNew[2] = ornt[2]; 6403 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6404 orntNew[3] = ornt[3]; 6405 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6406 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6407 #if 1 6408 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); 6409 for (p = 0; p < 4; ++p) { 6410 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); 6411 } 6412 #endif 6413 } 6414 /* Split faces have 2 vertices and the same cells as the parent */ 6415 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6416 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6417 for (f = fStart; f < fEnd; ++f) { 6418 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6419 6420 for (r = 0; r < 2; ++r) { 6421 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6422 const PetscInt *cone, *support; 6423 PetscInt coneNew[2], coneSize, c, supportSize, s; 6424 6425 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6426 coneNew[0] = vStartNew + (cone[0] - vStart); 6427 coneNew[1] = vStartNew + (cone[1] - vStart); 6428 coneNew[(r+1)%2] = newv; 6429 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6430 #if 1 6431 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6432 for (p = 0; p < 2; ++p) { 6433 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); 6434 } 6435 #endif 6436 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6437 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6438 for (s = 0; s < supportSize; ++s) { 6439 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6440 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6441 for (c = 0; c < coneSize; ++c) { 6442 if (cone[c] == f) break; 6443 } 6444 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6445 } 6446 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6447 #if 1 6448 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6449 for (p = 0; p < supportSize; ++p) { 6450 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); 6451 } 6452 #endif 6453 } 6454 } 6455 /* Interior faces have 2 vertices and 2 cells */ 6456 for (c = cStart; c < cEnd; ++c) { 6457 const PetscInt *cone; 6458 PetscInt coneNew[2], supportNew[2]; 6459 6460 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6461 for (r = 0; r < 4; ++r) { 6462 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6463 6464 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6465 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6466 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6467 #if 1 6468 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6469 for (p = 0; p < 2; ++p) { 6470 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); 6471 } 6472 #endif 6473 supportNew[0] = (c - cStart)*4 + r; 6474 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6475 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6476 #if 1 6477 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6478 for (p = 0; p < 2; ++p) { 6479 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); 6480 } 6481 #endif 6482 } 6483 } 6484 /* Old vertices have identical supports */ 6485 for (v = vStart; v < vEnd; ++v) { 6486 const PetscInt newp = vStartNew + (v - vStart); 6487 const PetscInt *support, *cone; 6488 PetscInt size, s; 6489 6490 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6491 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6492 for (s = 0; s < size; ++s) { 6493 PetscInt r = 0; 6494 6495 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6496 if (cone[1] == v) r = 1; 6497 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6498 } 6499 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6500 #if 1 6501 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6502 for (p = 0; p < size; ++p) { 6503 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); 6504 } 6505 #endif 6506 } 6507 /* Face vertices have 2 + cells supports */ 6508 for (f = fStart; f < fEnd; ++f) { 6509 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6510 const PetscInt *cone, *support; 6511 PetscInt size, s; 6512 6513 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6514 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6515 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6516 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6517 for (s = 0; s < size; ++s) { 6518 PetscInt r = 0; 6519 6520 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6521 if (cone[1] == f) r = 1; 6522 else if (cone[2] == f) r = 2; 6523 else if (cone[3] == f) r = 3; 6524 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6525 } 6526 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6527 #if 1 6528 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6529 for (p = 0; p < 2+size; ++p) { 6530 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); 6531 } 6532 #endif 6533 } 6534 /* Cell vertices have 4 supports */ 6535 for (c = cStart; c < cEnd; ++c) { 6536 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6537 PetscInt supportNew[4]; 6538 6539 for (r = 0; r < 4; ++r) { 6540 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6541 } 6542 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6543 } 6544 break; 6545 case 3: 6546 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6547 cMax = PetscMin(cEnd, cMax); 6548 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6549 fMax = PetscMin(fEnd, fMax); 6550 /* Interior cells have 3 faces */ 6551 for (c = cStart; c < cMax; ++c) { 6552 const PetscInt newp = cStartNew + (c - cStart)*4; 6553 const PetscInt *cone, *ornt; 6554 PetscInt coneNew[3], orntNew[3]; 6555 6556 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6557 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6558 /* A triangle */ 6559 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6560 orntNew[0] = ornt[0]; 6561 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6562 orntNew[1] = -2; 6563 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6564 orntNew[2] = ornt[2]; 6565 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6566 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6567 #if 1 6568 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); 6569 for (p = 0; p < 3; ++p) { 6570 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); 6571 } 6572 #endif 6573 /* B triangle */ 6574 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6575 orntNew[0] = ornt[0]; 6576 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6577 orntNew[1] = ornt[1]; 6578 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6579 orntNew[2] = -2; 6580 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6581 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6582 #if 1 6583 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); 6584 for (p = 0; p < 3; ++p) { 6585 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); 6586 } 6587 #endif 6588 /* C triangle */ 6589 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6590 orntNew[0] = -2; 6591 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6592 orntNew[1] = ornt[1]; 6593 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6594 orntNew[2] = ornt[2]; 6595 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6596 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6597 #if 1 6598 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); 6599 for (p = 0; p < 3; ++p) { 6600 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); 6601 } 6602 #endif 6603 /* D triangle */ 6604 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6605 orntNew[0] = 0; 6606 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6607 orntNew[1] = 0; 6608 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6609 orntNew[2] = 0; 6610 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6611 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6612 #if 1 6613 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); 6614 for (p = 0; p < 3; ++p) { 6615 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); 6616 } 6617 #endif 6618 } 6619 /* 6620 2----3----3 6621 | | 6622 | B | 6623 | | 6624 0----4--- 1 6625 | | 6626 | A | 6627 | | 6628 0----2----1 6629 */ 6630 /* Hybrid cells have 4 faces */ 6631 for (c = cMax; c < cEnd; ++c) { 6632 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6633 const PetscInt *cone, *ornt; 6634 PetscInt coneNew[4], orntNew[4]; 6635 6636 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6637 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6638 /* A quad */ 6639 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6640 orntNew[0] = ornt[0]; 6641 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6642 orntNew[1] = ornt[1]; 6643 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6644 orntNew[2] = 0; 6645 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6646 orntNew[3] = 0; 6647 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6648 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6649 #if 1 6650 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); 6651 for (p = 0; p < 4; ++p) { 6652 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); 6653 } 6654 #endif 6655 /* B quad */ 6656 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6657 orntNew[0] = ornt[0]; 6658 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6659 orntNew[1] = ornt[1]; 6660 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6661 orntNew[2] = 0; 6662 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6663 orntNew[3] = 0; 6664 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6665 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6666 #if 1 6667 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); 6668 for (p = 0; p < 4; ++p) { 6669 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); 6670 } 6671 #endif 6672 } 6673 /* Interior split faces have 2 vertices and the same cells as the parent */ 6674 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6675 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6676 for (f = fStart; f < fMax; ++f) { 6677 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6678 6679 for (r = 0; r < 2; ++r) { 6680 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6681 const PetscInt *cone, *support; 6682 PetscInt coneNew[2], coneSize, c, supportSize, s; 6683 6684 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6685 coneNew[0] = vStartNew + (cone[0] - vStart); 6686 coneNew[1] = vStartNew + (cone[1] - vStart); 6687 coneNew[(r+1)%2] = newv; 6688 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6689 #if 1 6690 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6691 for (p = 0; p < 2; ++p) { 6692 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); 6693 } 6694 #endif 6695 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6696 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6697 for (s = 0; s < supportSize; ++s) { 6698 if (support[s] >= cMax) { 6699 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6700 } else { 6701 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6702 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6703 for (c = 0; c < coneSize; ++c) { 6704 if (cone[c] == f) break; 6705 } 6706 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6707 } 6708 } 6709 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6710 #if 1 6711 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6712 for (p = 0; p < supportSize; ++p) { 6713 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); 6714 } 6715 #endif 6716 } 6717 } 6718 /* Interior cell faces have 2 vertices and 2 cells */ 6719 for (c = cStart; c < cMax; ++c) { 6720 const PetscInt *cone; 6721 6722 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6723 for (r = 0; r < 3; ++r) { 6724 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6725 PetscInt coneNew[2]; 6726 PetscInt supportNew[2]; 6727 6728 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6729 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6730 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6731 #if 1 6732 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6733 for (p = 0; p < 2; ++p) { 6734 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); 6735 } 6736 #endif 6737 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6738 supportNew[1] = (c - cStart)*4 + 3; 6739 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6740 #if 1 6741 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6742 for (p = 0; p < 2; ++p) { 6743 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); 6744 } 6745 #endif 6746 } 6747 } 6748 /* Interior hybrid faces have 2 vertices and the same cells */ 6749 for (f = fMax; f < fEnd; ++f) { 6750 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6751 const PetscInt *cone; 6752 const PetscInt *support; 6753 PetscInt coneNew[2]; 6754 PetscInt supportNew[2]; 6755 PetscInt size, s, r; 6756 6757 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6758 coneNew[0] = vStartNew + (cone[0] - vStart); 6759 coneNew[1] = vStartNew + (cone[1] - vStart); 6760 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6761 #if 1 6762 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6763 for (p = 0; p < 2; ++p) { 6764 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); 6765 } 6766 #endif 6767 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6768 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6769 for (s = 0; s < size; ++s) { 6770 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6771 for (r = 0; r < 2; ++r) { 6772 if (cone[r+2] == f) break; 6773 } 6774 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6775 } 6776 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6777 #if 1 6778 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6779 for (p = 0; p < size; ++p) { 6780 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); 6781 } 6782 #endif 6783 } 6784 /* Cell hybrid faces have 2 vertices and 2 cells */ 6785 for (c = cMax; c < cEnd; ++c) { 6786 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6787 const PetscInt *cone; 6788 PetscInt coneNew[2]; 6789 PetscInt supportNew[2]; 6790 6791 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6792 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6793 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6794 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6795 #if 1 6796 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6797 for (p = 0; p < 2; ++p) { 6798 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); 6799 } 6800 #endif 6801 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6802 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6803 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6804 #if 1 6805 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6806 for (p = 0; p < 2; ++p) { 6807 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); 6808 } 6809 #endif 6810 } 6811 /* Old vertices have identical supports */ 6812 for (v = vStart; v < vEnd; ++v) { 6813 const PetscInt newp = vStartNew + (v - vStart); 6814 const PetscInt *support, *cone; 6815 PetscInt size, s; 6816 6817 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6818 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6819 for (s = 0; s < size; ++s) { 6820 if (support[s] >= fMax) { 6821 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6822 } else { 6823 PetscInt r = 0; 6824 6825 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6826 if (cone[1] == v) r = 1; 6827 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6828 } 6829 } 6830 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6831 #if 1 6832 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6833 for (p = 0; p < size; ++p) { 6834 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); 6835 } 6836 #endif 6837 } 6838 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6839 for (f = fStart; f < fMax; ++f) { 6840 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6841 const PetscInt *cone, *support; 6842 PetscInt size, newSize = 2, s; 6843 6844 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6845 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6846 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6847 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6848 for (s = 0; s < size; ++s) { 6849 PetscInt r = 0; 6850 6851 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6852 if (support[s] >= cMax) { 6853 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6854 6855 newSize += 1; 6856 } else { 6857 if (cone[1] == f) r = 1; 6858 else if (cone[2] == f) r = 2; 6859 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6860 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6861 6862 newSize += 2; 6863 } 6864 } 6865 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6866 #if 1 6867 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6868 for (p = 0; p < newSize; ++p) { 6869 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); 6870 } 6871 #endif 6872 } 6873 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6874 break; 6875 default: 6876 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6877 } 6878 PetscFunctionReturn(0); 6879 } 6880 6881 #undef __FUNCT__ 6882 #define __FUNCT__ "CellRefinerSetCoordinates" 6883 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6884 { 6885 PetscSection coordSection, coordSectionNew; 6886 Vec coordinates, coordinatesNew; 6887 PetscScalar *coords, *coordsNew; 6888 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6889 PetscErrorCode ierr; 6890 6891 PetscFunctionBegin; 6892 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6893 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6894 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6895 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6896 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6897 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6898 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6899 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6900 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6901 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6902 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6903 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6904 if (fMax < 0) fMax = fEnd; 6905 switch (refiner) { 6906 case 1: 6907 case 2: 6908 case 3: 6909 /* Simplicial and Hex 2D */ 6910 /* All vertices have the dim coordinates */ 6911 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6912 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6913 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6914 } 6915 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6916 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6917 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6918 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6919 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6920 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6921 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6922 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6923 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6924 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6925 /* Old vertices have the same coordinates */ 6926 for (v = vStart; v < vEnd; ++v) { 6927 const PetscInt newv = vStartNew + (v - vStart); 6928 PetscInt off, offnew, d; 6929 6930 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6931 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6932 for (d = 0; d < dim; ++d) { 6933 coordsNew[offnew+d] = coords[off+d]; 6934 } 6935 } 6936 /* Face vertices have the average of endpoint coordinates */ 6937 for (f = fStart; f < fMax; ++f) { 6938 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6939 const PetscInt *cone; 6940 PetscInt coneSize, offA, offB, offnew, d; 6941 6942 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6943 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6944 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6945 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6946 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6947 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6948 for (d = 0; d < dim; ++d) { 6949 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6950 } 6951 } 6952 /* Just Hex 2D */ 6953 if (refiner == 2) { 6954 /* Cell vertices have the average of corner coordinates */ 6955 for (c = cStart; c < cEnd; ++c) { 6956 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6957 PetscInt *cone = NULL; 6958 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6959 6960 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6961 for (p = 0; p < closureSize*2; p += 2) { 6962 const PetscInt point = cone[p]; 6963 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6964 } 6965 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6966 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6967 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6968 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6969 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6970 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6971 for (d = 0; d < dim; ++d) { 6972 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6973 } 6974 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6975 } 6976 } 6977 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6978 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6979 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6980 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6981 break; 6982 default: 6983 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6984 } 6985 PetscFunctionReturn(0); 6986 } 6987 6988 #undef __FUNCT__ 6989 #define __FUNCT__ "DMPlexCreateProcessSF" 6990 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6991 { 6992 PetscInt numRoots, numLeaves, l; 6993 const PetscInt *localPoints; 6994 const PetscSFNode *remotePoints; 6995 PetscInt *localPointsNew; 6996 PetscSFNode *remotePointsNew; 6997 PetscInt *ranks, *ranksNew; 6998 PetscErrorCode ierr; 6999 7000 PetscFunctionBegin; 7001 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7002 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 7003 for (l = 0; l < numLeaves; ++l) { 7004 ranks[l] = remotePoints[l].rank; 7005 } 7006 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 7007 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 7008 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7009 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7010 for (l = 0; l < numLeaves; ++l) { 7011 ranksNew[l] = ranks[l]; 7012 localPointsNew[l] = l; 7013 remotePointsNew[l].index = 0; 7014 remotePointsNew[l].rank = ranksNew[l]; 7015 } 7016 ierr = PetscFree(ranks);CHKERRQ(ierr); 7017 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 7018 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 7019 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 7020 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7021 PetscFunctionReturn(0); 7022 } 7023 7024 #undef __FUNCT__ 7025 #define __FUNCT__ "CellRefinerCreateSF" 7026 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7027 { 7028 PetscSF sf, sfNew, sfProcess; 7029 IS processRanks; 7030 MPI_Datatype depthType; 7031 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7032 const PetscInt *localPoints, *neighbors; 7033 const PetscSFNode *remotePoints; 7034 PetscInt *localPointsNew; 7035 PetscSFNode *remotePointsNew; 7036 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7037 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7038 PetscErrorCode ierr; 7039 7040 PetscFunctionBegin; 7041 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7042 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7043 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7044 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7045 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7046 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7047 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7048 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7049 switch (refiner) { 7050 case 3: 7051 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7052 cMax = PetscMin(cEnd, cMax); 7053 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7054 fMax = PetscMin(fEnd, fMax); 7055 } 7056 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7057 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7058 /* Caculate size of new SF */ 7059 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7060 if (numRoots < 0) PetscFunctionReturn(0); 7061 for (l = 0; l < numLeaves; ++l) { 7062 const PetscInt p = localPoints[l]; 7063 7064 switch (refiner) { 7065 case 1: 7066 /* Simplicial 2D */ 7067 if ((p >= vStart) && (p < vEnd)) { 7068 /* Old vertices stay the same */ 7069 ++numLeavesNew; 7070 } else if ((p >= fStart) && (p < fEnd)) { 7071 /* Old faces add new faces and vertex */ 7072 numLeavesNew += 1 + 2; 7073 } else if ((p >= cStart) && (p < cEnd)) { 7074 /* Old cells add new cells and interior faces */ 7075 numLeavesNew += 4 + 3; 7076 } 7077 break; 7078 case 2: 7079 /* Hex 2D */ 7080 if ((p >= vStart) && (p < vEnd)) { 7081 /* Old vertices stay the same */ 7082 ++numLeavesNew; 7083 } else if ((p >= fStart) && (p < fEnd)) { 7084 /* Old faces add new faces and vertex */ 7085 numLeavesNew += 1 + 2; 7086 } else if ((p >= cStart) && (p < cEnd)) { 7087 /* Old cells add new cells and interior faces */ 7088 numLeavesNew += 4 + 4; 7089 } 7090 break; 7091 default: 7092 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7093 } 7094 } 7095 /* Communicate depthSizes for each remote rank */ 7096 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7097 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7098 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7099 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); 7100 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7101 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7102 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7103 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7104 for (n = 0; n < numNeighbors; ++n) { 7105 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7106 } 7107 depthSizeOld[depth] = cMax; 7108 depthSizeOld[0] = vMax; 7109 depthSizeOld[depth-1] = fMax; 7110 depthSizeOld[1] = eMax; 7111 7112 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7113 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7114 7115 depthSizeOld[depth] = cEnd - cStart; 7116 depthSizeOld[0] = vEnd - vStart; 7117 depthSizeOld[depth-1] = fEnd - fStart; 7118 depthSizeOld[1] = eEnd - eStart; 7119 7120 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7121 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7122 for (n = 0; n < numNeighbors; ++n) { 7123 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7124 } 7125 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7126 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7127 /* Calculate new point SF */ 7128 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7129 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7130 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7131 for (l = 0, m = 0; l < numLeaves; ++l) { 7132 PetscInt p = localPoints[l]; 7133 PetscInt rp = remotePoints[l].index, n; 7134 PetscMPIInt rrank = remotePoints[l].rank; 7135 7136 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7137 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7138 switch (refiner) { 7139 case 1: 7140 /* Simplicial 2D */ 7141 if ((p >= vStart) && (p < vEnd)) { 7142 /* Old vertices stay the same */ 7143 localPointsNew[m] = vStartNew + (p - vStart); 7144 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7145 remotePointsNew[m].rank = rrank; 7146 ++m; 7147 } else if ((p >= fStart) && (p < fEnd)) { 7148 /* Old faces add new faces and vertex */ 7149 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7150 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7151 remotePointsNew[m].rank = rrank; 7152 ++m; 7153 for (r = 0; r < 2; ++r, ++m) { 7154 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7155 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7156 remotePointsNew[m].rank = rrank; 7157 } 7158 } else if ((p >= cStart) && (p < cEnd)) { 7159 /* Old cells add new cells and interior faces */ 7160 for (r = 0; r < 4; ++r, ++m) { 7161 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7162 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7163 remotePointsNew[m].rank = rrank; 7164 } 7165 for (r = 0; r < 3; ++r, ++m) { 7166 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7167 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7168 remotePointsNew[m].rank = rrank; 7169 } 7170 } 7171 break; 7172 case 2: 7173 /* Hex 2D */ 7174 if ((p >= vStart) && (p < vEnd)) { 7175 /* Old vertices stay the same */ 7176 localPointsNew[m] = vStartNew + (p - vStart); 7177 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7178 remotePointsNew[m].rank = rrank; 7179 ++m; 7180 } else if ((p >= fStart) && (p < fEnd)) { 7181 /* Old faces add new faces and vertex */ 7182 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7183 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7184 remotePointsNew[m].rank = rrank; 7185 ++m; 7186 for (r = 0; r < 2; ++r, ++m) { 7187 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7188 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7189 remotePointsNew[m].rank = rrank; 7190 } 7191 } else if ((p >= cStart) && (p < cEnd)) { 7192 /* Old cells add new cells and interior faces */ 7193 for (r = 0; r < 4; ++r, ++m) { 7194 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7195 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7196 remotePointsNew[m].rank = rrank; 7197 } 7198 for (r = 0; r < 4; ++r, ++m) { 7199 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7200 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7201 remotePointsNew[m].rank = rrank; 7202 } 7203 } 7204 break; 7205 case 3: 7206 /* Hybrid simplicial 2D */ 7207 if ((p >= vStart) && (p < vEnd)) { 7208 /* Old vertices stay the same */ 7209 localPointsNew[m] = vStartNew + (p - vStart); 7210 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7211 remotePointsNew[m].rank = rrank; 7212 ++m; 7213 } else if ((p >= fStart) && (p < fMax)) { 7214 /* Old interior faces add new faces and vertex */ 7215 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7216 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7217 remotePointsNew[m].rank = rrank; 7218 ++m; 7219 for (r = 0; r < 2; ++r, ++m) { 7220 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7221 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7222 remotePointsNew[m].rank = rrank; 7223 } 7224 } else if ((p >= fMax) && (p < fEnd)) { 7225 /* Old hybrid faces stay the same */ 7226 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7227 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7228 remotePointsNew[m].rank = rrank; 7229 ++m; 7230 } else if ((p >= cStart) && (p < cMax)) { 7231 /* Old interior cells add new cells and interior faces */ 7232 for (r = 0; r < 4; ++r, ++m) { 7233 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7234 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7235 remotePointsNew[m].rank = rrank; 7236 } 7237 for (r = 0; r < 3; ++r, ++m) { 7238 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7239 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7240 remotePointsNew[m].rank = rrank; 7241 } 7242 } else if ((p >= cStart) && (p < cMax)) { 7243 /* Old hybrid cells add new cells and hybrid face */ 7244 for (r = 0; r < 2; ++r, ++m) { 7245 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7246 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7247 remotePointsNew[m].rank = rrank; 7248 } 7249 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7250 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]); 7251 remotePointsNew[m].rank = rrank; 7252 ++m; 7253 } 7254 break; 7255 default: 7256 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7257 } 7258 } 7259 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7260 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7261 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7262 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7263 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7264 PetscFunctionReturn(0); 7265 } 7266 7267 #undef __FUNCT__ 7268 #define __FUNCT__ "CellRefinerCreateLabels" 7269 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7270 { 7271 PetscInt numLabels, l; 7272 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7273 PetscErrorCode ierr; 7274 7275 PetscFunctionBegin; 7276 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7277 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7278 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7279 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7280 7281 cStartNew = 0; 7282 vStartNew = depthSize[2]; 7283 fStartNew = depthSize[2] + depthSize[0]; 7284 7285 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7286 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7287 switch (refiner) { 7288 case 3: 7289 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7290 cMax = PetscMin(cEnd, cMax); 7291 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7292 fMax = PetscMin(fEnd, fMax); 7293 } 7294 for (l = 0; l < numLabels; ++l) { 7295 DMLabel label, labelNew; 7296 const char *lname; 7297 PetscBool isDepth; 7298 IS valueIS; 7299 const PetscInt *values; 7300 PetscInt numValues, val; 7301 7302 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7303 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7304 if (isDepth) continue; 7305 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7306 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7307 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7308 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7309 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7310 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7311 for (val = 0; val < numValues; ++val) { 7312 IS pointIS; 7313 const PetscInt *points; 7314 PetscInt numPoints, n; 7315 7316 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7317 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7318 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7319 for (n = 0; n < numPoints; ++n) { 7320 const PetscInt p = points[n]; 7321 switch (refiner) { 7322 case 1: 7323 /* Simplicial 2D */ 7324 if ((p >= vStart) && (p < vEnd)) { 7325 /* Old vertices stay the same */ 7326 newp = vStartNew + (p - vStart); 7327 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7328 } else if ((p >= fStart) && (p < fEnd)) { 7329 /* Old faces add new faces and vertex */ 7330 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7331 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7332 for (r = 0; r < 2; ++r) { 7333 newp = fStartNew + (p - fStart)*2 + r; 7334 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7335 } 7336 } else if ((p >= cStart) && (p < cEnd)) { 7337 /* Old cells add new cells and interior faces */ 7338 for (r = 0; r < 4; ++r) { 7339 newp = cStartNew + (p - cStart)*4 + r; 7340 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7341 } 7342 for (r = 0; r < 3; ++r) { 7343 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7344 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7345 } 7346 } 7347 break; 7348 case 2: 7349 /* Hex 2D */ 7350 if ((p >= vStart) && (p < vEnd)) { 7351 /* Old vertices stay the same */ 7352 newp = vStartNew + (p - vStart); 7353 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7354 } else if ((p >= fStart) && (p < fEnd)) { 7355 /* Old faces add new faces and vertex */ 7356 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7357 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7358 for (r = 0; r < 2; ++r) { 7359 newp = fStartNew + (p - fStart)*2 + r; 7360 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7361 } 7362 } else if ((p >= cStart) && (p < cEnd)) { 7363 /* Old cells add new cells and interior faces and vertex */ 7364 for (r = 0; r < 4; ++r) { 7365 newp = cStartNew + (p - cStart)*4 + r; 7366 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7367 } 7368 for (r = 0; r < 4; ++r) { 7369 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7370 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7371 } 7372 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7373 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7374 } 7375 break; 7376 case 3: 7377 /* Hybrid simplicial 2D */ 7378 if ((p >= vStart) && (p < vEnd)) { 7379 /* Old vertices stay the same */ 7380 newp = vStartNew + (p - vStart); 7381 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7382 } else if ((p >= fStart) && (p < fMax)) { 7383 /* Old interior faces add new faces and vertex */ 7384 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7385 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7386 for (r = 0; r < 2; ++r) { 7387 newp = fStartNew + (p - fStart)*2 + r; 7388 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7389 } 7390 } else if ((p >= fMax) && (p < fEnd)) { 7391 /* Old hybrid faces stay the same */ 7392 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7393 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7394 } else if ((p >= cStart) && (p < cMax)) { 7395 /* Old interior cells add new cells and interior faces */ 7396 for (r = 0; r < 4; ++r) { 7397 newp = cStartNew + (p - cStart)*4 + r; 7398 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7399 } 7400 for (r = 0; r < 3; ++r) { 7401 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7402 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7403 } 7404 } else if ((p >= cMax) && (p < cEnd)) { 7405 /* Old hybrid cells add new cells and hybrid face */ 7406 for (r = 0; r < 2; ++r) { 7407 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7408 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7409 } 7410 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7411 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7412 } 7413 break; 7414 default: 7415 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7416 } 7417 } 7418 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7419 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7420 } 7421 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7422 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7423 if (0) { 7424 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7425 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7426 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7427 } 7428 } 7429 PetscFunctionReturn(0); 7430 } 7431 7432 #undef __FUNCT__ 7433 #define __FUNCT__ "DMPlexRefine_Uniform" 7434 /* This will only work for interpolated meshes */ 7435 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7436 { 7437 DM rdm; 7438 PetscInt *depthSize; 7439 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7440 PetscErrorCode ierr; 7441 7442 PetscFunctionBegin; 7443 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 7444 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7445 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7446 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7447 /* Calculate number of new points of each depth */ 7448 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7449 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7450 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7451 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7452 /* Step 1: Set chart */ 7453 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7454 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7455 /* Step 2: Set cone/support sizes */ 7456 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7457 /* Step 3: Setup refined DM */ 7458 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7459 /* Step 4: Set cones and supports */ 7460 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7461 /* Step 5: Stratify */ 7462 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7463 /* Step 6: Set coordinates for vertices */ 7464 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7465 /* Step 7: Create pointSF */ 7466 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7467 /* Step 8: Create labels */ 7468 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7469 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7470 7471 *dmRefined = rdm; 7472 PetscFunctionReturn(0); 7473 } 7474 7475 #undef __FUNCT__ 7476 #define __FUNCT__ "DMPlexSetRefinementUniform" 7477 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7478 { 7479 DM_Plex *mesh = (DM_Plex*) dm->data; 7480 7481 PetscFunctionBegin; 7482 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7483 mesh->refinementUniform = refinementUniform; 7484 PetscFunctionReturn(0); 7485 } 7486 7487 #undef __FUNCT__ 7488 #define __FUNCT__ "DMPlexGetRefinementUniform" 7489 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7490 { 7491 DM_Plex *mesh = (DM_Plex*) dm->data; 7492 7493 PetscFunctionBegin; 7494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7495 PetscValidPointer(refinementUniform, 2); 7496 *refinementUniform = mesh->refinementUniform; 7497 PetscFunctionReturn(0); 7498 } 7499 7500 #undef __FUNCT__ 7501 #define __FUNCT__ "DMPlexSetRefinementLimit" 7502 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7503 { 7504 DM_Plex *mesh = (DM_Plex*) dm->data; 7505 7506 PetscFunctionBegin; 7507 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7508 mesh->refinementLimit = refinementLimit; 7509 PetscFunctionReturn(0); 7510 } 7511 7512 #undef __FUNCT__ 7513 #define __FUNCT__ "DMPlexGetRefinementLimit" 7514 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7515 { 7516 DM_Plex *mesh = (DM_Plex*) dm->data; 7517 7518 PetscFunctionBegin; 7519 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7520 PetscValidPointer(refinementLimit, 2); 7521 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7522 *refinementLimit = mesh->refinementLimit; 7523 PetscFunctionReturn(0); 7524 } 7525 7526 #undef __FUNCT__ 7527 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7528 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7529 { 7530 PetscInt dim, cStart, coneSize, cMax; 7531 PetscErrorCode ierr; 7532 7533 PetscFunctionBegin; 7534 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7535 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7536 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7537 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7538 switch (dim) { 7539 case 2: 7540 switch (coneSize) { 7541 case 3: 7542 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7543 else *cellRefiner = 1; /* Triangular */ 7544 break; 7545 case 4: 7546 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7547 else *cellRefiner = 2; /* Quadrilateral */ 7548 break; 7549 default: 7550 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7551 } 7552 break; 7553 default: 7554 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7555 } 7556 PetscFunctionReturn(0); 7557 } 7558 7559 #undef __FUNCT__ 7560 #define __FUNCT__ "DMRefine_Plex" 7561 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7562 { 7563 PetscReal refinementLimit; 7564 PetscInt dim, cStart, cEnd; 7565 char genname[1024], *name = NULL; 7566 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7567 PetscErrorCode ierr; 7568 7569 PetscFunctionBegin; 7570 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7571 if (isUniform) { 7572 CellRefiner cellRefiner; 7573 7574 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7575 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7576 PetscFunctionReturn(0); 7577 } 7578 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7579 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7580 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7581 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7582 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7583 if (flg) name = genname; 7584 if (name) { 7585 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7586 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7587 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7588 } 7589 switch (dim) { 7590 case 2: 7591 if (!name || isTriangle) { 7592 #if defined(PETSC_HAVE_TRIANGLE) 7593 double *maxVolumes; 7594 PetscInt c; 7595 7596 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7597 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7598 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7599 #else 7600 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7601 #endif 7602 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7603 break; 7604 case 3: 7605 if (!name || isCTetgen) { 7606 #if defined(PETSC_HAVE_CTETGEN) 7607 PetscReal *maxVolumes; 7608 PetscInt c; 7609 7610 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7611 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7612 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7613 #else 7614 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7615 #endif 7616 } else if (isTetgen) { 7617 #if defined(PETSC_HAVE_TETGEN) 7618 double *maxVolumes; 7619 PetscInt c; 7620 7621 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7622 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7623 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7624 #else 7625 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7626 #endif 7627 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7628 break; 7629 default: 7630 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7631 } 7632 PetscFunctionReturn(0); 7633 } 7634 7635 #undef __FUNCT__ 7636 #define __FUNCT__ "DMPlexGetDepth" 7637 /*@ 7638 DMPlexGetDepth - get the number of strata 7639 7640 Not Collective 7641 7642 Input Parameters: 7643 . dm - The DMPlex object 7644 7645 Output Parameters: 7646 . depth - number of strata 7647 7648 Level: developer 7649 7650 Notes: 7651 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7652 7653 .keywords: mesh, points 7654 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7655 @*/ 7656 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7657 { 7658 PetscInt d; 7659 PetscErrorCode ierr; 7660 7661 PetscFunctionBegin; 7662 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7663 PetscValidPointer(depth, 2); 7664 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7665 *depth = d-1; 7666 PetscFunctionReturn(0); 7667 } 7668 7669 #undef __FUNCT__ 7670 #define __FUNCT__ "DMPlexGetDepthStratum" 7671 /*@ 7672 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7673 7674 Not Collective 7675 7676 Input Parameters: 7677 + dm - The DMPlex object 7678 - stratumValue - The requested depth 7679 7680 Output Parameters: 7681 + start - The first point at this depth 7682 - end - One beyond the last point at this depth 7683 7684 Level: developer 7685 7686 .keywords: mesh, points 7687 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7688 @*/ 7689 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7690 { 7691 DM_Plex *mesh = (DM_Plex*) dm->data; 7692 DMLabel next = mesh->labels; 7693 PetscBool flg = PETSC_FALSE; 7694 PetscInt depth; 7695 PetscErrorCode ierr; 7696 7697 PetscFunctionBegin; 7698 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7699 if (stratumValue < 0) { 7700 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7701 PetscFunctionReturn(0); 7702 } else { 7703 PetscInt pStart, pEnd; 7704 7705 if (start) *start = 0; 7706 if (end) *end = 0; 7707 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7708 if (pStart == pEnd) PetscFunctionReturn(0); 7709 } 7710 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7711 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7712 /* We should have a generic GetLabel() and a Label class */ 7713 while (next) { 7714 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7715 if (flg) break; 7716 next = next->next; 7717 } 7718 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7719 depth = stratumValue; 7720 if ((depth < 0) || (depth >= next->numStrata)) { 7721 if (start) *start = 0; 7722 if (end) *end = 0; 7723 } else { 7724 if (start) *start = next->points[next->stratumOffsets[depth]]; 7725 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7726 } 7727 PetscFunctionReturn(0); 7728 } 7729 7730 #undef __FUNCT__ 7731 #define __FUNCT__ "DMPlexGetHeightStratum" 7732 /*@ 7733 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7734 7735 Not Collective 7736 7737 Input Parameters: 7738 + dm - The DMPlex object 7739 - stratumValue - The requested height 7740 7741 Output Parameters: 7742 + start - The first point at this height 7743 - end - One beyond the last point at this height 7744 7745 Level: developer 7746 7747 .keywords: mesh, points 7748 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7749 @*/ 7750 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7751 { 7752 DM_Plex *mesh = (DM_Plex*) dm->data; 7753 DMLabel next = mesh->labels; 7754 PetscBool flg = PETSC_FALSE; 7755 PetscInt depth; 7756 PetscErrorCode ierr; 7757 7758 PetscFunctionBegin; 7759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7760 if (stratumValue < 0) { 7761 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7762 } else { 7763 PetscInt pStart, pEnd; 7764 7765 if (start) *start = 0; 7766 if (end) *end = 0; 7767 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7768 if (pStart == pEnd) PetscFunctionReturn(0); 7769 } 7770 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7771 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7772 /* We should have a generic GetLabel() and a Label class */ 7773 while (next) { 7774 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7775 if (flg) break; 7776 next = next->next; 7777 } 7778 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7779 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7780 if ((depth < 0) || (depth >= next->numStrata)) { 7781 if (start) *start = 0; 7782 if (end) *end = 0; 7783 } else { 7784 if (start) *start = next->points[next->stratumOffsets[depth]]; 7785 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7786 } 7787 PetscFunctionReturn(0); 7788 } 7789 7790 #undef __FUNCT__ 7791 #define __FUNCT__ "DMPlexCreateSectionInitial" 7792 /* Set the number of dof on each point and separate by fields */ 7793 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7794 { 7795 PetscInt *numDofTot; 7796 PetscInt pStart = 0, pEnd = 0; 7797 PetscInt p, d, f; 7798 PetscErrorCode ierr; 7799 7800 PetscFunctionBegin; 7801 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7802 for (d = 0; d <= dim; ++d) { 7803 numDofTot[d] = 0; 7804 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7805 } 7806 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7807 if (numFields > 0) { 7808 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7809 if (numComp) { 7810 for (f = 0; f < numFields; ++f) { 7811 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7812 } 7813 } 7814 } 7815 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7816 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7817 for (d = 0; d <= dim; ++d) { 7818 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7819 for (p = pStart; p < pEnd; ++p) { 7820 for (f = 0; f < numFields; ++f) { 7821 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7822 } 7823 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7824 } 7825 } 7826 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7827 PetscFunctionReturn(0); 7828 } 7829 7830 #undef __FUNCT__ 7831 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7832 /* Set the number of dof on each point and separate by fields 7833 If constDof is PETSC_DETERMINE, constrain every dof on the point 7834 */ 7835 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7836 { 7837 PetscInt numFields; 7838 PetscInt bc; 7839 PetscErrorCode ierr; 7840 7841 PetscFunctionBegin; 7842 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7843 for (bc = 0; bc < numBC; ++bc) { 7844 PetscInt field = 0; 7845 const PetscInt *idx; 7846 PetscInt n, i; 7847 7848 if (numFields) field = bcField[bc]; 7849 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7850 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7851 for (i = 0; i < n; ++i) { 7852 const PetscInt p = idx[i]; 7853 PetscInt numConst = constDof; 7854 7855 /* Constrain every dof on the point */ 7856 if (numConst < 0) { 7857 if (numFields) { 7858 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7859 } else { 7860 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7861 } 7862 } 7863 if (numFields) { 7864 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7865 } 7866 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7867 } 7868 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7869 } 7870 PetscFunctionReturn(0); 7871 } 7872 7873 #undef __FUNCT__ 7874 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7875 /* Set the constrained indices on each point and separate by fields */ 7876 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7877 { 7878 PetscInt *maxConstraints; 7879 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7880 PetscErrorCode ierr; 7881 7882 PetscFunctionBegin; 7883 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7884 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7885 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7886 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7887 for (p = pStart; p < pEnd; ++p) { 7888 PetscInt cdof; 7889 7890 if (numFields) { 7891 for (f = 0; f < numFields; ++f) { 7892 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7893 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7894 } 7895 } else { 7896 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7897 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7898 } 7899 } 7900 for (f = 0; f < numFields; ++f) { 7901 maxConstraints[numFields] += maxConstraints[f]; 7902 } 7903 if (maxConstraints[numFields]) { 7904 PetscInt *indices; 7905 7906 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7907 for (p = pStart; p < pEnd; ++p) { 7908 PetscInt cdof, d; 7909 7910 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7911 if (cdof) { 7912 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7913 if (numFields) { 7914 PetscInt numConst = 0, foff = 0; 7915 7916 for (f = 0; f < numFields; ++f) { 7917 PetscInt cfdof, fdof; 7918 7919 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7920 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7921 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7922 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7923 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7924 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7925 numConst += cfdof; 7926 foff += fdof; 7927 } 7928 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7929 } else { 7930 for (d = 0; d < cdof; ++d) indices[d] = d; 7931 } 7932 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7933 } 7934 } 7935 ierr = PetscFree(indices);CHKERRQ(ierr); 7936 } 7937 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7938 PetscFunctionReturn(0); 7939 } 7940 7941 #undef __FUNCT__ 7942 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7943 /* Set the constrained field indices on each point */ 7944 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7945 { 7946 const PetscInt *points, *indices; 7947 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7948 PetscErrorCode ierr; 7949 7950 PetscFunctionBegin; 7951 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7952 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7953 7954 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7955 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7956 if (!constraintIndices) { 7957 PetscInt *idx, i; 7958 7959 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7960 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7961 for (i = 0; i < maxDof; ++i) idx[i] = i; 7962 for (p = 0; p < numPoints; ++p) { 7963 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7964 } 7965 ierr = PetscFree(idx);CHKERRQ(ierr); 7966 } else { 7967 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7968 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7969 for (p = 0; p < numPoints; ++p) { 7970 PetscInt fcdof; 7971 7972 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7973 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); 7974 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7975 } 7976 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7977 } 7978 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7979 PetscFunctionReturn(0); 7980 } 7981 7982 #undef __FUNCT__ 7983 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7984 /* Set the constrained indices on each point and separate by fields */ 7985 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7986 { 7987 PetscInt *indices; 7988 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7989 PetscErrorCode ierr; 7990 7991 PetscFunctionBegin; 7992 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7993 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7994 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7995 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7996 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7997 for (p = pStart; p < pEnd; ++p) { 7998 PetscInt cdof, d; 7999 8000 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8001 if (cdof) { 8002 PetscInt numConst = 0, foff = 0; 8003 8004 for (f = 0; f < numFields; ++f) { 8005 const PetscInt *fcind; 8006 PetscInt fdof, fcdof; 8007 8008 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8009 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8010 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 8011 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8012 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 8013 foff += fdof; 8014 numConst += fcdof; 8015 } 8016 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8017 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8018 } 8019 } 8020 ierr = PetscFree(indices);CHKERRQ(ierr); 8021 PetscFunctionReturn(0); 8022 } 8023 8024 #undef __FUNCT__ 8025 #define __FUNCT__ "DMPlexCreateSection" 8026 /*@C 8027 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8028 8029 Not Collective 8030 8031 Input Parameters: 8032 + dm - The DMPlex object 8033 . dim - The spatial dimension of the problem 8034 . numFields - The number of fields in the problem 8035 . numComp - An array of size numFields that holds the number of components for each field 8036 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8037 . numBC - The number of boundary conditions 8038 . bcField - An array of size numBC giving the field number for each boundry condition 8039 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8040 8041 Output Parameter: 8042 . section - The PetscSection object 8043 8044 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 8045 nubmer of dof for field 0 on each edge. 8046 8047 Level: developer 8048 8049 .keywords: mesh, elements 8050 .seealso: DMPlexCreate(), PetscSectionCreate() 8051 @*/ 8052 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8053 { 8054 PetscErrorCode ierr; 8055 8056 PetscFunctionBegin; 8057 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8058 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8059 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8060 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8061 { 8062 PetscBool view = PETSC_FALSE; 8063 8064 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8065 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8066 } 8067 PetscFunctionReturn(0); 8068 } 8069 8070 #undef __FUNCT__ 8071 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8072 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8073 { 8074 PetscSection section; 8075 PetscErrorCode ierr; 8076 8077 PetscFunctionBegin; 8078 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8079 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8080 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8081 PetscFunctionReturn(0); 8082 } 8083 8084 #undef __FUNCT__ 8085 #define __FUNCT__ "DMPlexGetCoordinateSection" 8086 /*@ 8087 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8088 8089 Not Collective 8090 8091 Input Parameter: 8092 . dm - The DMPlex object 8093 8094 Output Parameter: 8095 . section - The PetscSection object 8096 8097 Level: intermediate 8098 8099 .keywords: mesh, coordinates 8100 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8101 @*/ 8102 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8103 { 8104 DM cdm; 8105 PetscErrorCode ierr; 8106 8107 PetscFunctionBegin; 8108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8109 PetscValidPointer(section, 2); 8110 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8111 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8112 PetscFunctionReturn(0); 8113 } 8114 8115 #undef __FUNCT__ 8116 #define __FUNCT__ "DMPlexSetCoordinateSection" 8117 /*@ 8118 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8119 8120 Not Collective 8121 8122 Input Parameters: 8123 + dm - The DMPlex object 8124 - section - The PetscSection object 8125 8126 Level: intermediate 8127 8128 .keywords: mesh, coordinates 8129 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8130 @*/ 8131 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8132 { 8133 DM cdm; 8134 PetscErrorCode ierr; 8135 8136 PetscFunctionBegin; 8137 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8138 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8139 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8140 PetscFunctionReturn(0); 8141 } 8142 8143 #undef __FUNCT__ 8144 #define __FUNCT__ "DMPlexGetConeSection" 8145 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8146 { 8147 DM_Plex *mesh = (DM_Plex*) dm->data; 8148 8149 PetscFunctionBegin; 8150 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8151 if (section) *section = mesh->coneSection; 8152 PetscFunctionReturn(0); 8153 } 8154 8155 #undef __FUNCT__ 8156 #define __FUNCT__ "DMPlexGetCones" 8157 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8158 { 8159 DM_Plex *mesh = (DM_Plex*) dm->data; 8160 8161 PetscFunctionBegin; 8162 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8163 if (cones) *cones = mesh->cones; 8164 PetscFunctionReturn(0); 8165 } 8166 8167 #undef __FUNCT__ 8168 #define __FUNCT__ "DMPlexGetConeOrientations" 8169 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8170 { 8171 DM_Plex *mesh = (DM_Plex*) dm->data; 8172 8173 PetscFunctionBegin; 8174 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8175 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8176 PetscFunctionReturn(0); 8177 } 8178 8179 #undef __FUNCT__ 8180 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8181 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8182 { 8183 const PetscInt embedDim = 2; 8184 PetscReal x = PetscRealPart(point[0]); 8185 PetscReal y = PetscRealPart(point[1]); 8186 PetscReal v0[2], J[4], invJ[4], detJ; 8187 PetscReal xi, eta; 8188 PetscErrorCode ierr; 8189 8190 PetscFunctionBegin; 8191 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8192 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8193 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8194 8195 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8196 else *cell = -1; 8197 PetscFunctionReturn(0); 8198 } 8199 8200 #undef __FUNCT__ 8201 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8202 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8203 { 8204 PetscSection coordSection; 8205 Vec coordsLocal; 8206 const PetscScalar *coords; 8207 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8208 PetscReal x = PetscRealPart(point[0]); 8209 PetscReal y = PetscRealPart(point[1]); 8210 PetscInt crossings = 0, f; 8211 PetscErrorCode ierr; 8212 8213 PetscFunctionBegin; 8214 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8215 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8216 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8217 for (f = 0; f < 4; ++f) { 8218 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8219 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8220 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8221 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8222 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8223 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8224 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8225 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8226 if ((cond1 || cond2) && above) ++crossings; 8227 } 8228 if (crossings % 2) *cell = c; 8229 else *cell = -1; 8230 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8231 PetscFunctionReturn(0); 8232 } 8233 8234 #undef __FUNCT__ 8235 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8236 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8237 { 8238 const PetscInt embedDim = 3; 8239 PetscReal v0[3], J[9], invJ[9], detJ; 8240 PetscReal x = PetscRealPart(point[0]); 8241 PetscReal y = PetscRealPart(point[1]); 8242 PetscReal z = PetscRealPart(point[2]); 8243 PetscReal xi, eta, zeta; 8244 PetscErrorCode ierr; 8245 8246 PetscFunctionBegin; 8247 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8248 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8249 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8250 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8251 8252 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8253 else *cell = -1; 8254 PetscFunctionReturn(0); 8255 } 8256 8257 #undef __FUNCT__ 8258 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8259 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8260 { 8261 PetscSection coordSection; 8262 Vec coordsLocal; 8263 const PetscScalar *coords; 8264 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8265 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8266 PetscBool found = PETSC_TRUE; 8267 PetscInt f; 8268 PetscErrorCode ierr; 8269 8270 PetscFunctionBegin; 8271 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8272 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8273 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8274 for (f = 0; f < 6; ++f) { 8275 /* Check the point is under plane */ 8276 /* Get face normal */ 8277 PetscReal v_i[3]; 8278 PetscReal v_j[3]; 8279 PetscReal normal[3]; 8280 PetscReal pp[3]; 8281 PetscReal dot; 8282 8283 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8284 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8285 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8286 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8287 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8288 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8289 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8290 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8291 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8292 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8293 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8294 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8295 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8296 8297 /* Check that projected point is in face (2D location problem) */ 8298 if (dot < 0.0) { 8299 found = PETSC_FALSE; 8300 break; 8301 } 8302 } 8303 if (found) *cell = c; 8304 else *cell = -1; 8305 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8306 PetscFunctionReturn(0); 8307 } 8308 8309 #undef __FUNCT__ 8310 #define __FUNCT__ "DMLocatePoints_Plex" 8311 /* 8312 Need to implement using the guess 8313 */ 8314 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8315 { 8316 PetscInt cell = -1 /*, guess = -1*/; 8317 PetscInt bs, numPoints, p; 8318 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8319 PetscInt *cells; 8320 PetscScalar *a; 8321 PetscErrorCode ierr; 8322 8323 PetscFunctionBegin; 8324 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8325 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8326 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 8327 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8328 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8329 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8330 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8331 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); 8332 numPoints /= bs; 8333 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8334 for (p = 0; p < numPoints; ++p) { 8335 const PetscScalar *point = &a[p*bs]; 8336 8337 switch (dim) { 8338 case 2: 8339 for (c = cStart; c < cEnd; ++c) { 8340 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8341 switch (coneSize) { 8342 case 3: 8343 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8344 break; 8345 case 4: 8346 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8347 break; 8348 default: 8349 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8350 } 8351 if (cell >= 0) break; 8352 } 8353 break; 8354 case 3: 8355 for (c = cStart; c < cEnd; ++c) { 8356 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8357 switch (coneSize) { 8358 case 4: 8359 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8360 break; 8361 case 8: 8362 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8363 break; 8364 default: 8365 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8366 } 8367 if (cell >= 0) break; 8368 } 8369 break; 8370 default: 8371 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8372 } 8373 cells[p] = cell; 8374 } 8375 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8376 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8377 PetscFunctionReturn(0); 8378 } 8379 8380 /******************************** FEM Support **********************************/ 8381 8382 #undef __FUNCT__ 8383 #define __FUNCT__ "DMPlexVecGetClosure" 8384 /*@C 8385 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8386 8387 Not collective 8388 8389 Input Parameters: 8390 + dm - The DM 8391 . section - The section describing the layout in v, or NULL to use the default section 8392 . v - The local vector 8393 - point - The sieve point in the DM 8394 8395 Output Parameters: 8396 + csize - The number of values in the closure, or NULL 8397 - values - The array of values, which is a borrowed array and should not be freed 8398 8399 Level: intermediate 8400 8401 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8402 @*/ 8403 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8404 { 8405 PetscScalar *array, *vArray; 8406 PetscInt *points = NULL; 8407 PetscInt offsets[32]; 8408 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8409 PetscErrorCode ierr; 8410 8411 PetscFunctionBegin; 8412 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8413 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8414 if (!section) { 8415 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8416 } 8417 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8418 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8419 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8420 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8421 /* Compress out points not in the section */ 8422 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8423 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8424 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8425 points[q*2] = points[p]; 8426 points[q*2+1] = points[p+1]; 8427 ++q; 8428 } 8429 } 8430 numPoints = q; 8431 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8432 PetscInt dof, fdof; 8433 8434 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8435 for (f = 0; f < numFields; ++f) { 8436 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8437 offsets[f+1] += fdof; 8438 } 8439 size += dof; 8440 } 8441 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8442 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8443 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8444 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8445 for (p = 0; p < numPoints*2; p += 2) { 8446 PetscInt o = points[p+1]; 8447 PetscInt dof, off, d; 8448 PetscScalar *varr; 8449 8450 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8451 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8452 varr = &vArray[off]; 8453 if (numFields) { 8454 PetscInt fdof, foff, fcomp, f, c; 8455 8456 for (f = 0, foff = 0; f < numFields; ++f) { 8457 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8458 if (o >= 0) { 8459 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8460 array[offsets[f]] = varr[foff+d]; 8461 } 8462 } else { 8463 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8464 for (d = fdof/fcomp-1; d >= 0; --d) { 8465 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8466 array[offsets[f]] = varr[foff+d*fcomp+c]; 8467 } 8468 } 8469 } 8470 foff += fdof; 8471 } 8472 } else { 8473 if (o >= 0) { 8474 for (d = 0; d < dof; ++d, ++offsets[0]) { 8475 array[offsets[0]] = varr[d]; 8476 } 8477 } else { 8478 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8479 array[offsets[0]] = varr[d]; 8480 } 8481 } 8482 } 8483 } 8484 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8485 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8486 if (csize) *csize = size; 8487 *values = array; 8488 PetscFunctionReturn(0); 8489 } 8490 8491 #undef __FUNCT__ 8492 #define __FUNCT__ "DMPlexVecRestoreClosure" 8493 /*@C 8494 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8495 8496 Not collective 8497 8498 Input Parameters: 8499 + dm - The DM 8500 . section - The section describing the layout in v, or NULL to use the default section 8501 . v - The local vector 8502 . point - The sieve point in the DM 8503 . csize - The number of values in the closure, or NULL 8504 - values - The array of values, which is a borrowed array and should not be freed 8505 8506 Level: intermediate 8507 8508 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8509 @*/ 8510 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8511 { 8512 PetscInt size = 0; 8513 PetscErrorCode ierr; 8514 8515 PetscFunctionBegin; 8516 /* Should work without recalculating size */ 8517 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8518 PetscFunctionReturn(0); 8519 } 8520 8521 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8522 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8523 8524 #undef __FUNCT__ 8525 #define __FUNCT__ "updatePoint_private" 8526 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8527 { 8528 PetscInt cdof; /* The number of constraints on this point */ 8529 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8530 PetscScalar *a; 8531 PetscInt off, cind = 0, k; 8532 PetscErrorCode ierr; 8533 8534 PetscFunctionBegin; 8535 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8536 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8537 a = &array[off]; 8538 if (!cdof || setBC) { 8539 if (orientation >= 0) { 8540 for (k = 0; k < dof; ++k) { 8541 fuse(&a[k], values[k]); 8542 } 8543 } else { 8544 for (k = 0; k < dof; ++k) { 8545 fuse(&a[k], values[dof-k-1]); 8546 } 8547 } 8548 } else { 8549 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8550 if (orientation >= 0) { 8551 for (k = 0; k < dof; ++k) { 8552 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8553 fuse(&a[k], values[k]); 8554 } 8555 } else { 8556 for (k = 0; k < dof; ++k) { 8557 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8558 fuse(&a[k], values[dof-k-1]); 8559 } 8560 } 8561 } 8562 PetscFunctionReturn(0); 8563 } 8564 8565 #undef __FUNCT__ 8566 #define __FUNCT__ "updatePointFields_private" 8567 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8568 { 8569 PetscScalar *a; 8570 PetscInt numFields, off, foff, f; 8571 PetscErrorCode ierr; 8572 8573 PetscFunctionBegin; 8574 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8575 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8576 a = &array[off]; 8577 for (f = 0, foff = 0; f < numFields; ++f) { 8578 PetscInt fdof, fcomp, fcdof; 8579 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8580 PetscInt cind = 0, k, c; 8581 8582 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8583 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8584 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8585 if (!fcdof || setBC) { 8586 if (orientation >= 0) { 8587 for (k = 0; k < fdof; ++k) { 8588 fuse(&a[foff+k], values[foffs[f]+k]); 8589 } 8590 } else { 8591 for (k = fdof/fcomp-1; k >= 0; --k) { 8592 for (c = 0; c < fcomp; ++c) { 8593 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8594 } 8595 } 8596 } 8597 } else { 8598 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8599 if (orientation >= 0) { 8600 for (k = 0; k < fdof; ++k) { 8601 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8602 fuse(&a[foff+k], values[foffs[f]+k]); 8603 } 8604 } else { 8605 for (k = fdof/fcomp-1; k >= 0; --k) { 8606 for (c = 0; c < fcomp; ++c) { 8607 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8608 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8609 } 8610 } 8611 } 8612 } 8613 foff += fdof; 8614 foffs[f] += fdof; 8615 } 8616 PetscFunctionReturn(0); 8617 } 8618 8619 #undef __FUNCT__ 8620 #define __FUNCT__ "DMPlexVecSetClosure" 8621 /*@C 8622 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8623 8624 Not collective 8625 8626 Input Parameters: 8627 + dm - The DM 8628 . section - The section describing the layout in v, or NULL to use the default sectionw 8629 . v - The local vector 8630 . point - The sieve point in the DM 8631 . values - The array of values, which is a borrowed array and should not be freed 8632 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8633 8634 Level: intermediate 8635 8636 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8637 @*/ 8638 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8639 { 8640 PetscScalar *array; 8641 PetscInt *points = NULL; 8642 PetscInt offsets[32]; 8643 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8644 PetscErrorCode ierr; 8645 8646 PetscFunctionBegin; 8647 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8648 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8649 if (!section) { 8650 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8651 } 8652 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8653 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8654 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8655 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8656 /* Compress out points not in the section */ 8657 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8658 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8659 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8660 points[q*2] = points[p]; 8661 points[q*2+1] = points[p+1]; 8662 ++q; 8663 } 8664 } 8665 numPoints = q; 8666 for (p = 0; p < numPoints*2; p += 2) { 8667 PetscInt fdof; 8668 8669 for (f = 0; f < numFields; ++f) { 8670 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8671 offsets[f+1] += fdof; 8672 } 8673 } 8674 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8675 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8676 if (numFields) { 8677 switch (mode) { 8678 case INSERT_VALUES: 8679 for (p = 0; p < numPoints*2; p += 2) { 8680 PetscInt o = points[p+1]; 8681 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8682 } break; 8683 case INSERT_ALL_VALUES: 8684 for (p = 0; p < numPoints*2; p += 2) { 8685 PetscInt o = points[p+1]; 8686 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8687 } break; 8688 case ADD_VALUES: 8689 for (p = 0; p < numPoints*2; p += 2) { 8690 PetscInt o = points[p+1]; 8691 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8692 } break; 8693 case ADD_ALL_VALUES: 8694 for (p = 0; p < numPoints*2; p += 2) { 8695 PetscInt o = points[p+1]; 8696 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8697 } break; 8698 default: 8699 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8700 } 8701 } else { 8702 switch (mode) { 8703 case INSERT_VALUES: 8704 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8705 PetscInt o = points[p+1]; 8706 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8707 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8708 } break; 8709 case INSERT_ALL_VALUES: 8710 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8711 PetscInt o = points[p+1]; 8712 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8713 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8714 } break; 8715 case ADD_VALUES: 8716 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8717 PetscInt o = points[p+1]; 8718 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8719 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8720 } break; 8721 case ADD_ALL_VALUES: 8722 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8723 PetscInt o = points[p+1]; 8724 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8725 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8726 } break; 8727 default: 8728 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8729 } 8730 } 8731 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8732 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8733 PetscFunctionReturn(0); 8734 } 8735 8736 #undef __FUNCT__ 8737 #define __FUNCT__ "DMPlexPrintMatSetValues" 8738 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8739 { 8740 PetscMPIInt rank; 8741 PetscInt i, j; 8742 PetscErrorCode ierr; 8743 8744 PetscFunctionBegin; 8745 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8746 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8747 for (i = 0; i < numIndices; i++) { 8748 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8749 } 8750 for (i = 0; i < numIndices; i++) { 8751 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8752 for (j = 0; j < numIndices; j++) { 8753 #if defined(PETSC_USE_COMPLEX) 8754 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8755 #else 8756 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8757 #endif 8758 } 8759 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8760 } 8761 PetscFunctionReturn(0); 8762 } 8763 8764 #undef __FUNCT__ 8765 #define __FUNCT__ "indicesPoint_private" 8766 /* . off - The global offset of this point */ 8767 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8768 { 8769 PetscInt dof; /* The number of unknowns on this point */ 8770 PetscInt cdof; /* The number of constraints on this point */ 8771 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8772 PetscInt cind = 0, k; 8773 PetscErrorCode ierr; 8774 8775 PetscFunctionBegin; 8776 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8777 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8778 if (!cdof || setBC) { 8779 if (orientation >= 0) { 8780 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8781 } else { 8782 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8783 } 8784 } else { 8785 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8786 if (orientation >= 0) { 8787 for (k = 0; k < dof; ++k) { 8788 if ((cind < cdof) && (k == cdofs[cind])) { 8789 /* Insert check for returning constrained indices */ 8790 indices[*loff+k] = -(off+k+1); 8791 ++cind; 8792 } else { 8793 indices[*loff+k] = off+k-cind; 8794 } 8795 } 8796 } else { 8797 for (k = 0; k < dof; ++k) { 8798 if ((cind < cdof) && (k == cdofs[cind])) { 8799 /* Insert check for returning constrained indices */ 8800 indices[*loff+dof-k-1] = -(off+k+1); 8801 ++cind; 8802 } else { 8803 indices[*loff+dof-k-1] = off+k-cind; 8804 } 8805 } 8806 } 8807 } 8808 *loff += dof; 8809 PetscFunctionReturn(0); 8810 } 8811 8812 #undef __FUNCT__ 8813 #define __FUNCT__ "indicesPointFields_private" 8814 /* . off - The global offset of this point */ 8815 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8816 { 8817 PetscInt numFields, foff, f; 8818 PetscErrorCode ierr; 8819 8820 PetscFunctionBegin; 8821 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8822 for (f = 0, foff = 0; f < numFields; ++f) { 8823 PetscInt fdof, fcomp, cfdof; 8824 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8825 PetscInt cind = 0, k, c; 8826 8827 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8828 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8829 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8830 if (!cfdof || setBC) { 8831 if (orientation >= 0) { 8832 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8833 } else { 8834 for (k = fdof/fcomp-1; k >= 0; --k) { 8835 for (c = 0; c < fcomp; ++c) { 8836 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8837 } 8838 } 8839 } 8840 } else { 8841 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8842 if (orientation >= 0) { 8843 for (k = 0; k < fdof; ++k) { 8844 if ((cind < cfdof) && (k == fcdofs[cind])) { 8845 indices[foffs[f]+k] = -(off+foff+k+1); 8846 ++cind; 8847 } else { 8848 indices[foffs[f]+k] = off+foff+k-cind; 8849 } 8850 } 8851 } else { 8852 for (k = fdof/fcomp-1; k >= 0; --k) { 8853 for (c = 0; c < fcomp; ++c) { 8854 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8855 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8856 ++cind; 8857 } else { 8858 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8859 } 8860 } 8861 } 8862 } 8863 } 8864 foff += fdof - cfdof; 8865 foffs[f] += fdof; 8866 } 8867 PetscFunctionReturn(0); 8868 } 8869 8870 #undef __FUNCT__ 8871 #define __FUNCT__ "DMPlexMatSetClosure" 8872 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8873 { 8874 DM_Plex *mesh = (DM_Plex*) dm->data; 8875 PetscInt *points = NULL; 8876 PetscInt *indices; 8877 PetscInt offsets[32]; 8878 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8879 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8880 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8881 PetscErrorCode ierr; 8882 8883 PetscFunctionBegin; 8884 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8885 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8886 if (useDefault) { 8887 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8888 } 8889 if (useGlobalDefault) { 8890 if (useDefault) { 8891 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8892 } else { 8893 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8894 } 8895 } 8896 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8897 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8898 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8899 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8900 /* Compress out points not in the section */ 8901 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8902 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8903 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8904 points[q*2] = points[p]; 8905 points[q*2+1] = points[p+1]; 8906 ++q; 8907 } 8908 } 8909 numPoints = q; 8910 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8911 PetscInt fdof; 8912 8913 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8914 for (f = 0; f < numFields; ++f) { 8915 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8916 offsets[f+1] += fdof; 8917 } 8918 numIndices += dof; 8919 } 8920 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8921 8922 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8923 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8924 if (numFields) { 8925 for (p = 0; p < numPoints*2; p += 2) { 8926 PetscInt o = points[p+1]; 8927 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8928 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8929 } 8930 } else { 8931 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8932 PetscInt o = points[p+1]; 8933 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8934 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8935 } 8936 } 8937 if (useGlobalDefault && !useDefault) { 8938 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8939 } 8940 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8941 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8942 if (ierr) { 8943 PetscMPIInt rank; 8944 PetscErrorCode ierr2; 8945 8946 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8947 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8948 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8949 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8950 CHKERRQ(ierr); 8951 } 8952 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8953 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8954 PetscFunctionReturn(0); 8955 } 8956 8957 #undef __FUNCT__ 8958 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8959 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8960 { 8961 PetscSection coordSection; 8962 Vec coordinates; 8963 const PetscScalar *coords; 8964 const PetscInt dim = 2; 8965 PetscInt d, f; 8966 PetscErrorCode ierr; 8967 8968 PetscFunctionBegin; 8969 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8970 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8971 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8972 if (v0) { 8973 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8974 } 8975 if (J) { 8976 for (d = 0; d < dim; d++) { 8977 for (f = 0; f < dim; f++) { 8978 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8979 } 8980 } 8981 *detJ = J[0]*J[3] - J[1]*J[2]; 8982 #if 0 8983 if (detJ < 0.0) { 8984 const PetscReal xLength = mesh->periodicity[0]; 8985 8986 if (xLength != 0.0) { 8987 PetscReal v0x = coords[0*dim+0]; 8988 8989 if (v0x == 0.0) v0x = v0[0] = xLength; 8990 for (f = 0; f < dim; f++) { 8991 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8992 8993 J[0*dim+f] = 0.5*(px - v0x); 8994 } 8995 } 8996 detJ = J[0]*J[3] - J[1]*J[2]; 8997 } 8998 #endif 8999 PetscLogFlops(8.0 + 3.0); 9000 } 9001 if (invJ) { 9002 const PetscReal invDet = 1.0/(*detJ); 9003 9004 invJ[0] = invDet*J[3]; 9005 invJ[1] = -invDet*J[1]; 9006 invJ[2] = -invDet*J[2]; 9007 invJ[3] = invDet*J[0]; 9008 PetscLogFlops(5.0); 9009 } 9010 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9011 PetscFunctionReturn(0); 9012 } 9013 9014 #undef __FUNCT__ 9015 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9016 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9017 { 9018 PetscSection coordSection; 9019 Vec coordinates; 9020 const PetscScalar *coords; 9021 const PetscInt dim = 2; 9022 PetscInt d, f; 9023 PetscErrorCode ierr; 9024 9025 PetscFunctionBegin; 9026 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9027 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9028 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9029 if (v0) { 9030 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9031 } 9032 if (J) { 9033 for (d = 0; d < dim; d++) { 9034 for (f = 0; f < dim; f++) { 9035 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9036 } 9037 } 9038 *detJ = J[0]*J[3] - J[1]*J[2]; 9039 PetscLogFlops(8.0 + 3.0); 9040 } 9041 if (invJ) { 9042 const PetscReal invDet = 1.0/(*detJ); 9043 9044 invJ[0] = invDet*J[3]; 9045 invJ[1] = -invDet*J[1]; 9046 invJ[2] = -invDet*J[2]; 9047 invJ[3] = invDet*J[0]; 9048 PetscLogFlops(5.0); 9049 } 9050 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9051 PetscFunctionReturn(0); 9052 } 9053 9054 #undef __FUNCT__ 9055 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9056 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9057 { 9058 PetscSection coordSection; 9059 Vec coordinates; 9060 const PetscScalar *coords; 9061 const PetscInt dim = 3; 9062 PetscInt d, f; 9063 PetscErrorCode ierr; 9064 9065 PetscFunctionBegin; 9066 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9067 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9068 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9069 if (v0) { 9070 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9071 } 9072 if (J) { 9073 for (d = 0; d < dim; d++) { 9074 for (f = 0; f < dim; f++) { 9075 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9076 } 9077 } 9078 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9079 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9080 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9081 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9082 PetscLogFlops(18.0 + 12.0); 9083 } 9084 if (invJ) { 9085 const PetscReal invDet = 1.0/(*detJ); 9086 9087 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9088 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9089 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9090 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9091 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9092 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9093 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9094 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9095 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9096 PetscLogFlops(37.0); 9097 } 9098 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9099 PetscFunctionReturn(0); 9100 } 9101 9102 #undef __FUNCT__ 9103 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9104 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9105 { 9106 PetscSection coordSection; 9107 Vec coordinates; 9108 const PetscScalar *coords; 9109 const PetscInt dim = 3; 9110 PetscInt d; 9111 PetscErrorCode ierr; 9112 9113 PetscFunctionBegin; 9114 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9115 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9116 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9117 if (v0) { 9118 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9119 } 9120 if (J) { 9121 for (d = 0; d < dim; d++) { 9122 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9123 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9124 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9125 } 9126 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9127 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9128 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9129 PetscLogFlops(18.0 + 12.0); 9130 } 9131 if (invJ) { 9132 const PetscReal invDet = -1.0/(*detJ); 9133 9134 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9135 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9136 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9137 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9138 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9139 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9140 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9141 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9142 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9143 PetscLogFlops(37.0); 9144 } 9145 *detJ *= 8.0; 9146 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9147 PetscFunctionReturn(0); 9148 } 9149 9150 #undef __FUNCT__ 9151 #define __FUNCT__ "DMPlexComputeCellGeometry" 9152 /*@C 9153 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9154 9155 Collective on DM 9156 9157 Input Arguments: 9158 + dm - the DM 9159 - cell - the cell 9160 9161 Output Arguments: 9162 + v0 - the translation part of this affine transform 9163 . J - the Jacobian of the transform to the reference element 9164 . invJ - the inverse of the Jacobian 9165 - detJ - the Jacobian determinant 9166 9167 Level: advanced 9168 9169 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9170 @*/ 9171 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9172 { 9173 PetscInt dim, coneSize; 9174 PetscErrorCode ierr; 9175 9176 PetscFunctionBegin; 9177 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9178 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9179 switch (dim) { 9180 case 2: 9181 switch (coneSize) { 9182 case 3: 9183 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9184 break; 9185 case 4: 9186 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9187 break; 9188 default: 9189 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9190 } 9191 break; 9192 case 3: 9193 switch (coneSize) { 9194 case 4: 9195 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9196 break; 9197 case 8: 9198 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9199 break; 9200 default: 9201 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9202 } 9203 break; 9204 default: 9205 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9206 } 9207 PetscFunctionReturn(0); 9208 } 9209 9210 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9211 { 9212 switch (i) { 9213 case 0: 9214 switch (j) { 9215 case 0: return 0; 9216 case 1: 9217 switch (k) { 9218 case 0: return 0; 9219 case 1: return 0; 9220 case 2: return 1; 9221 } 9222 case 2: 9223 switch (k) { 9224 case 0: return 0; 9225 case 1: return -1; 9226 case 2: return 0; 9227 } 9228 } 9229 case 1: 9230 switch (j) { 9231 case 0: 9232 switch (k) { 9233 case 0: return 0; 9234 case 1: return 0; 9235 case 2: return -1; 9236 } 9237 case 1: return 0; 9238 case 2: 9239 switch (k) { 9240 case 0: return 1; 9241 case 1: return 0; 9242 case 2: return 0; 9243 } 9244 } 9245 case 2: 9246 switch (j) { 9247 case 0: 9248 switch (k) { 9249 case 0: return 0; 9250 case 1: return 1; 9251 case 2: return 0; 9252 } 9253 case 1: 9254 switch (k) { 9255 case 0: return -1; 9256 case 1: return 0; 9257 case 2: return 0; 9258 } 9259 case 2: return 0; 9260 } 9261 } 9262 return 0; 9263 } 9264 9265 #undef __FUNCT__ 9266 #define __FUNCT__ "DMPlexCreateRigidBody" 9267 /*@C 9268 DMPlexCreateRigidBody - create rigid body modes from coordinates 9269 9270 Collective on DM 9271 9272 Input Arguments: 9273 + dm - the DM 9274 . section - the local section associated with the rigid field, or NULL for the default section 9275 - globalSection - the global section associated with the rigid field, or NULL for the default section 9276 9277 Output Argument: 9278 . sp - the null space 9279 9280 Note: This is necessary to take account of Dirichlet conditions on the displacements 9281 9282 Level: advanced 9283 9284 .seealso: MatNullSpaceCreate() 9285 @*/ 9286 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9287 { 9288 MPI_Comm comm; 9289 Vec coordinates, localMode, mode[6]; 9290 PetscSection coordSection; 9291 PetscScalar *coords; 9292 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9293 PetscErrorCode ierr; 9294 9295 PetscFunctionBegin; 9296 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 9297 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9298 if (dim == 1) { 9299 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 9300 PetscFunctionReturn(0); 9301 } 9302 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9303 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9304 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9305 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9306 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9307 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9308 m = (dim*(dim+1))/2; 9309 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9310 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9311 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9312 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9313 /* Assume P1 */ 9314 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9315 for (d = 0; d < dim; ++d) { 9316 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9317 9318 values[d] = 1.0; 9319 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9320 for (v = vStart; v < vEnd; ++v) { 9321 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9322 } 9323 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9324 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9325 } 9326 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9327 for (d = dim; d < dim*(dim+1)/2; ++d) { 9328 PetscInt i, j, k = dim > 2 ? d - dim : d; 9329 9330 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9331 for (v = vStart; v < vEnd; ++v) { 9332 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9333 PetscInt off; 9334 9335 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9336 for (i = 0; i < dim; ++i) { 9337 for (j = 0; j < dim; ++j) { 9338 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9339 } 9340 } 9341 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9342 } 9343 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9344 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9345 } 9346 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9347 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9348 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 9349 /* Orthonormalize system */ 9350 for (i = dim; i < m; ++i) { 9351 PetscScalar dots[6]; 9352 9353 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9354 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9355 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9356 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 9357 } 9358 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9359 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9360 PetscFunctionReturn(0); 9361 } 9362 9363 #undef __FUNCT__ 9364 #define __FUNCT__ "DMPlexGetHybridBounds" 9365 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9366 { 9367 DM_Plex *mesh = (DM_Plex*) dm->data; 9368 PetscInt dim; 9369 PetscErrorCode ierr; 9370 9371 PetscFunctionBegin; 9372 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9373 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9374 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9375 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9376 if (eMax) *eMax = mesh->hybridPointMax[1]; 9377 if (vMax) *vMax = mesh->hybridPointMax[0]; 9378 PetscFunctionReturn(0); 9379 } 9380 9381 #undef __FUNCT__ 9382 #define __FUNCT__ "DMPlexSetHybridBounds" 9383 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9384 { 9385 DM_Plex *mesh = (DM_Plex*) dm->data; 9386 PetscInt dim; 9387 PetscErrorCode ierr; 9388 9389 PetscFunctionBegin; 9390 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9391 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9392 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9393 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9394 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9395 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9396 PetscFunctionReturn(0); 9397 } 9398 9399 #undef __FUNCT__ 9400 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9401 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9402 { 9403 DM_Plex *mesh = (DM_Plex*) dm->data; 9404 9405 PetscFunctionBegin; 9406 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9407 PetscValidPointer(cellHeight, 2); 9408 *cellHeight = mesh->vtkCellHeight; 9409 PetscFunctionReturn(0); 9410 } 9411 9412 #undef __FUNCT__ 9413 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9414 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9415 { 9416 DM_Plex *mesh = (DM_Plex*) dm->data; 9417 9418 PetscFunctionBegin; 9419 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9420 mesh->vtkCellHeight = cellHeight; 9421 PetscFunctionReturn(0); 9422 } 9423 9424 #undef __FUNCT__ 9425 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9426 /* We can easily have a form that takes an IS instead */ 9427 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9428 { 9429 PetscSection section, globalSection; 9430 PetscInt *numbers, p; 9431 PetscErrorCode ierr; 9432 9433 PetscFunctionBegin; 9434 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 9435 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9436 for (p = pStart; p < pEnd; ++p) { 9437 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9438 } 9439 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9440 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9441 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9442 for (p = pStart; p < pEnd; ++p) { 9443 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9444 } 9445 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9446 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9447 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9448 PetscFunctionReturn(0); 9449 } 9450 9451 #undef __FUNCT__ 9452 #define __FUNCT__ "DMPlexGetCellNumbering" 9453 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9454 { 9455 DM_Plex *mesh = (DM_Plex*) dm->data; 9456 PetscInt cellHeight, cStart, cEnd, cMax; 9457 PetscErrorCode ierr; 9458 9459 PetscFunctionBegin; 9460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9461 if (!mesh->globalCellNumbers) { 9462 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9463 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9464 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 9465 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9466 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9467 } 9468 *globalCellNumbers = mesh->globalCellNumbers; 9469 PetscFunctionReturn(0); 9470 } 9471 9472 #undef __FUNCT__ 9473 #define __FUNCT__ "DMPlexGetVertexNumbering" 9474 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9475 { 9476 DM_Plex *mesh = (DM_Plex*) dm->data; 9477 PetscInt vStart, vEnd, vMax; 9478 PetscErrorCode ierr; 9479 9480 PetscFunctionBegin; 9481 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9482 if (!mesh->globalVertexNumbers) { 9483 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9484 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9485 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9486 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9487 } 9488 *globalVertexNumbers = mesh->globalVertexNumbers; 9489 PetscFunctionReturn(0); 9490 } 9491 9492 #undef __FUNCT__ 9493 #define __FUNCT__ "DMPlexGetScale" 9494 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9495 { 9496 DM_Plex *mesh = (DM_Plex*) dm->data; 9497 9498 PetscFunctionBegin; 9499 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9500 PetscValidPointer(scale, 3); 9501 *scale = mesh->scale[unit]; 9502 PetscFunctionReturn(0); 9503 } 9504 9505 #undef __FUNCT__ 9506 #define __FUNCT__ "DMPlexSetScale" 9507 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9508 { 9509 DM_Plex *mesh = (DM_Plex*) dm->data; 9510 9511 PetscFunctionBegin; 9512 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9513 mesh->scale[unit] = scale; 9514 PetscFunctionReturn(0); 9515 } 9516 9517 9518 /******************************************************************************* 9519 This should be in a separate Discretization object, but I am not sure how to lay 9520 it out yet, so I am stuffing things here while I experiment. 9521 *******************************************************************************/ 9522 #undef __FUNCT__ 9523 #define __FUNCT__ "DMPlexSetFEMIntegration" 9524 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9525 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9526 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9527 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9528 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9529 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9530 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9531 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9532 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9533 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9534 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9535 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9536 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9537 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9538 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9539 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9540 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9541 { 9542 DM_Plex *mesh = (DM_Plex*) dm->data; 9543 9544 PetscFunctionBegin; 9545 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9546 mesh->integrateResidualFEM = integrateResidualFEM; 9547 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9548 mesh->integrateJacobianFEM = integrateJacobianFEM; 9549 PetscFunctionReturn(0); 9550 } 9551 9552 #undef __FUNCT__ 9553 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9554 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9555 { 9556 Vec coordinates; 9557 PetscSection section, cSection; 9558 PetscInt dim, vStart, vEnd, v, c, d; 9559 PetscScalar *values, *cArray; 9560 PetscReal *coords; 9561 PetscErrorCode ierr; 9562 9563 PetscFunctionBegin; 9564 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9565 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9566 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9567 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9568 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9569 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9570 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9571 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9572 for (v = vStart; v < vEnd; ++v) { 9573 PetscInt dof, off; 9574 9575 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9576 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9577 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9578 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9579 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9580 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9581 } 9582 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9583 /* Temporary, must be replaced by a projection on the finite element basis */ 9584 { 9585 PetscInt eStart = 0, eEnd = 0, e, depth; 9586 9587 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9588 --depth; 9589 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9590 for (e = eStart; e < eEnd; ++e) { 9591 const PetscInt *cone = NULL; 9592 PetscInt coneSize, d; 9593 PetscScalar *coordsA, *coordsB; 9594 9595 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9596 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9597 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9598 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9599 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9600 for (d = 0; d < dim; ++d) { 9601 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9602 } 9603 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9604 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9605 } 9606 } 9607 9608 ierr = PetscFree(coords);CHKERRQ(ierr); 9609 ierr = PetscFree(values);CHKERRQ(ierr); 9610 #if 0 9611 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9612 PetscReal detJ; 9613 9614 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9615 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9616 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9617 9618 for (PetscInt c = cStart; c < cEnd; ++c) { 9619 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9620 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9621 const int oSize = pV.getSize(); 9622 int v = 0; 9623 9624 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9625 for (PetscInt cl = 0; cl < oSize; ++cl) { 9626 const PetscInt fDim; 9627 9628 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9629 if (pointDim) { 9630 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9631 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9632 } 9633 } 9634 } 9635 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9636 pV.clear(); 9637 } 9638 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9639 ierr = PetscFree(values);CHKERRQ(ierr); 9640 #endif 9641 PetscFunctionReturn(0); 9642 } 9643 9644 #undef __FUNCT__ 9645 #define __FUNCT__ "DMPlexProjectFunction" 9646 /*@C 9647 DMPlexProjectFunction - This projects the given function into the function space provided. 9648 9649 Input Parameters: 9650 + dm - The DM 9651 . numComp - The number of components (functions) 9652 . funcs - The coordinate functions to evaluate 9653 - mode - The insertion mode for values 9654 9655 Output Parameter: 9656 . X - vector 9657 9658 Level: developer 9659 9660 Note: 9661 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9662 We will eventually fix it. 9663 9664 ,seealso: DMPlexComputeL2Diff() 9665 */ 9666 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9667 { 9668 Vec localX; 9669 PetscErrorCode ierr; 9670 9671 PetscFunctionBegin; 9672 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9673 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9674 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9675 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9676 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9677 PetscFunctionReturn(0); 9678 } 9679 9680 #undef __FUNCT__ 9681 #define __FUNCT__ "DMPlexComputeL2Diff" 9682 /*@C 9683 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9684 9685 Input Parameters: 9686 + dm - The DM 9687 . quad - The PetscQuadrature object for each field 9688 . funcs - The functions to evaluate for each field component 9689 - X - The coefficient vector u_h 9690 9691 Output Parameter: 9692 . diff - The diff ||u - u_h||_2 9693 9694 Level: developer 9695 9696 .seealso: DMPlexProjectFunction() 9697 */ 9698 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9699 { 9700 const PetscInt debug = 0; 9701 PetscSection section; 9702 Vec localX; 9703 PetscReal *coords, *v0, *J, *invJ, detJ; 9704 PetscReal localDiff = 0.0; 9705 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9706 PetscErrorCode ierr; 9707 9708 PetscFunctionBegin; 9709 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9710 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9711 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9712 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9713 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9714 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9715 for (field = 0; field < numFields; ++field) { 9716 numComponents += quad[field].numComponents; 9717 } 9718 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9719 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9720 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9721 for (c = cStart; c < cEnd; ++c) { 9722 const PetscScalar *x; 9723 PetscReal elemDiff = 0.0; 9724 9725 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9726 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9727 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9728 9729 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9730 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9731 const PetscReal *quadPoints = quad[field].quadPoints; 9732 const PetscReal *quadWeights = quad[field].quadWeights; 9733 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9734 const PetscInt numBasisComps = quad[field].numComponents; 9735 const PetscReal *basis = quad[field].basis; 9736 PetscInt q, d, e, fc, f; 9737 9738 if (debug) { 9739 char title[1024]; 9740 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9741 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9742 } 9743 for (q = 0; q < numQuadPoints; ++q) { 9744 for (d = 0; d < dim; d++) { 9745 coords[d] = v0[d]; 9746 for (e = 0; e < dim; e++) { 9747 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9748 } 9749 } 9750 for (fc = 0; fc < numBasisComps; ++fc) { 9751 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9752 PetscReal interpolant = 0.0; 9753 for (f = 0; f < numBasisFuncs; ++f) { 9754 const PetscInt fidx = f*numBasisComps+fc; 9755 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9756 } 9757 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9758 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9759 } 9760 } 9761 comp += numBasisComps; 9762 fieldOffset += numBasisFuncs*numBasisComps; 9763 } 9764 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9765 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9766 localDiff += elemDiff; 9767 } 9768 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9769 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9770 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9771 *diff = PetscSqrtReal(*diff); 9772 PetscFunctionReturn(0); 9773 } 9774 9775 #undef __FUNCT__ 9776 #define __FUNCT__ "DMPlexComputeResidualFEM" 9777 /*@ 9778 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9779 9780 Input Parameters: 9781 + dm - The mesh 9782 . X - Local input vector 9783 - user - The user context 9784 9785 Output Parameter: 9786 . F - Local output vector 9787 9788 Note: 9789 The second member of the user context must be an FEMContext. 9790 9791 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9792 like a GPU, or vectorize on a multicore machine. 9793 9794 .seealso: DMPlexComputeJacobianActionFEM() 9795 */ 9796 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9797 { 9798 DM_Plex *mesh = (DM_Plex*) dm->data; 9799 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9800 PetscQuadrature *quad = fem->quad; 9801 PetscSection section; 9802 PetscReal *v0, *J, *invJ, *detJ; 9803 PetscScalar *elemVec, *u; 9804 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9805 PetscInt cellDof = 0, numComponents = 0; 9806 PetscErrorCode ierr; 9807 9808 PetscFunctionBegin; 9809 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9810 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9811 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9812 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9813 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9814 numCells = cEnd - cStart; 9815 for (field = 0; field < numFields; ++field) { 9816 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9817 numComponents += quad[field].numComponents; 9818 } 9819 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9820 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9821 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); 9822 for (c = cStart; c < cEnd; ++c) { 9823 const PetscScalar *x; 9824 PetscInt i; 9825 9826 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9827 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9828 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9829 9830 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9831 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9832 } 9833 for (field = 0; field < numFields; ++field) { 9834 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9835 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9836 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9837 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9838 /* Conforming batches */ 9839 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9840 PetscInt numBlocks = 1; 9841 PetscInt batchSize = numBlocks * blockSize; 9842 PetscInt numBatches = numBatchesTmp; 9843 PetscInt numChunks = numCells / (numBatches*batchSize); 9844 /* Remainder */ 9845 PetscInt numRemainder = numCells % (numBatches * batchSize); 9846 PetscInt offset = numCells - numRemainder; 9847 9848 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9849 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9850 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9851 } 9852 for (c = cStart; c < cEnd; ++c) { 9853 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9854 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9855 } 9856 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9857 if (mesh->printFEM) { 9858 PetscMPIInt rank, numProcs; 9859 PetscInt p; 9860 9861 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9862 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9863 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9864 for (p = 0; p < numProcs; ++p) { 9865 if (p == rank) { 9866 Vec f; 9867 9868 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9869 ierr = VecCopy(F, f);CHKERRQ(ierr); 9870 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9871 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9872 ierr = VecDestroy(&f);CHKERRQ(ierr); 9873 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9874 } 9875 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9876 } 9877 } 9878 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9879 PetscFunctionReturn(0); 9880 } 9881 9882 #undef __FUNCT__ 9883 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9884 /*@C 9885 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9886 9887 Input Parameters: 9888 + dm - The mesh 9889 . J - The Jacobian shell matrix 9890 . X - Local input vector 9891 - user - The user context 9892 9893 Output Parameter: 9894 . F - Local output vector 9895 9896 Note: 9897 The second member of the user context must be an FEMContext. 9898 9899 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9900 like a GPU, or vectorize on a multicore machine. 9901 9902 .seealso: DMPlexComputeResidualFEM() 9903 */ 9904 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9905 { 9906 DM_Plex *mesh = (DM_Plex*) dm->data; 9907 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9908 PetscQuadrature *quad = fem->quad; 9909 PetscSection section; 9910 JacActionCtx *jctx; 9911 PetscReal *v0, *J, *invJ, *detJ; 9912 PetscScalar *elemVec, *u, *a; 9913 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9914 PetscInt cellDof = 0; 9915 PetscErrorCode ierr; 9916 9917 PetscFunctionBegin; 9918 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9919 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9920 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9921 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9922 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9923 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9924 numCells = cEnd - cStart; 9925 for (field = 0; field < numFields; ++field) { 9926 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9927 } 9928 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9929 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); 9930 for (c = cStart; c < cEnd; ++c) { 9931 const PetscScalar *x; 9932 PetscInt i; 9933 9934 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9935 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9936 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9937 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9938 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9939 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9940 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9941 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9942 } 9943 for (field = 0; field < numFields; ++field) { 9944 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9945 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9946 /* Conforming batches */ 9947 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9948 PetscInt numBlocks = 1; 9949 PetscInt batchSize = numBlocks * blockSize; 9950 PetscInt numBatches = numBatchesTmp; 9951 PetscInt numChunks = numCells / (numBatches*batchSize); 9952 /* Remainder */ 9953 PetscInt numRemainder = numCells % (numBatches * batchSize); 9954 PetscInt offset = numCells - numRemainder; 9955 9956 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); 9957 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], 9958 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9959 } 9960 for (c = cStart; c < cEnd; ++c) { 9961 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9962 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9963 } 9964 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9965 if (mesh->printFEM) { 9966 PetscMPIInt rank, numProcs; 9967 PetscInt p; 9968 9969 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9970 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9971 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9972 for (p = 0; p < numProcs; ++p) { 9973 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9974 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9975 } 9976 } 9977 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9978 PetscFunctionReturn(0); 9979 } 9980 9981 #undef __FUNCT__ 9982 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9983 /*@ 9984 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9985 9986 Input Parameters: 9987 + dm - The mesh 9988 . X - Local input vector 9989 - user - The user context 9990 9991 Output Parameter: 9992 . Jac - Jacobian matrix 9993 9994 Note: 9995 The second member of the user context must be an FEMContext. 9996 9997 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9998 like a GPU, or vectorize on a multicore machine. 9999 10000 .seealso: FormFunctionLocal() 10001 */ 10002 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10003 { 10004 DM_Plex *mesh = (DM_Plex*) dm->data; 10005 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10006 PetscQuadrature *quad = fem->quad; 10007 PetscSection section; 10008 PetscReal *v0, *J, *invJ, *detJ; 10009 PetscScalar *elemMat, *u; 10010 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10011 PetscInt cellDof = 0, numComponents = 0; 10012 PetscBool isShell; 10013 PetscErrorCode ierr; 10014 10015 PetscFunctionBegin; 10016 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10017 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10018 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10019 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10020 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10021 numCells = cEnd - cStart; 10022 for (field = 0; field < numFields; ++field) { 10023 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10024 numComponents += quad[field].numComponents; 10025 } 10026 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10027 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10028 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); 10029 for (c = cStart; c < cEnd; ++c) { 10030 const PetscScalar *x; 10031 PetscInt i; 10032 10033 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10034 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10035 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 10036 10037 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10038 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 10039 } 10040 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10041 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10042 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10043 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10044 PetscInt fieldJ; 10045 10046 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10047 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10048 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10049 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10050 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10051 /* Conforming batches */ 10052 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10053 PetscInt numBlocks = 1; 10054 PetscInt batchSize = numBlocks * blockSize; 10055 PetscInt numBatches = numBatchesTmp; 10056 PetscInt numChunks = numCells / (numBatches*batchSize); 10057 /* Remainder */ 10058 PetscInt numRemainder = numCells % (numBatches * batchSize); 10059 PetscInt offset = numCells - numRemainder; 10060 10061 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10062 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10063 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10064 } 10065 } 10066 for (c = cStart; c < cEnd; ++c) { 10067 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10068 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10069 } 10070 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10071 10072 /* Assemble matrix, using the 2-step process: 10073 MatAssemblyBegin(), MatAssemblyEnd(). */ 10074 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10075 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10076 10077 if (mesh->printFEM) { 10078 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10079 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10080 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10081 } 10082 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10083 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10084 if (isShell) { 10085 JacActionCtx *jctx; 10086 10087 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10088 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10089 } 10090 *str = SAME_NONZERO_PATTERN; 10091 PetscFunctionReturn(0); 10092 } 10093 10094 10095 #undef __FUNCT__ 10096 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10097 /*@C 10098 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10099 the local section and an SF describing the section point overlap. 10100 10101 Input Parameters: 10102 + s - The PetscSection for the local field layout 10103 . sf - The SF describing parallel layout of the section points 10104 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10105 . label - The label specifying the points 10106 - labelValue - The label stratum specifying the points 10107 10108 Output Parameter: 10109 . gsection - The PetscSection for the global field layout 10110 10111 Note: This gives negative sizes and offsets to points not owned by this process 10112 10113 Level: developer 10114 10115 .seealso: PetscSectionCreate() 10116 @*/ 10117 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10118 { 10119 PetscInt *neg; 10120 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10121 PetscErrorCode ierr; 10122 10123 PetscFunctionBegin; 10124 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10125 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10126 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10127 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10128 /* Mark ghost points with negative dof */ 10129 for (p = pStart; p < pEnd; ++p) { 10130 PetscInt value; 10131 10132 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10133 if (value != labelValue) continue; 10134 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10135 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10136 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10137 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10138 neg[p-pStart] = -(dof+1); 10139 } 10140 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10141 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 10142 if (nroots >= 0) { 10143 if (nroots > pEnd - pStart) { 10144 PetscInt *tmpDof; 10145 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10146 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10147 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10148 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10149 for (p = pStart; p < pEnd; ++p) { 10150 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 10151 } 10152 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10153 } else { 10154 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10155 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10156 } 10157 } 10158 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10159 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10160 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10161 10162 (*gsection)->atlasOff[p] = off; 10163 10164 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10165 } 10166 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10167 globalOff -= off; 10168 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10169 (*gsection)->atlasOff[p] += globalOff; 10170 10171 neg[p] = -((*gsection)->atlasOff[p]+1); 10172 } 10173 /* Put in negative offsets for ghost points */ 10174 if (nroots >= 0) { 10175 if (nroots > pEnd - pStart) { 10176 PetscInt *tmpOff; 10177 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10178 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10179 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10180 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10181 for (p = pStart; p < pEnd; ++p) { 10182 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 10183 } 10184 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10185 } else { 10186 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10187 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10188 } 10189 } 10190 ierr = PetscFree(neg);CHKERRQ(ierr); 10191 PetscFunctionReturn(0); 10192 } 10193