1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/vecimpl.h> 4 5 /* Logging support */ 6 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 7 8 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 9 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 10 11 #undef __FUNCT__ 12 #define __FUNCT__ "VecView_Plex_Local" 13 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 14 { 15 DM dm; 16 PetscBool isvtk; 17 PetscErrorCode ierr; 18 19 PetscFunctionBegin; 20 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 21 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 22 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 23 if (isvtk) { 24 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 25 PetscSection section; 26 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 27 28 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 29 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 33 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 34 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 35 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 36 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 37 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 38 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 39 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 40 } else if (cdof && vdof) { 41 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 42 } else if (cdof) { 43 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 44 * vector or just happens to have the same number of dofs as the dimension. */ 45 if (cdof == dim) { 46 ft = PETSC_VTK_CELL_VECTOR_FIELD; 47 } else { 48 ft = PETSC_VTK_CELL_FIELD; 49 } 50 } else if (vdof) { 51 if (vdof == dim) { 52 ft = PETSC_VTK_POINT_VECTOR_FIELD; 53 } else { 54 ft = PETSC_VTK_POINT_FIELD; 55 } 56 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 57 58 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 61 } else { 62 PetscBool isseq; 63 64 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 65 if (isseq) { 66 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 67 } else { 68 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 69 } 70 } 71 PetscFunctionReturn(0); 72 } 73 74 #undef __FUNCT__ 75 #define __FUNCT__ "VecView_Plex" 76 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 77 { 78 DM dm; 79 PetscBool isvtk; 80 PetscErrorCode ierr; 81 82 PetscFunctionBegin; 83 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 84 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 85 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 86 if (isvtk) { 87 Vec locv; 88 const char *name; 89 90 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 91 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 92 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 96 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 97 } else { 98 PetscBool isseq; 99 100 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 101 if (isseq) { 102 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 103 } else { 104 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 105 } 106 } 107 PetscFunctionReturn(0); 108 } 109 110 #undef __FUNCT__ 111 #define __FUNCT__ "DMPlexView_Ascii" 112 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 113 { 114 DM_Plex *mesh = (DM_Plex*) dm->data; 115 DM cdm; 116 DMLabel markers; 117 PetscSection coordSection; 118 Vec coordinates; 119 PetscViewerFormat format; 120 PetscErrorCode ierr; 121 122 PetscFunctionBegin; 123 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 124 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 125 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 126 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 127 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 128 const char *name; 129 PetscInt maxConeSize, maxSupportSize; 130 PetscInt pStart, pEnd, p; 131 PetscMPIInt rank, size; 132 133 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 134 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 135 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 136 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 137 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 138 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 139 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 140 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 143 for (p = pStart; p < pEnd; ++p) { 144 PetscInt dof, off, s; 145 146 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 147 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 148 for (s = off; s < off+dof; ++s) { 149 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 150 } 151 } 152 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 153 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 154 for (p = pStart; p < pEnd; ++p) { 155 PetscInt dof, off, c; 156 157 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 158 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 159 for (c = off; c < off+dof; ++c) { 160 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 161 } 162 } 163 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 164 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 165 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 166 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 167 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 168 if (size > 1) { 169 PetscSF sf; 170 171 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 172 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 173 } 174 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 175 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 176 const char *name; 177 const char *colors[3] = {"red", "blue", "green"}; 178 const int numColors = 3; 179 PetscReal scale = 2.0; 180 PetscScalar *coords; 181 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 182 PetscMPIInt rank, size; 183 184 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 185 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 186 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 187 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 188 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 189 ierr = PetscViewerASCIIPrintf(viewer, "\ 190 \\documentclass[crop,multi=false]{standalone}\n\n\ 191 \\usepackage{tikz}\n\ 192 \\usepackage{pgflibraryshapes}\n\ 193 \\usetikzlibrary{backgrounds}\n\ 194 \\usetikzlibrary{arrows}\n\ 195 \\begin{document}\n\ 196 \\section{%s}\n\ 197 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 198 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 199 for (p = 0; p < size; ++p) { 200 if (p > 0 && p == size-1) { 201 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 202 } else if (p > 0) { 203 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 204 } 205 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 206 } 207 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 208 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 209 /* Plot vertices */ 210 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 211 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 212 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 213 for (v = vStart; v < vEnd; ++v) { 214 PetscInt off, dof, d; 215 216 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 217 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 218 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 219 for (d = 0; d < dof; ++d) { 220 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 221 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 222 } 223 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 224 } 225 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 226 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 227 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 228 /* Plot edges */ 229 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 230 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 231 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 232 for (e = eStart; e < eEnd; ++e) { 233 const PetscInt *cone; 234 PetscInt coneSize, offA, offB, dof, d; 235 236 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 237 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 238 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 239 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 240 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 242 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 243 for (d = 0; d < dof; ++d) { 244 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 245 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 246 } 247 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 248 } 249 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 250 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 251 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 252 /* Plot cells */ 253 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 254 for (c = cStart; c < cEnd; ++c) { 255 PetscInt *closure = NULL; 256 PetscInt closureSize, firstPoint = -1; 257 258 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 259 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 260 for (p = 0; p < closureSize*2; p += 2) { 261 const PetscInt point = closure[p]; 262 263 if ((point < vStart) || (point >= vEnd)) continue; 264 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 265 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 266 if (firstPoint < 0) firstPoint = point; 267 } 268 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 269 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 270 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 271 } 272 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 273 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 275 } else { 276 MPI_Comm comm = ((PetscObject) dm)->comm; 277 PetscInt *sizes; 278 PetscInt locDepth, depth, dim, d; 279 PetscInt pStart, pEnd, p; 280 PetscMPIInt size; 281 282 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 283 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 284 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 285 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 286 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 287 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 288 if (depth == 1) { 289 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 290 pEnd = pEnd - pStart; 291 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 292 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 293 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 294 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 295 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 296 pEnd = pEnd - pStart; 297 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 298 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 299 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 300 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 301 } else { 302 for (d = 0; d <= dim; d++) { 303 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 304 pEnd = pEnd - pStart; 305 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 306 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 307 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 308 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 309 } 310 } 311 ierr = PetscFree(sizes);CHKERRQ(ierr); 312 } 313 PetscFunctionReturn(0); 314 } 315 316 #undef __FUNCT__ 317 #define __FUNCT__ "DMView_Plex" 318 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 319 { 320 PetscBool iascii, isbinary; 321 PetscErrorCode ierr; 322 323 PetscFunctionBegin; 324 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 325 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 326 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 327 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 328 if (iascii) { 329 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 330 #if 0 331 } else if (isbinary) { 332 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 333 #endif 334 } 335 PetscFunctionReturn(0); 336 } 337 338 #undef __FUNCT__ 339 #define __FUNCT__ "DMDestroy_Plex" 340 PetscErrorCode DMDestroy_Plex(DM dm) 341 { 342 DM_Plex *mesh = (DM_Plex*) dm->data; 343 DMLabel next = mesh->labels; 344 PetscErrorCode ierr; 345 346 PetscFunctionBegin; 347 if (--mesh->refct > 0) PetscFunctionReturn(0); 348 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 349 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 350 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 351 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 353 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 354 while (next) { 355 DMLabel tmp = next->next; 356 357 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 358 next = tmp; 359 } 360 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 361 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 362 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 363 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 364 ierr = PetscFree(mesh);CHKERRQ(ierr); 365 PetscFunctionReturn(0); 366 } 367 368 #undef __FUNCT__ 369 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 370 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 371 { 372 const PetscInt *support = NULL; 373 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 374 PetscErrorCode ierr; 375 376 PetscFunctionBegin; 377 if (useClosure) { 378 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 379 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 380 for (s = 0; s < supportSize; ++s) { 381 const PetscInt *cone = NULL; 382 PetscInt coneSize, c, q; 383 384 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 385 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 386 for (c = 0; c < coneSize; ++c) { 387 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 388 if (cone[c] == adj[q]) break; 389 } 390 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 391 } 392 } 393 } else { 394 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 395 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 396 for (s = 0; s < supportSize; ++s) { 397 const PetscInt *cone = NULL; 398 PetscInt coneSize, c, q; 399 400 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 401 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 402 for (c = 0; c < coneSize; ++c) { 403 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 404 if (cone[c] == adj[q]) break; 405 } 406 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 407 } 408 } 409 } 410 *adjSize = numAdj; 411 PetscFunctionReturn(0); 412 } 413 414 #undef __FUNCT__ 415 #define __FUNCT__ "DMPlexGetAdjacency_Private" 416 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 417 { 418 const PetscInt *star = tmpClosure; 419 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 420 PetscErrorCode ierr; 421 422 PetscFunctionBegin; 423 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 424 for (s = 2; s < starSize*2; s += 2) { 425 const PetscInt *closure = NULL; 426 PetscInt closureSize, c, q; 427 428 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 429 for (c = 0; c < closureSize*2; c += 2) { 430 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 431 if (closure[c] == adj[q]) break; 432 } 433 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 434 } 435 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 436 } 437 *adjSize = numAdj; 438 PetscFunctionReturn(0); 439 } 440 441 #undef __FUNCT__ 442 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 443 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 444 { 445 DM_Plex *mesh = (DM_Plex*) dm->data; 446 447 PetscFunctionBegin; 448 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 449 mesh->preallocCenterDim = preallocCenterDim; 450 PetscFunctionReturn(0); 451 } 452 453 #undef __FUNCT__ 454 #define __FUNCT__ "DMPlexPreallocateOperator" 455 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 456 { 457 DM_Plex *mesh = (DM_Plex*) dm->data; 458 MPI_Comm comm = ((PetscObject) dm)->comm; 459 PetscSF sf, sfDof, sfAdj; 460 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 461 PetscInt nleaves, l, p; 462 const PetscInt *leaves; 463 const PetscSFNode *remotes; 464 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 465 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 466 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 467 PetscLayout rLayout; 468 PetscInt locRows, rStart, rEnd, r; 469 PetscMPIInt size; 470 PetscBool useClosure, debug = PETSC_FALSE; 471 PetscErrorCode ierr; 472 473 PetscFunctionBegin; 474 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 475 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 476 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 477 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 478 /* Create dof SF based on point SF */ 479 if (debug) { 480 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 481 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 482 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 483 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 484 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 485 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 486 } 487 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 488 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 489 if (debug) { 490 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 491 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 492 } 493 /* Create section for dof adjacency (dof ==> # adj dof) */ 494 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 495 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 496 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 497 if (mesh->preallocCenterDim == dim) { 498 useClosure = PETSC_FALSE; 499 } else if (mesh->preallocCenterDim == 0) { 500 useClosure = PETSC_TRUE; 501 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 502 503 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 504 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 505 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 506 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 507 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 508 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 509 /* Fill in the ghost dofs on the interface */ 510 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 511 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 512 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 513 514 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 515 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 516 517 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 518 519 /* 520 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 521 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 522 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 523 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 524 Create sfAdj connecting rootSectionAdj and leafSectionAdj 525 3. Visit unowned points on interface, write adjacencies to adj 526 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 527 4. Visit owned points on interface, write adjacencies to rootAdj 528 Remove redundancy in rootAdj 529 ** The last two traversals use transitive closure 530 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 531 Allocate memory addressed by sectionAdj (cols) 532 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 533 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 534 */ 535 536 for (l = 0; l < nleaves; ++l) { 537 PetscInt dof, off, d, q; 538 PetscInt p = leaves[l], numAdj = maxAdjSize; 539 540 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 541 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 542 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 543 for (q = 0; q < numAdj; ++q) { 544 PetscInt ndof, ncdof; 545 546 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 547 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 548 for (d = off; d < off+dof; ++d) { 549 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 550 } 551 } 552 } 553 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 554 if (debug) { 555 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 556 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 557 } 558 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 559 if (size > 1) { 560 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 561 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 562 } 563 if (debug) { 564 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 565 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 566 } 567 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 568 for (p = pStart; p < pEnd; ++p) { 569 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 570 571 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 572 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 573 if (!dof) continue; 574 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 575 if (adof <= 0) continue; 576 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 577 for (q = 0; q < numAdj; ++q) { 578 PetscInt ndof, ncdof; 579 580 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 581 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 582 for (d = off; d < off+dof; ++d) { 583 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 584 } 585 } 586 } 587 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 588 if (debug) { 589 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 590 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 591 } 592 /* Create adj SF based on dof SF */ 593 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 594 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 595 if (debug) { 596 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 597 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 598 } 599 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 600 /* Create leaf adjacency */ 601 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 602 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 603 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 604 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 605 for (l = 0; l < nleaves; ++l) { 606 PetscInt dof, off, d, q; 607 PetscInt p = leaves[l], numAdj = maxAdjSize; 608 609 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 610 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 611 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 612 for (d = off; d < off+dof; ++d) { 613 PetscInt aoff, i = 0; 614 615 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 616 for (q = 0; q < numAdj; ++q) { 617 PetscInt ndof, ncdof, ngoff, nd; 618 619 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 620 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 621 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 622 for (nd = 0; nd < ndof-ncdof; ++nd) { 623 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 624 ++i; 625 } 626 } 627 } 628 } 629 /* Debugging */ 630 if (debug) { 631 IS tmp; 632 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 633 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 634 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 635 } 636 /* Gather adjacenct indices to root */ 637 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 638 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 639 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 640 if (size > 1) { 641 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 642 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 643 } 644 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 645 ierr = PetscFree(adj);CHKERRQ(ierr); 646 /* Debugging */ 647 if (debug) { 648 IS tmp; 649 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 650 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 651 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 652 } 653 /* Add in local adjacency indices for owned dofs on interface (roots) */ 654 for (p = pStart; p < pEnd; ++p) { 655 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 656 657 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 658 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 659 if (!dof) continue; 660 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 661 if (adof <= 0) continue; 662 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 663 for (d = off; d < off+dof; ++d) { 664 PetscInt adof, aoff, i; 665 666 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 667 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 668 i = adof-1; 669 for (q = 0; q < numAdj; ++q) { 670 PetscInt ndof, ncdof, ngoff, nd; 671 672 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 673 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 674 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 675 for (nd = 0; nd < ndof-ncdof; ++nd) { 676 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 677 --i; 678 } 679 } 680 } 681 } 682 /* Debugging */ 683 if (debug) { 684 IS tmp; 685 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 686 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 687 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 688 } 689 /* Compress indices */ 690 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 691 for (p = pStart; p < pEnd; ++p) { 692 PetscInt dof, cdof, off, d; 693 PetscInt adof, aoff; 694 695 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 696 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 697 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 698 if (!dof) continue; 699 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 700 if (adof <= 0) continue; 701 for (d = off; d < off+dof-cdof; ++d) { 702 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 703 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 704 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 705 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 706 } 707 } 708 /* Debugging */ 709 if (debug) { 710 IS tmp; 711 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 712 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 713 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 714 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 715 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 716 } 717 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 718 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 719 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 720 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 721 for (p = pStart; p < pEnd; ++p) { 722 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 723 PetscBool found = PETSC_TRUE; 724 725 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 726 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 727 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 728 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 729 for (d = 0; d < dof-cdof; ++d) { 730 PetscInt ldof, rdof; 731 732 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 733 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 734 if (ldof > 0) { 735 /* We do not own this point */ 736 } else if (rdof > 0) { 737 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 738 } else { 739 found = PETSC_FALSE; 740 } 741 } 742 if (found) continue; 743 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 744 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 745 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 746 for (q = 0; q < numAdj; ++q) { 747 PetscInt ndof, ncdof, noff; 748 749 /* Adjacent points may not be in the section chart */ 750 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 751 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 752 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 753 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 754 for (d = goff; d < goff+dof-cdof; ++d) { 755 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 756 } 757 } 758 } 759 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 760 if (debug) { 761 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 762 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 763 } 764 /* Get adjacent indices */ 765 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 766 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 767 for (p = pStart; p < pEnd; ++p) { 768 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 769 PetscBool found = PETSC_TRUE; 770 771 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 772 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 773 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 774 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 775 for (d = 0; d < dof-cdof; ++d) { 776 PetscInt ldof, rdof; 777 778 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 779 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 780 if (ldof > 0) { 781 /* We do not own this point */ 782 } else if (rdof > 0) { 783 PetscInt aoff, roff; 784 785 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 786 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 787 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 788 } else { 789 found = PETSC_FALSE; 790 } 791 } 792 if (found) continue; 793 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 794 for (d = goff; d < goff+dof-cdof; ++d) { 795 PetscInt adof, aoff, i = 0; 796 797 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 798 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 799 for (q = 0; q < numAdj; ++q) { 800 PetscInt ndof, ncdof, ngoff, nd; 801 const PetscInt *ncind; 802 803 /* Adjacent points may not be in the section chart */ 804 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 805 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 806 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 807 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 808 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 809 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 810 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 811 } 812 } 813 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); 814 } 815 } 816 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 817 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 818 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 819 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 820 /* Debugging */ 821 if (debug) { 822 IS tmp; 823 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 824 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 825 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 826 } 827 /* Create allocation vectors from adjacency graph */ 828 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 829 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 830 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 831 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 832 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 833 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 834 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 835 /* Only loop over blocks of rows */ 836 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 837 for (r = rStart/bs; r < rEnd/bs; ++r) { 838 const PetscInt row = r*bs; 839 PetscInt numCols, cStart, c; 840 841 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 842 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 843 for (c = cStart; c < cStart+numCols; ++c) { 844 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 845 ++dnz[r-rStart]; 846 if (cols[c] >= row) ++dnzu[r-rStart]; 847 } else { 848 ++onz[r-rStart]; 849 if (cols[c] >= row) ++onzu[r-rStart]; 850 } 851 } 852 } 853 if (bs > 1) { 854 for (r = 0; r < locRows/bs; ++r) { 855 dnz[r] /= bs; 856 onz[r] /= bs; 857 dnzu[r] /= bs; 858 onzu[r] /= bs; 859 } 860 } 861 /* Set matrix pattern */ 862 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 863 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 864 /* Fill matrix with zeros */ 865 if (fillMatrix) { 866 PetscScalar *values; 867 PetscInt maxRowLen = 0; 868 869 for (r = rStart; r < rEnd; ++r) { 870 PetscInt len; 871 872 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 873 maxRowLen = PetscMax(maxRowLen, len); 874 } 875 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 876 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 877 for (r = rStart; r < rEnd; ++r) { 878 PetscInt numCols, cStart; 879 880 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 881 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 882 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 883 } 884 ierr = PetscFree(values);CHKERRQ(ierr); 885 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 886 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 887 } 888 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 889 ierr = PetscFree(cols);CHKERRQ(ierr); 890 PetscFunctionReturn(0); 891 } 892 893 #if 0 894 #undef __FUNCT__ 895 #define __FUNCT__ "DMPlexPreallocateOperator_2" 896 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 897 { 898 PetscInt *tmpClosure,*tmpAdj,*visits; 899 PetscInt c,cStart,cEnd,pStart,pEnd; 900 PetscErrorCode ierr; 901 902 PetscFunctionBegin; 903 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 904 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 905 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 906 907 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 908 909 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 910 npoints = pEnd - pStart; 911 912 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 913 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 914 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 915 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 916 for (c=cStart; c<cEnd; c++) { 917 PetscInt *support = tmpClosure; 918 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 919 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 920 } 921 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 922 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 923 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 924 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 925 926 ierr = PetscSFGetRanks();CHKERRQ(ierr); 927 928 929 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 930 for (c=cStart; c<cEnd; c++) { 931 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 932 /* 933 Depth-first walk of transitive closure. 934 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. 935 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 936 */ 937 } 938 939 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 940 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 941 PetscFunctionReturn(0); 942 } 943 #endif 944 945 #undef __FUNCT__ 946 #define __FUNCT__ "DMCreateMatrix_Plex" 947 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 948 { 949 PetscSection section, sectionGlobal; 950 PetscInt bs = -1; 951 PetscInt localSize; 952 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 953 PetscErrorCode ierr; 954 955 PetscFunctionBegin; 956 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 957 ierr = MatInitializePackage(NULL);CHKERRQ(ierr); 958 #endif 959 if (!mtype) mtype = MATAIJ; 960 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 961 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 962 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 963 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 964 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 965 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 966 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 967 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 974 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 975 /* Check for symmetric storage */ 976 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 977 if (isSymmetric) { 978 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 979 } 980 if (!isShell) { 981 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 982 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 983 984 if (bs < 0) { 985 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 986 PetscInt pStart, pEnd, p, dof, cdof; 987 988 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 989 for (p = pStart; p < pEnd; ++p) { 990 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 991 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 992 if (dof-cdof) { 993 if (bs < 0) { 994 bs = dof-cdof; 995 } else if (bs != dof-cdof) { 996 /* Layout does not admit a pointwise block size */ 997 bs = 1; 998 break; 999 } 1000 } 1001 } 1002 /* Must have same blocksize on all procs (some might have no points) */ 1003 bsLocal = bs; 1004 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1005 bsLocal = bs < 0 ? bsMax : bs; 1006 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1007 if (bsMin != bsMax) { 1008 bs = 1; 1009 } else { 1010 bs = bsMax; 1011 } 1012 } else { 1013 bs = 1; 1014 } 1015 } 1016 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1017 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1018 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1019 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1020 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1021 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1022 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1023 } 1024 PetscFunctionReturn(0); 1025 } 1026 1027 #undef __FUNCT__ 1028 #define __FUNCT__ "DMPlexGetDimension" 1029 /*@ 1030 DMPlexGetDimension - Return the topological mesh dimension 1031 1032 Not collective 1033 1034 Input Parameter: 1035 . mesh - The DMPlex 1036 1037 Output Parameter: 1038 . dim - The topological mesh dimension 1039 1040 Level: beginner 1041 1042 .seealso: DMPlexCreate() 1043 @*/ 1044 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1045 { 1046 DM_Plex *mesh = (DM_Plex*) dm->data; 1047 1048 PetscFunctionBegin; 1049 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1050 PetscValidPointer(dim, 2); 1051 *dim = mesh->dim; 1052 PetscFunctionReturn(0); 1053 } 1054 1055 #undef __FUNCT__ 1056 #define __FUNCT__ "DMPlexSetDimension" 1057 /*@ 1058 DMPlexSetDimension - Set the topological mesh dimension 1059 1060 Collective on mesh 1061 1062 Input Parameters: 1063 + mesh - The DMPlex 1064 - dim - The topological mesh dimension 1065 1066 Level: beginner 1067 1068 .seealso: DMPlexCreate() 1069 @*/ 1070 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1071 { 1072 DM_Plex *mesh = (DM_Plex*) dm->data; 1073 1074 PetscFunctionBegin; 1075 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1076 PetscValidLogicalCollectiveInt(dm, dim, 2); 1077 mesh->dim = dim; 1078 mesh->preallocCenterDim = dim; 1079 PetscFunctionReturn(0); 1080 } 1081 1082 #undef __FUNCT__ 1083 #define __FUNCT__ "DMPlexGetChart" 1084 /*@ 1085 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1086 1087 Not collective 1088 1089 Input Parameter: 1090 . mesh - The DMPlex 1091 1092 Output Parameters: 1093 + pStart - The first mesh point 1094 - pEnd - The upper bound for mesh points 1095 1096 Level: beginner 1097 1098 .seealso: DMPlexCreate(), DMPlexSetChart() 1099 @*/ 1100 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1101 { 1102 DM_Plex *mesh = (DM_Plex*) dm->data; 1103 PetscErrorCode ierr; 1104 1105 PetscFunctionBegin; 1106 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1107 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1108 PetscFunctionReturn(0); 1109 } 1110 1111 #undef __FUNCT__ 1112 #define __FUNCT__ "DMPlexSetChart" 1113 /*@ 1114 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1115 1116 Not collective 1117 1118 Input Parameters: 1119 + mesh - The DMPlex 1120 . pStart - The first mesh point 1121 - pEnd - The upper bound for mesh points 1122 1123 Output Parameters: 1124 1125 Level: beginner 1126 1127 .seealso: DMPlexCreate(), DMPlexGetChart() 1128 @*/ 1129 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1130 { 1131 DM_Plex *mesh = (DM_Plex*) dm->data; 1132 PetscErrorCode ierr; 1133 1134 PetscFunctionBegin; 1135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1136 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1137 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1138 PetscFunctionReturn(0); 1139 } 1140 1141 #undef __FUNCT__ 1142 #define __FUNCT__ "DMPlexGetConeSize" 1143 /*@ 1144 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1145 1146 Not collective 1147 1148 Input Parameters: 1149 + mesh - The DMPlex 1150 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1151 1152 Output Parameter: 1153 . size - The cone size for point p 1154 1155 Level: beginner 1156 1157 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1158 @*/ 1159 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1160 { 1161 DM_Plex *mesh = (DM_Plex*) dm->data; 1162 PetscErrorCode ierr; 1163 1164 PetscFunctionBegin; 1165 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1166 PetscValidPointer(size, 3); 1167 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1168 PetscFunctionReturn(0); 1169 } 1170 1171 #undef __FUNCT__ 1172 #define __FUNCT__ "DMPlexSetConeSize" 1173 /*@ 1174 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1175 1176 Not collective 1177 1178 Input Parameters: 1179 + mesh - The DMPlex 1180 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1181 - size - The cone size for point p 1182 1183 Output Parameter: 1184 1185 Note: 1186 This should be called after DMPlexSetChart(). 1187 1188 Level: beginner 1189 1190 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1191 @*/ 1192 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1193 { 1194 DM_Plex *mesh = (DM_Plex*) dm->data; 1195 PetscErrorCode ierr; 1196 1197 PetscFunctionBegin; 1198 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1199 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1200 1201 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1202 PetscFunctionReturn(0); 1203 } 1204 1205 #undef __FUNCT__ 1206 #define __FUNCT__ "DMPlexGetCone" 1207 /*@C 1208 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1209 1210 Not collective 1211 1212 Input Parameters: 1213 + mesh - The DMPlex 1214 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1215 1216 Output Parameter: 1217 . cone - An array of points which are on the in-edges for point p 1218 1219 Level: beginner 1220 1221 Note: 1222 This routine is not available in Fortran. 1223 1224 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1225 @*/ 1226 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1227 { 1228 DM_Plex *mesh = (DM_Plex*) dm->data; 1229 PetscInt off; 1230 PetscErrorCode ierr; 1231 1232 PetscFunctionBegin; 1233 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1234 PetscValidPointer(cone, 3); 1235 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1236 *cone = &mesh->cones[off]; 1237 PetscFunctionReturn(0); 1238 } 1239 1240 #undef __FUNCT__ 1241 #define __FUNCT__ "DMPlexSetCone" 1242 /*@ 1243 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1244 1245 Not collective 1246 1247 Input Parameters: 1248 + mesh - The DMPlex 1249 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1250 - cone - An array of points which are on the in-edges for point p 1251 1252 Output Parameter: 1253 1254 Note: 1255 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1256 1257 Level: beginner 1258 1259 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1260 @*/ 1261 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1262 { 1263 DM_Plex *mesh = (DM_Plex*) dm->data; 1264 PetscInt pStart, pEnd; 1265 PetscInt dof, off, c; 1266 PetscErrorCode ierr; 1267 1268 PetscFunctionBegin; 1269 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1270 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1271 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1272 if (dof) PetscValidPointer(cone, 3); 1273 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1274 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1275 for (c = 0; c < dof; ++c) { 1276 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1277 mesh->cones[off+c] = cone[c]; 1278 } 1279 PetscFunctionReturn(0); 1280 } 1281 1282 #undef __FUNCT__ 1283 #define __FUNCT__ "DMPlexGetConeOrientation" 1284 /*@C 1285 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1286 1287 Not collective 1288 1289 Input Parameters: 1290 + mesh - The DMPlex 1291 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1292 1293 Output Parameter: 1294 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1295 integer giving the prescription for cone traversal. If it is negative, the cone is 1296 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1297 the index of the cone point on which to start. 1298 1299 Level: beginner 1300 1301 Note: 1302 This routine is not available in Fortran. 1303 1304 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1305 @*/ 1306 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1307 { 1308 DM_Plex *mesh = (DM_Plex*) dm->data; 1309 PetscInt off; 1310 PetscErrorCode ierr; 1311 1312 PetscFunctionBegin; 1313 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1314 #if defined(PETSC_USE_DEBUG) 1315 { 1316 PetscInt dof; 1317 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1318 if (dof) PetscValidPointer(coneOrientation, 3); 1319 } 1320 #endif 1321 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1322 1323 *coneOrientation = &mesh->coneOrientations[off]; 1324 PetscFunctionReturn(0); 1325 } 1326 1327 #undef __FUNCT__ 1328 #define __FUNCT__ "DMPlexSetConeOrientation" 1329 /*@ 1330 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1331 1332 Not collective 1333 1334 Input Parameters: 1335 + mesh - The DMPlex 1336 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1337 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1338 integer giving the prescription for cone traversal. If it is negative, the cone is 1339 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1340 the index of the cone point on which to start. 1341 1342 Output Parameter: 1343 1344 Note: 1345 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1346 1347 Level: beginner 1348 1349 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1350 @*/ 1351 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1352 { 1353 DM_Plex *mesh = (DM_Plex*) dm->data; 1354 PetscInt pStart, pEnd; 1355 PetscInt dof, off, c; 1356 PetscErrorCode ierr; 1357 1358 PetscFunctionBegin; 1359 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1360 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1361 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1362 if (dof) PetscValidPointer(coneOrientation, 3); 1363 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1364 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1365 for (c = 0; c < dof; ++c) { 1366 PetscInt cdof, o = coneOrientation[c]; 1367 1368 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1369 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1370 mesh->coneOrientations[off+c] = o; 1371 } 1372 PetscFunctionReturn(0); 1373 } 1374 1375 #undef __FUNCT__ 1376 #define __FUNCT__ "DMPlexInsertCone" 1377 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1378 { 1379 DM_Plex *mesh = (DM_Plex*) dm->data; 1380 PetscInt pStart, pEnd; 1381 PetscInt dof, off; 1382 PetscErrorCode ierr; 1383 1384 PetscFunctionBegin; 1385 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1386 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1387 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1388 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1389 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1390 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1391 if (conePos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1392 mesh->cones[off+conePos] = conePoint; 1393 PetscFunctionReturn(0); 1394 } 1395 1396 #undef __FUNCT__ 1397 #define __FUNCT__ "DMPlexGetSupportSize" 1398 /*@ 1399 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1400 1401 Not collective 1402 1403 Input Parameters: 1404 + mesh - The DMPlex 1405 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1406 1407 Output Parameter: 1408 . size - The support size for point p 1409 1410 Level: beginner 1411 1412 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1413 @*/ 1414 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1415 { 1416 DM_Plex *mesh = (DM_Plex*) dm->data; 1417 PetscErrorCode ierr; 1418 1419 PetscFunctionBegin; 1420 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1421 PetscValidPointer(size, 3); 1422 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1423 PetscFunctionReturn(0); 1424 } 1425 1426 #undef __FUNCT__ 1427 #define __FUNCT__ "DMPlexSetSupportSize" 1428 /*@ 1429 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1430 1431 Not collective 1432 1433 Input Parameters: 1434 + mesh - The DMPlex 1435 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1436 - size - The support size for point p 1437 1438 Output Parameter: 1439 1440 Note: 1441 This should be called after DMPlexSetChart(). 1442 1443 Level: beginner 1444 1445 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1446 @*/ 1447 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1448 { 1449 DM_Plex *mesh = (DM_Plex*) dm->data; 1450 PetscErrorCode ierr; 1451 1452 PetscFunctionBegin; 1453 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1454 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1455 1456 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1457 PetscFunctionReturn(0); 1458 } 1459 1460 #undef __FUNCT__ 1461 #define __FUNCT__ "DMPlexGetSupport" 1462 /*@C 1463 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1464 1465 Not collective 1466 1467 Input Parameters: 1468 + mesh - The DMPlex 1469 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1470 1471 Output Parameter: 1472 . support - An array of points which are on the out-edges for point p 1473 1474 Level: beginner 1475 1476 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1477 @*/ 1478 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1479 { 1480 DM_Plex *mesh = (DM_Plex*) dm->data; 1481 PetscInt off; 1482 PetscErrorCode ierr; 1483 1484 PetscFunctionBegin; 1485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1486 PetscValidPointer(support, 3); 1487 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1488 *support = &mesh->supports[off]; 1489 PetscFunctionReturn(0); 1490 } 1491 1492 #undef __FUNCT__ 1493 #define __FUNCT__ "DMPlexSetSupport" 1494 /*@ 1495 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1496 1497 Not collective 1498 1499 Input Parameters: 1500 + mesh - The DMPlex 1501 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1502 - support - An array of points which are on the in-edges for point p 1503 1504 Output Parameter: 1505 1506 Note: 1507 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1508 1509 Level: beginner 1510 1511 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1512 @*/ 1513 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1514 { 1515 DM_Plex *mesh = (DM_Plex*) dm->data; 1516 PetscInt pStart, pEnd; 1517 PetscInt dof, off, c; 1518 PetscErrorCode ierr; 1519 1520 PetscFunctionBegin; 1521 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1522 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1523 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1524 if (dof) PetscValidPointer(support, 3); 1525 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1526 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1527 for (c = 0; c < dof; ++c) { 1528 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1529 mesh->supports[off+c] = support[c]; 1530 } 1531 PetscFunctionReturn(0); 1532 } 1533 1534 #undef __FUNCT__ 1535 #define __FUNCT__ "DMPlexInsertSupport" 1536 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1537 { 1538 DM_Plex *mesh = (DM_Plex*) dm->data; 1539 PetscInt pStart, pEnd; 1540 PetscInt dof, off; 1541 PetscErrorCode ierr; 1542 1543 PetscFunctionBegin; 1544 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1545 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1546 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1547 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1548 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1549 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1550 if (supportPos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1551 mesh->supports[off+supportPos] = supportPoint; 1552 PetscFunctionReturn(0); 1553 } 1554 1555 #undef __FUNCT__ 1556 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1557 /*@C 1558 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1559 1560 Not collective 1561 1562 Input Parameters: 1563 + mesh - The DMPlex 1564 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1565 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1566 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1567 1568 Output Parameters: 1569 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1570 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1571 1572 Note: 1573 If using internal storage (points is NULL on input), each call overwrites the last output. 1574 1575 Level: beginner 1576 1577 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1578 @*/ 1579 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1580 { 1581 DM_Plex *mesh = (DM_Plex*) dm->data; 1582 PetscInt *closure, *fifo; 1583 const PetscInt *tmp = NULL, *tmpO = NULL; 1584 PetscInt tmpSize, t; 1585 PetscInt depth = 0, maxSize; 1586 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1587 PetscErrorCode ierr; 1588 1589 PetscFunctionBegin; 1590 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1591 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1592 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1593 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1594 if (*points) { 1595 closure = *points; 1596 } else { 1597 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1598 } 1599 closure[0] = p; closure[1] = 0; 1600 /* This is only 1-level */ 1601 if (useCone) { 1602 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1603 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1604 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1605 } else { 1606 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1607 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1608 } 1609 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1610 const PetscInt cp = tmp[t]; 1611 const PetscInt co = tmpO ? tmpO[t] : 0; 1612 1613 closure[closureSize] = cp; 1614 closure[closureSize+1] = co; 1615 fifo[fifoSize] = cp; 1616 fifo[fifoSize+1] = co; 1617 } 1618 while (fifoSize - fifoStart) { 1619 const PetscInt q = fifo[fifoStart]; 1620 const PetscInt o = fifo[fifoStart+1]; 1621 const PetscInt rev = o >= 0 ? 0 : 1; 1622 const PetscInt off = rev ? -(o+1) : o; 1623 1624 if (useCone) { 1625 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1626 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1627 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1628 } else { 1629 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1630 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1631 tmpO = NULL; 1632 } 1633 for (t = 0; t < tmpSize; ++t) { 1634 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1635 const PetscInt cp = tmp[i]; 1636 /* Must propogate orientation */ 1637 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1638 PetscInt c; 1639 1640 /* Check for duplicate */ 1641 for (c = 0; c < closureSize; c += 2) { 1642 if (closure[c] == cp) break; 1643 } 1644 if (c == closureSize) { 1645 closure[closureSize] = cp; 1646 closure[closureSize+1] = co; 1647 fifo[fifoSize] = cp; 1648 fifo[fifoSize+1] = co; 1649 closureSize += 2; 1650 fifoSize += 2; 1651 } 1652 } 1653 fifoStart += 2; 1654 } 1655 if (numPoints) *numPoints = closureSize/2; 1656 if (points) *points = closure; 1657 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1658 PetscFunctionReturn(0); 1659 } 1660 1661 #undef __FUNCT__ 1662 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1663 /*@C 1664 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1665 1666 Not collective 1667 1668 Input Parameters: 1669 + mesh - The DMPlex 1670 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1671 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1672 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1673 1674 Output Parameters: 1675 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1676 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1677 1678 Note: 1679 If not using internal storage (points is not NULL on input), this call is unnecessary 1680 1681 Level: beginner 1682 1683 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1684 @*/ 1685 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1686 { 1687 PetscErrorCode ierr; 1688 1689 PetscFunctionBegin; 1690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1691 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1692 PetscFunctionReturn(0); 1693 } 1694 1695 #undef __FUNCT__ 1696 #define __FUNCT__ "DMPlexGetFaces" 1697 /* 1698 DMPlexGetFaces - 1699 1700 Note: This will only work for cell-vertex meshes. 1701 */ 1702 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1703 { 1704 DM_Plex *mesh = (DM_Plex*) dm->data; 1705 const PetscInt *cone = NULL; 1706 PetscInt depth = 0, dim, coneSize; 1707 PetscErrorCode ierr; 1708 1709 PetscFunctionBegin; 1710 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1711 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1712 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1713 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1714 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1715 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1716 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1717 switch (dim) { 1718 case 2: 1719 switch (coneSize) { 1720 case 3: 1721 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1722 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1723 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1724 *numFaces = 3; 1725 *faceSize = 2; 1726 *faces = mesh->facesTmp; 1727 break; 1728 case 4: 1729 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1730 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1731 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1732 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1733 *numFaces = 4; 1734 *faceSize = 2; 1735 *faces = mesh->facesTmp; 1736 break; 1737 default: 1738 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1739 } 1740 break; 1741 case 3: 1742 switch (coneSize) { 1743 case 3: 1744 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1745 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1746 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1747 *numFaces = 3; 1748 *faceSize = 2; 1749 *faces = mesh->facesTmp; 1750 break; 1751 case 4: 1752 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1753 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1754 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1755 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1756 *numFaces = 4; 1757 *faceSize = 3; 1758 *faces = mesh->facesTmp; 1759 break; 1760 default: 1761 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1762 } 1763 break; 1764 default: 1765 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1766 } 1767 PetscFunctionReturn(0); 1768 } 1769 1770 #undef __FUNCT__ 1771 #define __FUNCT__ "DMPlexGetMaxSizes" 1772 /*@ 1773 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1774 1775 Not collective 1776 1777 Input Parameter: 1778 . mesh - The DMPlex 1779 1780 Output Parameters: 1781 + maxConeSize - The maximum number of in-edges 1782 - maxSupportSize - The maximum number of out-edges 1783 1784 Level: beginner 1785 1786 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1787 @*/ 1788 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1789 { 1790 DM_Plex *mesh = (DM_Plex*) dm->data; 1791 1792 PetscFunctionBegin; 1793 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1794 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1795 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1796 PetscFunctionReturn(0); 1797 } 1798 1799 #undef __FUNCT__ 1800 #define __FUNCT__ "DMSetUp_Plex" 1801 PetscErrorCode DMSetUp_Plex(DM dm) 1802 { 1803 DM_Plex *mesh = (DM_Plex*) dm->data; 1804 PetscInt size; 1805 PetscErrorCode ierr; 1806 1807 PetscFunctionBegin; 1808 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1809 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1810 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1811 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1812 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1813 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1814 if (mesh->maxSupportSize) { 1815 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1816 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1817 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1818 } 1819 PetscFunctionReturn(0); 1820 } 1821 1822 #undef __FUNCT__ 1823 #define __FUNCT__ "DMCreateSubDM_Plex" 1824 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1825 { 1826 PetscSection section, sectionGlobal; 1827 PetscInt *subIndices; 1828 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1829 PetscErrorCode ierr; 1830 1831 PetscFunctionBegin; 1832 if (!numFields) PetscFunctionReturn(0); 1833 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1834 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1835 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1836 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1837 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1838 if (numFields > nF) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1839 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1840 for (p = pStart; p < pEnd; ++p) { 1841 PetscInt gdof; 1842 1843 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1844 if (gdof > 0) { 1845 for (f = 0; f < numFields; ++f) { 1846 PetscInt fdof, fcdof; 1847 1848 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1849 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1850 subSize += fdof-fcdof; 1851 } 1852 } 1853 } 1854 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1855 for (p = pStart; p < pEnd; ++p) { 1856 PetscInt gdof, goff; 1857 1858 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1859 if (gdof > 0) { 1860 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1861 for (f = 0; f < numFields; ++f) { 1862 PetscInt fdof, fcdof, fc, f2, poff = 0; 1863 1864 /* Can get rid of this loop by storing field information in the global section */ 1865 for (f2 = 0; f2 < fields[f]; ++f2) { 1866 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1867 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1868 poff += fdof-fcdof; 1869 } 1870 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1871 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1872 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1873 subIndices[subOff] = goff+poff+fc; 1874 } 1875 } 1876 } 1877 } 1878 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1879 if (subdm) { 1880 PetscSection subsection; 1881 PetscBool haveNull = PETSC_FALSE; 1882 PetscInt f, nf = 0; 1883 1884 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1885 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1886 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1887 for (f = 0; f < numFields; ++f) { 1888 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1889 if ((*subdm)->nullspaceConstructors[f]) { 1890 haveNull = PETSC_TRUE; 1891 nf = f; 1892 } 1893 } 1894 if (haveNull) { 1895 MatNullSpace nullSpace; 1896 1897 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1898 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1899 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1900 } 1901 if (dm->fields) { 1902 if (nF != dm->numFields) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1903 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1904 for (f = 0; f < numFields; ++f) { 1905 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1906 } 1907 if (numFields == 1) { 1908 MatNullSpace space; 1909 Mat pmat; 1910 1911 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1912 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1913 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1914 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1915 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1916 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1917 } 1918 } 1919 } 1920 PetscFunctionReturn(0); 1921 } 1922 1923 #undef __FUNCT__ 1924 #define __FUNCT__ "DMPlexSymmetrize" 1925 /*@ 1926 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1927 1928 Not collective 1929 1930 Input Parameter: 1931 . mesh - The DMPlex 1932 1933 Output Parameter: 1934 1935 Note: 1936 This should be called after all calls to DMPlexSetCone() 1937 1938 Level: beginner 1939 1940 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1941 @*/ 1942 PetscErrorCode DMPlexSymmetrize(DM dm) 1943 { 1944 DM_Plex *mesh = (DM_Plex*) dm->data; 1945 PetscInt *offsets; 1946 PetscInt supportSize; 1947 PetscInt pStart, pEnd, p; 1948 PetscErrorCode ierr; 1949 1950 PetscFunctionBegin; 1951 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1952 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1953 /* Calculate support sizes */ 1954 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1955 for (p = pStart; p < pEnd; ++p) { 1956 PetscInt dof, off, c; 1957 1958 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1959 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1960 for (c = off; c < off+dof; ++c) { 1961 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1962 } 1963 } 1964 for (p = pStart; p < pEnd; ++p) { 1965 PetscInt dof; 1966 1967 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1968 1969 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1970 } 1971 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1972 /* Calculate supports */ 1973 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1974 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1975 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1976 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1977 for (p = pStart; p < pEnd; ++p) { 1978 PetscInt dof, off, c; 1979 1980 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1981 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1982 for (c = off; c < off+dof; ++c) { 1983 const PetscInt q = mesh->cones[c]; 1984 PetscInt offS; 1985 1986 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1987 1988 mesh->supports[offS+offsets[q]] = p; 1989 ++offsets[q]; 1990 } 1991 } 1992 ierr = PetscFree(offsets);CHKERRQ(ierr); 1993 PetscFunctionReturn(0); 1994 } 1995 1996 #undef __FUNCT__ 1997 #define __FUNCT__ "DMPlexSetDepth_Private" 1998 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1999 { 2000 PetscInt d; 2001 PetscErrorCode ierr; 2002 2003 PetscFunctionBegin; 2004 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 2005 if (d < 0) { 2006 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2007 const PetscInt *cone = NULL; 2008 PetscInt dCone; 2009 2010 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2011 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2012 d = dCone+1; 2013 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2014 } 2015 *depth = d; 2016 PetscFunctionReturn(0); 2017 } 2018 2019 #undef __FUNCT__ 2020 #define __FUNCT__ "DMPlexStratify" 2021 /*@ 2022 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2023 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2024 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2025 the DAG. 2026 2027 Not collective 2028 2029 Input Parameter: 2030 . mesh - The DMPlex 2031 2032 Output Parameter: 2033 2034 Notes: 2035 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2036 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2037 2038 This should be called after all calls to DMPlexSymmetrize() 2039 2040 Level: beginner 2041 2042 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2043 @*/ 2044 PetscErrorCode DMPlexStratify(DM dm) 2045 { 2046 DM_Plex *mesh = (DM_Plex*) dm->data; 2047 PetscInt pStart, pEnd, p; 2048 PetscInt numRoots = 0, numLeaves = 0; 2049 PetscErrorCode ierr; 2050 2051 PetscFunctionBegin; 2052 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2053 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2054 /* Calculate depth */ 2055 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2056 /* Initialize roots and count leaves */ 2057 for (p = pStart; p < pEnd; ++p) { 2058 PetscInt coneSize, supportSize; 2059 2060 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2061 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2062 if (!coneSize && supportSize) { 2063 ++numRoots; 2064 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2065 } else if (!supportSize && coneSize) { 2066 ++numLeaves; 2067 } else if (!supportSize && !coneSize) { 2068 /* Isolated points */ 2069 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2070 } 2071 } 2072 if (numRoots + numLeaves == (pEnd - pStart)) { 2073 for (p = pStart; p < pEnd; ++p) { 2074 PetscInt coneSize, supportSize; 2075 2076 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2077 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2078 if (!supportSize && coneSize) { 2079 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2080 } 2081 } 2082 } else { 2083 /* This might be slow since lookup is not fast */ 2084 for (p = pStart; p < pEnd; ++p) { 2085 PetscInt depth; 2086 2087 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2088 } 2089 } 2090 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2091 PetscFunctionReturn(0); 2092 } 2093 2094 #undef __FUNCT__ 2095 #define __FUNCT__ "DMPlexGetJoin" 2096 /*@C 2097 DMPlexGetJoin - Get an array for the join of the set of points 2098 2099 Not Collective 2100 2101 Input Parameters: 2102 + dm - The DMPlex object 2103 . numPoints - The number of input points for the join 2104 - points - The input points 2105 2106 Output Parameters: 2107 + numCoveredPoints - The number of points in the join 2108 - coveredPoints - The points in the join 2109 2110 Level: intermediate 2111 2112 Note: Currently, this is restricted to a single level join 2113 2114 .keywords: mesh 2115 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2116 @*/ 2117 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2118 { 2119 DM_Plex *mesh = (DM_Plex*) dm->data; 2120 PetscInt *join[2]; 2121 PetscInt joinSize, i = 0; 2122 PetscInt dof, off, p, c, m; 2123 PetscErrorCode ierr; 2124 2125 PetscFunctionBegin; 2126 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2127 PetscValidPointer(points, 2); 2128 PetscValidPointer(numCoveredPoints, 3); 2129 PetscValidPointer(coveredPoints, 4); 2130 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2131 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2132 /* Copy in support of first point */ 2133 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2134 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2135 for (joinSize = 0; joinSize < dof; ++joinSize) { 2136 join[i][joinSize] = mesh->supports[off+joinSize]; 2137 } 2138 /* Check each successive support */ 2139 for (p = 1; p < numPoints; ++p) { 2140 PetscInt newJoinSize = 0; 2141 2142 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2143 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2144 for (c = 0; c < dof; ++c) { 2145 const PetscInt point = mesh->supports[off+c]; 2146 2147 for (m = 0; m < joinSize; ++m) { 2148 if (point == join[i][m]) { 2149 join[1-i][newJoinSize++] = point; 2150 break; 2151 } 2152 } 2153 } 2154 joinSize = newJoinSize; 2155 i = 1-i; 2156 } 2157 *numCoveredPoints = joinSize; 2158 *coveredPoints = join[i]; 2159 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2160 PetscFunctionReturn(0); 2161 } 2162 2163 #undef __FUNCT__ 2164 #define __FUNCT__ "DMPlexRestoreJoin" 2165 /*@C 2166 DMPlexRestoreJoin - Restore an array for the join of the set of points 2167 2168 Not Collective 2169 2170 Input Parameters: 2171 + dm - The DMPlex object 2172 . numPoints - The number of input points for the join 2173 - points - The input points 2174 2175 Output Parameters: 2176 + numCoveredPoints - The number of points in the join 2177 - coveredPoints - The points in the join 2178 2179 Level: intermediate 2180 2181 .keywords: mesh 2182 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2183 @*/ 2184 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2185 { 2186 PetscErrorCode ierr; 2187 2188 PetscFunctionBegin; 2189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2190 PetscValidPointer(coveredPoints, 4); 2191 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2192 PetscFunctionReturn(0); 2193 } 2194 2195 #undef __FUNCT__ 2196 #define __FUNCT__ "DMPlexGetFullJoin" 2197 /*@C 2198 DMPlexGetFullJoin - Get an array for the join of the set of points 2199 2200 Not Collective 2201 2202 Input Parameters: 2203 + dm - The DMPlex object 2204 . numPoints - The number of input points for the join 2205 - points - The input points 2206 2207 Output Parameters: 2208 + numCoveredPoints - The number of points in the join 2209 - coveredPoints - The points in the join 2210 2211 Level: intermediate 2212 2213 .keywords: mesh 2214 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2215 @*/ 2216 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2217 { 2218 DM_Plex *mesh = (DM_Plex*) dm->data; 2219 PetscInt *offsets, **closures; 2220 PetscInt *join[2]; 2221 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2222 PetscInt p, d, c, m; 2223 PetscErrorCode ierr; 2224 2225 PetscFunctionBegin; 2226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2227 PetscValidPointer(points, 2); 2228 PetscValidPointer(numCoveredPoints, 3); 2229 PetscValidPointer(coveredPoints, 4); 2230 2231 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2232 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2233 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2234 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2235 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2236 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2237 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2238 2239 for (p = 0; p < numPoints; ++p) { 2240 PetscInt closureSize; 2241 2242 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2243 2244 offsets[p*(depth+2)+0] = 0; 2245 for (d = 0; d < depth+1; ++d) { 2246 PetscInt pStart, pEnd, i; 2247 2248 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2249 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2250 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2251 offsets[p*(depth+2)+d+1] = i; 2252 break; 2253 } 2254 } 2255 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2256 } 2257 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2258 } 2259 for (d = 0; d < depth+1; ++d) { 2260 PetscInt dof; 2261 2262 /* Copy in support of first point */ 2263 dof = offsets[d+1] - offsets[d]; 2264 for (joinSize = 0; joinSize < dof; ++joinSize) { 2265 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2266 } 2267 /* Check each successive cone */ 2268 for (p = 1; p < numPoints && joinSize; ++p) { 2269 PetscInt newJoinSize = 0; 2270 2271 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2272 for (c = 0; c < dof; ++c) { 2273 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2274 2275 for (m = 0; m < joinSize; ++m) { 2276 if (point == join[i][m]) { 2277 join[1-i][newJoinSize++] = point; 2278 break; 2279 } 2280 } 2281 } 2282 joinSize = newJoinSize; 2283 i = 1-i; 2284 } 2285 if (joinSize) break; 2286 } 2287 *numCoveredPoints = joinSize; 2288 *coveredPoints = join[i]; 2289 for (p = 0; p < numPoints; ++p) { 2290 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2291 } 2292 ierr = PetscFree(closures);CHKERRQ(ierr); 2293 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2294 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2295 PetscFunctionReturn(0); 2296 } 2297 2298 #undef __FUNCT__ 2299 #define __FUNCT__ "DMPlexGetMeet" 2300 /*@C 2301 DMPlexGetMeet - Get an array for the meet of the set of points 2302 2303 Not Collective 2304 2305 Input Parameters: 2306 + dm - The DMPlex object 2307 . numPoints - The number of input points for the meet 2308 - points - The input points 2309 2310 Output Parameters: 2311 + numCoveredPoints - The number of points in the meet 2312 - coveredPoints - The points in the meet 2313 2314 Level: intermediate 2315 2316 Note: Currently, this is restricted to a single level meet 2317 2318 .keywords: mesh 2319 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2320 @*/ 2321 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2322 { 2323 DM_Plex *mesh = (DM_Plex*) dm->data; 2324 PetscInt *meet[2]; 2325 PetscInt meetSize, i = 0; 2326 PetscInt dof, off, p, c, m; 2327 PetscErrorCode ierr; 2328 2329 PetscFunctionBegin; 2330 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2331 PetscValidPointer(points, 2); 2332 PetscValidPointer(numCoveringPoints, 3); 2333 PetscValidPointer(coveringPoints, 4); 2334 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2335 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2336 /* Copy in cone of first point */ 2337 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2338 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2339 for (meetSize = 0; meetSize < dof; ++meetSize) { 2340 meet[i][meetSize] = mesh->cones[off+meetSize]; 2341 } 2342 /* Check each successive cone */ 2343 for (p = 1; p < numPoints; ++p) { 2344 PetscInt newMeetSize = 0; 2345 2346 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2347 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2348 for (c = 0; c < dof; ++c) { 2349 const PetscInt point = mesh->cones[off+c]; 2350 2351 for (m = 0; m < meetSize; ++m) { 2352 if (point == meet[i][m]) { 2353 meet[1-i][newMeetSize++] = point; 2354 break; 2355 } 2356 } 2357 } 2358 meetSize = newMeetSize; 2359 i = 1-i; 2360 } 2361 *numCoveringPoints = meetSize; 2362 *coveringPoints = meet[i]; 2363 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2364 PetscFunctionReturn(0); 2365 } 2366 2367 #undef __FUNCT__ 2368 #define __FUNCT__ "DMPlexRestoreMeet" 2369 /*@C 2370 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2371 2372 Not Collective 2373 2374 Input Parameters: 2375 + dm - The DMPlex object 2376 . numPoints - The number of input points for the meet 2377 - points - The input points 2378 2379 Output Parameters: 2380 + numCoveredPoints - The number of points in the meet 2381 - coveredPoints - The points in the meet 2382 2383 Level: intermediate 2384 2385 .keywords: mesh 2386 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2387 @*/ 2388 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2389 { 2390 PetscErrorCode ierr; 2391 2392 PetscFunctionBegin; 2393 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2394 PetscValidPointer(coveredPoints, 4); 2395 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2396 PetscFunctionReturn(0); 2397 } 2398 2399 #undef __FUNCT__ 2400 #define __FUNCT__ "DMPlexGetFullMeet" 2401 /*@C 2402 DMPlexGetFullMeet - Get an array for the meet of the set of points 2403 2404 Not Collective 2405 2406 Input Parameters: 2407 + dm - The DMPlex object 2408 . numPoints - The number of input points for the meet 2409 - points - The input points 2410 2411 Output Parameters: 2412 + numCoveredPoints - The number of points in the meet 2413 - coveredPoints - The points in the meet 2414 2415 Level: intermediate 2416 2417 .keywords: mesh 2418 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2419 @*/ 2420 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2421 { 2422 DM_Plex *mesh = (DM_Plex*) dm->data; 2423 PetscInt *offsets, **closures; 2424 PetscInt *meet[2]; 2425 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2426 PetscInt p, h, c, m; 2427 PetscErrorCode ierr; 2428 2429 PetscFunctionBegin; 2430 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2431 PetscValidPointer(points, 2); 2432 PetscValidPointer(numCoveredPoints, 3); 2433 PetscValidPointer(coveredPoints, 4); 2434 2435 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2436 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2437 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2438 maxSize = PetscPowInt(mesh->maxConeSize,height); 2439 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2440 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2441 2442 for (p = 0; p < numPoints; ++p) { 2443 PetscInt closureSize; 2444 2445 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2446 2447 offsets[p*(height+2)+0] = 0; 2448 for (h = 0; h < height+1; ++h) { 2449 PetscInt pStart, pEnd, i; 2450 2451 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2452 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2453 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2454 offsets[p*(height+2)+h+1] = i; 2455 break; 2456 } 2457 } 2458 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2459 } 2460 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2461 } 2462 for (h = 0; h < height+1; ++h) { 2463 PetscInt dof; 2464 2465 /* Copy in cone of first point */ 2466 dof = offsets[h+1] - offsets[h]; 2467 for (meetSize = 0; meetSize < dof; ++meetSize) { 2468 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2469 } 2470 /* Check each successive cone */ 2471 for (p = 1; p < numPoints && meetSize; ++p) { 2472 PetscInt newMeetSize = 0; 2473 2474 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2475 for (c = 0; c < dof; ++c) { 2476 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2477 2478 for (m = 0; m < meetSize; ++m) { 2479 if (point == meet[i][m]) { 2480 meet[1-i][newMeetSize++] = point; 2481 break; 2482 } 2483 } 2484 } 2485 meetSize = newMeetSize; 2486 i = 1-i; 2487 } 2488 if (meetSize) break; 2489 } 2490 *numCoveredPoints = meetSize; 2491 *coveredPoints = meet[i]; 2492 for (p = 0; p < numPoints; ++p) { 2493 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2494 } 2495 ierr = PetscFree(closures);CHKERRQ(ierr); 2496 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2497 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2498 PetscFunctionReturn(0); 2499 } 2500 2501 #undef __FUNCT__ 2502 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2503 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2504 { 2505 MPI_Comm comm = ((PetscObject) dm)->comm; 2506 PetscInt cellDim; 2507 PetscErrorCode ierr; 2508 2509 PetscFunctionBegin; 2510 PetscValidPointer(numFaceVertices,3); 2511 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2512 switch (cellDim) { 2513 case 0: 2514 *numFaceVertices = 0; 2515 break; 2516 case 1: 2517 *numFaceVertices = 1; 2518 break; 2519 case 2: 2520 switch (numCorners) { 2521 case 3: /* triangle */ 2522 *numFaceVertices = 2; /* Edge has 2 vertices */ 2523 break; 2524 case 4: /* quadrilateral */ 2525 *numFaceVertices = 2; /* Edge has 2 vertices */ 2526 break; 2527 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2528 *numFaceVertices = 3; /* Edge has 3 vertices */ 2529 break; 2530 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2531 *numFaceVertices = 3; /* Edge has 3 vertices */ 2532 break; 2533 default: 2534 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2535 } 2536 break; 2537 case 3: 2538 switch (numCorners) { 2539 case 4: /* tetradehdron */ 2540 *numFaceVertices = 3; /* Face has 3 vertices */ 2541 break; 2542 case 6: /* tet cohesive cells */ 2543 *numFaceVertices = 4; /* Face has 4 vertices */ 2544 break; 2545 case 8: /* hexahedron */ 2546 *numFaceVertices = 4; /* Face has 4 vertices */ 2547 break; 2548 case 9: /* tet cohesive Lagrange cells */ 2549 *numFaceVertices = 6; /* Face has 6 vertices */ 2550 break; 2551 case 10: /* quadratic tetrahedron */ 2552 *numFaceVertices = 6; /* Face has 6 vertices */ 2553 break; 2554 case 12: /* hex cohesive Lagrange cells */ 2555 *numFaceVertices = 6; /* Face has 6 vertices */ 2556 break; 2557 case 18: /* quadratic tet cohesive Lagrange cells */ 2558 *numFaceVertices = 6; /* Face has 6 vertices */ 2559 break; 2560 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2561 *numFaceVertices = 9; /* Face has 9 vertices */ 2562 break; 2563 default: 2564 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2565 } 2566 break; 2567 default: 2568 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2569 } 2570 PetscFunctionReturn(0); 2571 } 2572 2573 #undef __FUNCT__ 2574 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2575 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2576 { 2577 const PetscInt maxFaceCases = 30; 2578 PetscInt numFaceCases = 0; 2579 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2580 PetscInt *off, *adj; 2581 PetscInt *neighborCells, *tmpClosure; 2582 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2583 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2584 PetscErrorCode ierr; 2585 2586 PetscFunctionBegin; 2587 /* For parallel partitioning, I think you have to communicate supports */ 2588 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2589 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2590 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2591 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2592 if (cEnd - cStart == 0) { 2593 if (numVertices) *numVertices = 0; 2594 if (offsets) *offsets = NULL; 2595 if (adjacency) *adjacency = NULL; 2596 PetscFunctionReturn(0); 2597 } 2598 numCells = cEnd - cStart; 2599 /* Setup face recognition */ 2600 if (depth == 1) { 2601 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 */ 2602 2603 for (c = cStart; c < cEnd; ++c) { 2604 PetscInt corners; 2605 2606 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2607 if (!cornersSeen[corners]) { 2608 PetscInt nFV; 2609 2610 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2611 cornersSeen[corners] = 1; 2612 2613 ierr = DMPlexGetNumFaceVertices_Internal(dm, corners, &nFV);CHKERRQ(ierr); 2614 2615 numFaceVertices[numFaceCases++] = nFV; 2616 } 2617 } 2618 } 2619 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2620 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2621 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2622 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2623 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2624 /* Count neighboring cells */ 2625 for (cell = cStart; cell < cEnd; ++cell) { 2626 PetscInt numNeighbors = maxNeighbors, n; 2627 2628 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2629 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2630 for (n = 0; n < numNeighbors; ++n) { 2631 PetscInt cellPair[2]; 2632 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2633 PetscInt meetSize = 0; 2634 const PetscInt *meet = NULL; 2635 2636 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2637 if (cellPair[0] == cellPair[1]) continue; 2638 if (!found) { 2639 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2640 if (meetSize) { 2641 PetscInt f; 2642 2643 for (f = 0; f < numFaceCases; ++f) { 2644 if (numFaceVertices[f] == meetSize) { 2645 found = PETSC_TRUE; 2646 break; 2647 } 2648 } 2649 } 2650 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2651 } 2652 if (found) ++off[cell-cStart+1]; 2653 } 2654 } 2655 /* Prefix sum */ 2656 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2657 2658 if (adjacency) { 2659 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2660 /* Get neighboring cells */ 2661 for (cell = cStart; cell < cEnd; ++cell) { 2662 PetscInt numNeighbors = maxNeighbors, n; 2663 PetscInt cellOffset = 0; 2664 2665 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2666 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2667 for (n = 0; n < numNeighbors; ++n) { 2668 PetscInt cellPair[2]; 2669 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2670 PetscInt meetSize = 0; 2671 const PetscInt *meet = NULL; 2672 2673 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2674 if (cellPair[0] == cellPair[1]) continue; 2675 if (!found) { 2676 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2677 if (meetSize) { 2678 PetscInt f; 2679 2680 for (f = 0; f < numFaceCases; ++f) { 2681 if (numFaceVertices[f] == meetSize) { 2682 found = PETSC_TRUE; 2683 break; 2684 } 2685 } 2686 } 2687 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2688 } 2689 if (found) { 2690 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2691 ++cellOffset; 2692 } 2693 } 2694 } 2695 } 2696 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2697 if (numVertices) *numVertices = numCells; 2698 if (offsets) *offsets = off; 2699 if (adjacency) *adjacency = adj; 2700 PetscFunctionReturn(0); 2701 } 2702 2703 #if defined(PETSC_HAVE_CHACO) 2704 #if defined(PETSC_HAVE_UNISTD_H) 2705 #include <unistd.h> 2706 #endif 2707 /* Chaco does not have an include file */ 2708 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2709 float *ewgts, float *x, float *y, float *z, char *outassignname, 2710 char *outfilename, short *assignment, int architecture, int ndims_tot, 2711 int mesh_dims[3], double *goal, int global_method, int local_method, 2712 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2713 2714 extern int FREE_GRAPH; 2715 2716 #undef __FUNCT__ 2717 #define __FUNCT__ "DMPlexPartition_Chaco" 2718 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2719 { 2720 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2721 MPI_Comm comm = ((PetscObject) dm)->comm; 2722 int nvtxs = numVertices; /* number of vertices in full graph */ 2723 int *vwgts = NULL; /* weights for all vertices */ 2724 float *ewgts = NULL; /* weights for all edges */ 2725 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2726 char *outassignname = NULL; /* name of assignment output file */ 2727 char *outfilename = NULL; /* output file name */ 2728 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2729 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2730 int mesh_dims[3]; /* dimensions of mesh of processors */ 2731 double *goal = NULL; /* desired set sizes for each set */ 2732 int global_method = 1; /* global partitioning algorithm */ 2733 int local_method = 1; /* local partitioning algorithm */ 2734 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2735 int vmax = 200; /* how many vertices to coarsen down to? */ 2736 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2737 double eigtol = 0.001; /* tolerance on eigenvectors */ 2738 long seed = 123636512; /* for random graph mutations */ 2739 short int *assignment; /* Output partition */ 2740 int fd_stdout, fd_pipe[2]; 2741 PetscInt *points; 2742 PetscMPIInt commSize; 2743 int i, v, p; 2744 PetscErrorCode ierr; 2745 2746 PetscFunctionBegin; 2747 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2748 if (!numVertices) { 2749 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2750 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2751 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2752 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2753 PetscFunctionReturn(0); 2754 } 2755 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2756 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2757 2758 if (global_method == INERTIAL_METHOD) { 2759 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2760 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2761 } 2762 mesh_dims[0] = commSize; 2763 mesh_dims[1] = 1; 2764 mesh_dims[2] = 1; 2765 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2766 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2767 /* TODO: check error codes for UNIX calls */ 2768 #if defined(PETSC_HAVE_UNISTD_H) 2769 { 2770 int piperet; 2771 piperet = pipe(fd_pipe); 2772 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2773 fd_stdout = dup(1); 2774 close(1); 2775 dup2(fd_pipe[1], 1); 2776 } 2777 #endif 2778 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2779 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2780 vmax, ndims, eigtol, seed); 2781 #if defined(PETSC_HAVE_UNISTD_H) 2782 { 2783 char msgLog[10000]; 2784 int count; 2785 2786 fflush(stdout); 2787 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2788 if (count < 0) count = 0; 2789 msgLog[count] = 0; 2790 close(1); 2791 dup2(fd_stdout, 1); 2792 close(fd_stdout); 2793 close(fd_pipe[0]); 2794 close(fd_pipe[1]); 2795 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2796 } 2797 #endif 2798 /* Convert to PetscSection+IS */ 2799 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2800 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2801 for (v = 0; v < nvtxs; ++v) { 2802 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2803 } 2804 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2805 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2806 for (p = 0, i = 0; p < commSize; ++p) { 2807 for (v = 0; v < nvtxs; ++v) { 2808 if (assignment[v] == p) points[i++] = v; 2809 } 2810 } 2811 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2812 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2813 if (global_method == INERTIAL_METHOD) { 2814 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2815 } 2816 ierr = PetscFree(assignment);CHKERRQ(ierr); 2817 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2818 PetscFunctionReturn(0); 2819 } 2820 #endif 2821 2822 #if defined(PETSC_HAVE_PARMETIS) 2823 #undef __FUNCT__ 2824 #define __FUNCT__ "DMPlexPartition_ParMetis" 2825 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2826 { 2827 PetscFunctionBegin; 2828 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2829 PetscFunctionReturn(0); 2830 } 2831 #endif 2832 2833 #undef __FUNCT__ 2834 #define __FUNCT__ "DMPlexEnlargePartition" 2835 /* Expand the partition by BFS on the adjacency graph */ 2836 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2837 { 2838 PetscHashI h; 2839 const PetscInt *points; 2840 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2841 PetscInt pStart, pEnd, part, q; 2842 PetscErrorCode ierr; 2843 2844 PetscFunctionBegin; 2845 PetscHashICreate(h); 2846 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2847 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2848 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2849 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2850 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2851 for (part = pStart; part < pEnd; ++part) { 2852 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2853 2854 PetscHashIClear(h); 2855 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2856 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2857 /* Add all existing points to h */ 2858 for (p = 0; p < numPoints; ++p) { 2859 const PetscInt point = points[off+p]; 2860 PetscHashIAdd(h, point, 1); 2861 } 2862 PetscHashISize(h, nP); 2863 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2864 /* Add all points in next BFS level */ 2865 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2866 for (p = 0; p < numPoints; ++p) { 2867 const PetscInt point = points[off+p]; 2868 PetscInt s = start[point], e = start[point+1], a; 2869 2870 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2871 } 2872 PetscHashISize(h, numNewPoints); 2873 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2874 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2875 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2876 totPoints += numNewPoints; 2877 } 2878 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2879 PetscHashIDestroy(h); 2880 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2881 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2882 for (part = pStart, q = 0; part < pEnd; ++part) { 2883 PetscInt numPoints, p; 2884 2885 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2886 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2887 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2888 } 2889 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2890 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2891 PetscFunctionReturn(0); 2892 } 2893 2894 #undef __FUNCT__ 2895 #define __FUNCT__ "DMPlexCreatePartition" 2896 /* 2897 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2898 2899 Collective on DM 2900 2901 Input Parameters: 2902 + dm - The DM 2903 . height - The height for points in the partition 2904 - enlarge - Expand each partition with neighbors 2905 2906 Output Parameters: 2907 + partSection - The PetscSection giving the division of points by partition 2908 . partition - The list of points by partition 2909 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2910 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2911 2912 Level: developer 2913 2914 .seealso DMPlexDistribute() 2915 */ 2916 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2917 { 2918 PetscMPIInt size; 2919 PetscErrorCode ierr; 2920 2921 PetscFunctionBegin; 2922 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2923 2924 *origPartSection = NULL; 2925 *origPartition = NULL; 2926 if (size == 1) { 2927 PetscInt *points; 2928 PetscInt cStart, cEnd, c; 2929 2930 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2931 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2932 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2933 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2934 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2935 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2936 for (c = cStart; c < cEnd; ++c) points[c] = c; 2937 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2938 PetscFunctionReturn(0); 2939 } 2940 if (height == 0) { 2941 PetscInt numVertices; 2942 PetscInt *start = NULL; 2943 PetscInt *adjacency = NULL; 2944 2945 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2946 if (1) { 2947 #if defined(PETSC_HAVE_CHACO) 2948 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2949 #endif 2950 } else { 2951 #if defined(PETSC_HAVE_PARMETIS) 2952 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2953 #endif 2954 } 2955 if (enlarge) { 2956 *origPartSection = *partSection; 2957 *origPartition = *partition; 2958 2959 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2960 } 2961 ierr = PetscFree(start);CHKERRQ(ierr); 2962 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2963 # if 0 2964 } else if (height == 1) { 2965 /* Build the dual graph for faces and partition the hypergraph */ 2966 PetscInt numEdges; 2967 2968 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2969 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2970 destroyCSR(numEdges, start, adjacency); 2971 #endif 2972 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2973 PetscFunctionReturn(0); 2974 } 2975 2976 #undef __FUNCT__ 2977 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2978 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2979 { 2980 /* const PetscInt height = 0; */ 2981 const PetscInt *partArray; 2982 PetscInt *allPoints, *partPoints = NULL; 2983 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2984 PetscErrorCode ierr; 2985 2986 PetscFunctionBegin; 2987 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2988 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2989 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2990 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2991 for (rank = rStart; rank < rEnd; ++rank) { 2992 PetscInt partSize = 0; 2993 PetscInt numPoints, offset, p; 2994 2995 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2996 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2997 for (p = 0; p < numPoints; ++p) { 2998 PetscInt point = partArray[offset+p], closureSize, c; 2999 PetscInt *closure = NULL; 3000 3001 /* TODO Include support for height > 0 case */ 3002 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3003 /* Merge into existing points */ 3004 if (partSize+closureSize > maxPartSize) { 3005 PetscInt *tmpPoints; 3006 3007 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 3008 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 3009 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3010 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3011 3012 partPoints = tmpPoints; 3013 } 3014 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3015 partSize += closureSize; 3016 3017 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3018 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3019 } 3020 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3021 } 3022 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3023 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3024 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3025 3026 for (rank = rStart; rank < rEnd; ++rank) { 3027 PetscInt partSize = 0, newOffset; 3028 PetscInt numPoints, offset, p; 3029 3030 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3031 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3032 for (p = 0; p < numPoints; ++p) { 3033 PetscInt point = partArray[offset+p], closureSize, c; 3034 PetscInt *closure = NULL; 3035 3036 /* TODO Include support for height > 0 case */ 3037 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3038 /* Merge into existing points */ 3039 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3040 partSize += closureSize; 3041 3042 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3043 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3044 } 3045 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3046 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3047 } 3048 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3049 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3050 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3051 PetscFunctionReturn(0); 3052 } 3053 3054 #undef __FUNCT__ 3055 #define __FUNCT__ "DMPlexDistributeField" 3056 /* 3057 Input Parameters: 3058 . originalSection 3059 , originalVec 3060 3061 Output Parameters: 3062 . newSection 3063 . newVec 3064 */ 3065 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3066 { 3067 PetscSF fieldSF; 3068 PetscInt *remoteOffsets, fieldSize; 3069 PetscScalar *originalValues, *newValues; 3070 PetscErrorCode ierr; 3071 3072 PetscFunctionBegin; 3073 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3074 3075 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3076 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3077 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3078 3079 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3080 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3081 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3082 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3083 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3084 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3085 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3086 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3087 PetscFunctionReturn(0); 3088 } 3089 3090 #undef __FUNCT__ 3091 #define __FUNCT__ "DMPlexDistribute" 3092 /*@C 3093 DMPlexDistribute - Distributes the mesh and any associated sections. 3094 3095 Not Collective 3096 3097 Input Parameter: 3098 + dm - The original DMPlex object 3099 . partitioner - The partitioning package, or NULL for the default 3100 - overlap - The overlap of partitions, 0 is the default 3101 3102 Output Parameter: 3103 . parallelMesh - The distributed DMPlex object, or NULL 3104 3105 Note: If the mesh was not distributed, the return value is NULL 3106 3107 Level: intermediate 3108 3109 .keywords: mesh, elements 3110 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3111 @*/ 3112 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3113 { 3114 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3115 MPI_Comm comm = ((PetscObject) dm)->comm; 3116 const PetscInt height = 0; 3117 PetscInt dim, numRemoteRanks; 3118 IS origCellPart, cellPart, part; 3119 PetscSection origCellPartSection, cellPartSection, partSection; 3120 PetscSFNode *remoteRanks; 3121 PetscSF partSF, pointSF, coneSF; 3122 ISLocalToGlobalMapping renumbering; 3123 PetscSection originalConeSection, newConeSection; 3124 PetscInt *remoteOffsets; 3125 PetscInt *cones, *newCones, newConesSize; 3126 PetscBool flg; 3127 PetscMPIInt rank, numProcs, p; 3128 PetscErrorCode ierr; 3129 3130 PetscFunctionBegin; 3131 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3132 PetscValidPointer(dmParallel,4); 3133 3134 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3135 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3136 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3137 3138 *dmParallel = NULL; 3139 if (numProcs == 1) PetscFunctionReturn(0); 3140 3141 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3142 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3143 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3144 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3145 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3146 if (!rank) numRemoteRanks = numProcs; 3147 else numRemoteRanks = 0; 3148 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3149 for (p = 0; p < numRemoteRanks; ++p) { 3150 remoteRanks[p].rank = p; 3151 remoteRanks[p].index = 0; 3152 } 3153 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3154 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3155 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3156 if (flg) { 3157 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3158 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3159 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3160 if (origCellPart) { 3161 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3162 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3163 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3164 } 3165 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3166 } 3167 /* Close the partition over the mesh */ 3168 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3169 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3170 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3171 /* Create new mesh */ 3172 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3173 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3174 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3175 pmesh = (DM_Plex*) (*dmParallel)->data; 3176 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3177 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3178 if (flg) { 3179 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3180 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3181 ierr = ISView(part, NULL);CHKERRQ(ierr); 3182 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3183 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3184 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3185 } 3186 /* Distribute cone section */ 3187 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3188 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3189 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3190 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3191 { 3192 PetscInt pStart, pEnd, p; 3193 3194 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3195 for (p = pStart; p < pEnd; ++p) { 3196 PetscInt coneSize; 3197 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3198 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3199 } 3200 } 3201 /* Communicate and renumber cones */ 3202 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3203 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3204 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3205 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3206 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3207 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3208 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3209 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3210 if (flg) { 3211 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3212 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3213 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3214 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3215 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3216 } 3217 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3218 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3219 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3220 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3221 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3222 /* Create supports and stratify sieve */ 3223 { 3224 PetscInt pStart, pEnd; 3225 3226 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3227 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3228 } 3229 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3230 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3231 /* Distribute Coordinates */ 3232 { 3233 PetscSection originalCoordSection, newCoordSection; 3234 Vec originalCoordinates, newCoordinates; 3235 const char *name; 3236 3237 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3238 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3239 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3240 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3241 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3242 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3243 3244 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3245 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3246 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3247 } 3248 /* Distribute labels */ 3249 { 3250 DMLabel next = mesh->labels, newNext = pmesh->labels; 3251 PetscInt numLabels = 0, l; 3252 3253 /* Bcast number of labels */ 3254 while (next) { 3255 ++numLabels; next = next->next; 3256 } 3257 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3258 next = mesh->labels; 3259 for (l = 0; l < numLabels; ++l) { 3260 DMLabel newLabel; 3261 const PetscInt *partArray; 3262 char *name; 3263 PetscInt *stratumSizes = NULL, *points = NULL; 3264 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3265 PetscInt nameSize, s, p; 3266 PetscBool isdepth; 3267 size_t len = 0; 3268 3269 /* Bcast name (could filter for no points) */ 3270 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3271 nameSize = len; 3272 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3273 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3274 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3275 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3276 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3277 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3278 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3279 newLabel->name = name; 3280 /* Bcast numStrata (could filter for no points in stratum) */ 3281 if (!rank) newLabel->numStrata = next->numStrata; 3282 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3283 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3284 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3285 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3286 /* Bcast stratumValues (could filter for no points in stratum) */ 3287 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3288 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3289 /* Find size on each process and Scatter */ 3290 if (!rank) { 3291 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3292 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3293 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3294 for (s = 0; s < next->numStrata; ++s) { 3295 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3296 const PetscInt point = next->points[p]; 3297 PetscInt proc; 3298 3299 for (proc = 0; proc < numProcs; ++proc) { 3300 PetscInt dof, off, pPart; 3301 3302 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3303 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3304 for (pPart = off; pPart < off+dof; ++pPart) { 3305 if (partArray[pPart] == point) { 3306 ++stratumSizes[proc*next->numStrata+s]; 3307 break; 3308 } 3309 } 3310 } 3311 } 3312 } 3313 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3314 } 3315 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3316 /* Calculate stratumOffsets */ 3317 newLabel->stratumOffsets[0] = 0; 3318 for (s = 0; s < newLabel->numStrata; ++s) { 3319 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3320 } 3321 /* Pack points and Scatter */ 3322 if (!rank) { 3323 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3324 displs[0] = 0; 3325 for (p = 0; p < numProcs; ++p) { 3326 sendcnts[p] = 0; 3327 for (s = 0; s < next->numStrata; ++s) { 3328 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3329 } 3330 offsets[p] = displs[p]; 3331 displs[p+1] = displs[p] + sendcnts[p]; 3332 } 3333 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3334 for (s = 0; s < next->numStrata; ++s) { 3335 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3336 const PetscInt point = next->points[p]; 3337 PetscInt proc; 3338 3339 for (proc = 0; proc < numProcs; ++proc) { 3340 PetscInt dof, off, pPart; 3341 3342 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3343 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3344 for (pPart = off; pPart < off+dof; ++pPart) { 3345 if (partArray[pPart] == point) { 3346 points[offsets[proc]++] = point; 3347 break; 3348 } 3349 } 3350 } 3351 } 3352 } 3353 } 3354 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3355 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3356 ierr = PetscFree(points);CHKERRQ(ierr); 3357 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3358 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3359 /* Renumber points */ 3360 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3361 /* Sort points */ 3362 for (s = 0; s < newLabel->numStrata; ++s) { 3363 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3364 } 3365 /* Insert into list */ 3366 if (newNext) newNext->next = newLabel; 3367 else pmesh->labels = newLabel; 3368 newNext = newLabel; 3369 if (!rank) next = next->next; 3370 } 3371 } 3372 /* Cleanup Partition */ 3373 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3374 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3375 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3376 ierr = ISDestroy(&part);CHKERRQ(ierr); 3377 /* Create point SF for parallel mesh */ 3378 { 3379 const PetscInt *leaves; 3380 PetscSFNode *remotePoints, *rowners, *lowners; 3381 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3382 PetscInt pStart, pEnd; 3383 3384 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3385 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3386 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3387 for (p=0; p<numRoots; p++) { 3388 rowners[p].rank = -1; 3389 rowners[p].index = -1; 3390 } 3391 if (origCellPart) { 3392 /* Make sure cells in the original partition are not assigned to other procs */ 3393 const PetscInt *origCells; 3394 3395 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3396 for (p = 0; p < numProcs; ++p) { 3397 PetscInt dof, off, d; 3398 3399 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3400 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3401 for (d = off; d < off+dof; ++d) { 3402 rowners[origCells[d]].rank = p; 3403 } 3404 } 3405 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3406 } 3407 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3408 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3409 3410 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3411 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3412 for (p = 0; p < numLeaves; ++p) { 3413 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3414 lowners[p].rank = rank; 3415 lowners[p].index = leaves ? leaves[p] : p; 3416 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3417 lowners[p].rank = -2; 3418 lowners[p].index = -2; 3419 } 3420 } 3421 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3422 rowners[p].rank = -3; 3423 rowners[p].index = -3; 3424 } 3425 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3426 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3427 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3428 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3429 for (p = 0; p < numLeaves; ++p) { 3430 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3431 if (lowners[p].rank != rank) ++numGhostPoints; 3432 } 3433 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3434 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3435 for (p = 0, gp = 0; p < numLeaves; ++p) { 3436 if (lowners[p].rank != rank) { 3437 ghostPoints[gp] = leaves ? leaves[p] : p; 3438 remotePoints[gp].rank = lowners[p].rank; 3439 remotePoints[gp].index = lowners[p].index; 3440 ++gp; 3441 } 3442 } 3443 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3444 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3445 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3446 } 3447 /* Cleanup */ 3448 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3449 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3450 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3451 PetscFunctionReturn(0); 3452 } 3453 3454 #undef __FUNCT__ 3455 #define __FUNCT__ "DMPlexRenumber_Private" 3456 /* 3457 Reasons to renumber: 3458 3459 1) Permute points, e.g. bandwidth reduction (Renumber) 3460 3461 a) Must not mix strata 3462 3463 2) Shift numbers for point insertion (Shift) 3464 3465 a) Want operation brken into parts so that insertion can be interleaved 3466 3467 renumbering - An IS which provides the new numbering 3468 */ 3469 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3470 { 3471 PetscFunctionBegin; 3472 PetscFunctionReturn(0); 3473 } 3474 3475 #undef __FUNCT__ 3476 #define __FUNCT__ "DMPlexShiftPoint_Private" 3477 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3478 { 3479 if (depth < 0) return p; 3480 /* Cells */ if (p < depthEnd[depth]) return p; 3481 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3482 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3483 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3484 } 3485 3486 #undef __FUNCT__ 3487 #define __FUNCT__ "DMPlexShiftSizes_Private" 3488 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3489 { 3490 PetscInt *depthEnd; 3491 PetscInt depth = 0, d, pStart, pEnd, p; 3492 PetscErrorCode ierr; 3493 3494 PetscFunctionBegin; 3495 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3496 if (depth < 0) PetscFunctionReturn(0); 3497 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3498 /* Step 1: Expand chart */ 3499 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3500 for (d = 0; d <= depth; ++d) { 3501 pEnd += depthShift[d]; 3502 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3503 } 3504 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3505 /* Step 2: Set cone and support sizes */ 3506 for (d = 0; d <= depth; ++d) { 3507 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3508 for (p = pStart; p < pEnd; ++p) { 3509 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3510 PetscInt size; 3511 3512 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3513 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3514 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3515 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3516 } 3517 } 3518 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3519 PetscFunctionReturn(0); 3520 } 3521 3522 #undef __FUNCT__ 3523 #define __FUNCT__ "DMPlexShiftPoints_Private" 3524 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3525 { 3526 PetscInt *depthEnd, *newpoints; 3527 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3528 PetscErrorCode ierr; 3529 3530 PetscFunctionBegin; 3531 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3532 if (depth < 0) PetscFunctionReturn(0); 3533 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3534 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3535 for (d = 0; d <= depth; ++d) { 3536 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3537 } 3538 /* Step 5: Set cones and supports */ 3539 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3540 for (p = pStart; p < pEnd; ++p) { 3541 const PetscInt *points = NULL, *orientations = NULL; 3542 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3543 3544 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3545 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3546 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3547 for (i = 0; i < size; ++i) { 3548 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3549 } 3550 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3551 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3552 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3553 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3554 for (i = 0; i < size; ++i) { 3555 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3556 } 3557 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3558 } 3559 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3560 PetscFunctionReturn(0); 3561 } 3562 3563 #undef __FUNCT__ 3564 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3565 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3566 { 3567 PetscSection coordSection, newCoordSection; 3568 Vec coordinates, newCoordinates; 3569 PetscScalar *coords, *newCoords; 3570 PetscInt *depthEnd, coordSize; 3571 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3572 PetscErrorCode ierr; 3573 3574 PetscFunctionBegin; 3575 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3576 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3577 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3578 for (d = 0; d <= depth; ++d) { 3579 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3580 } 3581 /* Step 8: Convert coordinates */ 3582 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3583 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3584 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3585 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3586 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3587 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3588 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3589 for (v = vStartNew; v < vEndNew; ++v) { 3590 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3591 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3592 } 3593 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3594 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3595 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3596 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3597 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3598 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3599 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3600 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3601 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3602 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3603 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3604 for (v = vStart; v < vEnd; ++v) { 3605 PetscInt dof, off, noff, d; 3606 3607 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3608 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3609 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3610 for (d = 0; d < dof; ++d) { 3611 newCoords[noff+d] = coords[off+d]; 3612 } 3613 } 3614 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3615 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3616 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3617 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3618 PetscFunctionReturn(0); 3619 } 3620 3621 #undef __FUNCT__ 3622 #define __FUNCT__ "DMPlexShiftSF_Private" 3623 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3624 { 3625 PetscInt *depthEnd; 3626 PetscInt depth = 0, d; 3627 PetscSF sfPoint, sfPointNew; 3628 const PetscSFNode *remotePoints; 3629 PetscSFNode *gremotePoints; 3630 const PetscInt *localPoints; 3631 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3632 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3633 PetscMPIInt numProcs; 3634 PetscErrorCode ierr; 3635 3636 PetscFunctionBegin; 3637 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3638 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3639 for (d = 0; d <= depth; ++d) { 3640 totShift += depthShift[d]; 3641 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3642 } 3643 /* Step 9: Convert pointSF */ 3644 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3645 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3646 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3647 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3648 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3649 if (numRoots >= 0) { 3650 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3651 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3652 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3653 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3654 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3655 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3656 for (l = 0; l < numLeaves; ++l) { 3657 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3658 gremotePoints[l].rank = remotePoints[l].rank; 3659 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3660 } 3661 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3662 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3663 } 3664 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3665 PetscFunctionReturn(0); 3666 } 3667 3668 #undef __FUNCT__ 3669 #define __FUNCT__ "DMPlexShiftLabels_Private" 3670 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3671 { 3672 PetscSF sfPoint; 3673 DMLabel vtkLabel, ghostLabel; 3674 PetscInt *depthEnd; 3675 const PetscSFNode *leafRemote; 3676 const PetscInt *leafLocal; 3677 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3678 PetscMPIInt rank; 3679 PetscErrorCode ierr; 3680 3681 PetscFunctionBegin; 3682 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3683 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3684 for (d = 0; d <= depth; ++d) { 3685 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3686 } 3687 /* Step 10: Convert labels */ 3688 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3689 for (l = 0; l < numLabels; ++l) { 3690 DMLabel label, newlabel; 3691 const char *lname; 3692 PetscBool isDepth; 3693 IS valueIS; 3694 const PetscInt *values; 3695 PetscInt numValues, val; 3696 3697 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3698 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3699 if (isDepth) continue; 3700 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3701 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3702 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3703 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3704 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3705 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3706 for (val = 0; val < numValues; ++val) { 3707 IS pointIS; 3708 const PetscInt *points; 3709 PetscInt numPoints, p; 3710 3711 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3712 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3713 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3714 for (p = 0; p < numPoints; ++p) { 3715 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3716 3717 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3718 } 3719 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3720 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3721 } 3722 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3723 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3724 } 3725 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3726 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3727 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3728 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3729 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3730 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3731 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3732 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3733 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3734 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3735 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3736 for (; c < leafLocal[l] && c < cEnd; ++c) { 3737 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3738 } 3739 if (leafLocal[l] >= cEnd) break; 3740 if (leafRemote[l].rank == rank) { 3741 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3742 } else { 3743 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3744 } 3745 } 3746 for (; c < cEnd; ++c) { 3747 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3748 } 3749 if (0) { 3750 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3751 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3752 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3753 } 3754 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3755 for (f = fStart; f < fEnd; ++f) { 3756 PetscInt numCells; 3757 3758 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3759 if (numCells < 2) { 3760 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3761 } else { 3762 const PetscInt *cells = NULL; 3763 PetscInt vA, vB; 3764 3765 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3766 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3767 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3768 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3769 } 3770 } 3771 if (0) { 3772 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3773 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3774 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3775 } 3776 PetscFunctionReturn(0); 3777 } 3778 3779 #undef __FUNCT__ 3780 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3781 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3782 { 3783 DMLabel label; 3784 IS valueIS; 3785 const PetscInt *values; 3786 PetscInt *depthShift; 3787 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3788 PetscErrorCode ierr; 3789 3790 PetscFunctionBegin; 3791 /* Count ghost cells */ 3792 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3793 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3794 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3795 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3796 3797 *numGhostCells = 0; 3798 for (fs = 0; fs < numFS; ++fs) { 3799 PetscInt numBdFaces; 3800 3801 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3802 3803 *numGhostCells += numBdFaces; 3804 } 3805 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3806 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3807 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3808 if (depth >= 0) depthShift[depth] = *numGhostCells; 3809 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3810 /* Step 3: Set cone/support sizes for new points */ 3811 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3812 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3813 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3814 } 3815 for (fs = 0; fs < numFS; ++fs) { 3816 IS faceIS; 3817 const PetscInt *faces; 3818 PetscInt numFaces, f; 3819 3820 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3821 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3822 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3823 for (f = 0; f < numFaces; ++f) { 3824 PetscInt size; 3825 3826 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3827 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3828 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3829 } 3830 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3831 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3832 } 3833 /* Step 4: Setup ghosted DM */ 3834 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3835 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3836 /* Step 6: Set cones and supports for new points */ 3837 ghostCell = cEnd; 3838 for (fs = 0; fs < numFS; ++fs) { 3839 IS faceIS; 3840 const PetscInt *faces; 3841 PetscInt numFaces, f; 3842 3843 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3844 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3845 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3846 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3847 PetscInt newFace = faces[f] + *numGhostCells; 3848 3849 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3850 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3851 } 3852 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3853 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3854 } 3855 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3856 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3857 /* Step 7: Stratify */ 3858 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3859 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3860 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3861 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3862 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3863 PetscFunctionReturn(0); 3864 } 3865 3866 #undef __FUNCT__ 3867 #define __FUNCT__ "DMPlexConstructGhostCells" 3868 /*@C 3869 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3870 3871 Collective on dm 3872 3873 Input Parameters: 3874 + dm - The original DM 3875 - labelName - The label specifying the boundary faces (this could be auto-generated) 3876 3877 Output Parameters: 3878 + numGhostCells - The number of ghost cells added to the DM 3879 - dmGhosted - The new DM 3880 3881 Level: developer 3882 3883 .seealso: DMCreate() 3884 */ 3885 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3886 { 3887 DM gdm; 3888 PetscInt dim; 3889 PetscErrorCode ierr; 3890 3891 PetscFunctionBegin; 3892 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3893 PetscValidPointer(numGhostCells, 3); 3894 PetscValidPointer(dmGhosted, 4); 3895 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3896 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3897 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3898 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3899 switch (dim) { 3900 case 2: 3901 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3902 break; 3903 default: 3904 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3905 } 3906 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3907 *dmGhosted = gdm; 3908 PetscFunctionReturn(0); 3909 } 3910 3911 #undef __FUNCT__ 3912 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3913 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3914 { 3915 MPI_Comm comm = ((PetscObject) dm)->comm; 3916 IS valueIS, *pointIS; 3917 const PetscInt *values, **splitPoints; 3918 PetscSection coordSection; 3919 Vec coordinates; 3920 PetscScalar *coords; 3921 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3922 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3923 PetscErrorCode ierr; 3924 3925 PetscFunctionBegin; 3926 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3927 /* Count split points and add cohesive cells */ 3928 if (label) { 3929 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3930 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3931 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3932 } 3933 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3934 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3935 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3936 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3937 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3938 for (d = 0; d <= depth; ++d) { 3939 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3940 numSplitPoints[d] = 0; 3941 splitPoints[d] = NULL; 3942 pointIS[d] = NULL; 3943 } 3944 for (sp = 0; sp < numSP; ++sp) { 3945 const PetscInt dep = values[sp]; 3946 3947 if ((dep < 0) || (dep > depth)) continue; 3948 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3949 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3950 if (pointIS[dep]) { 3951 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3952 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3953 } 3954 } 3955 if (depth >= 0) { 3956 /* Calculate number of additional points */ 3957 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3958 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3959 /* Calculate hybrid bound for each dimension */ 3960 pMaxNew[0] += depthShift[depth]; 3961 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3962 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3963 3964 /* Calculate point offset for each dimension */ 3965 depthOffset[depth] = 0; 3966 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3967 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3968 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3969 } 3970 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3971 /* Step 3: Set cone/support sizes for new points */ 3972 for (dep = 0; dep <= depth; ++dep) { 3973 for (p = 0; p < numSplitPoints[dep]; ++p) { 3974 const PetscInt oldp = splitPoints[dep][p]; 3975 const PetscInt newp = depthOffset[dep] + oldp; 3976 const PetscInt splitp = pMaxNew[dep] + p; 3977 const PetscInt *support; 3978 PetscInt coneSize, supportSize, q, e; 3979 3980 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3981 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3982 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3983 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3984 if (dep == depth-1) { 3985 const PetscInt ccell = pMaxNew[depth] + p; 3986 /* Add cohesive cells, they are prisms */ 3987 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3988 } else if (dep == 0) { 3989 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3990 3991 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3992 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3993 for (e = 0, q = 0; e < supportSize; ++e) { 3994 PetscInt val; 3995 3996 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3997 if ((val == 1) || (val == (shift + 1))) ++q; 3998 } 3999 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 4000 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4001 for (e = 0, q = 0; e < supportSize; ++e) { 4002 PetscInt val; 4003 4004 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4005 if ((val == 1) || (val == -(shift + 1))) ++q; 4006 } 4007 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 4008 /* Add cohesive edges */ 4009 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 4010 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4011 } else if (dep == dim-2) { 4012 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4013 /* Split old edge: Faces in positive side cells and old split faces */ 4014 for (e = 0, q = 0; e < supportSize; ++e) { 4015 PetscInt val; 4016 4017 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4018 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4019 } 4020 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4021 /* Split new edge: Faces in negative side cells and new split faces */ 4022 for (e = 0, q = 0; e < supportSize; ++e) { 4023 PetscInt val; 4024 4025 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4026 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4027 } 4028 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4029 } 4030 } 4031 } 4032 /* Step 4: Setup split DM */ 4033 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4034 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4035 /* Step 6: Set cones and supports for new points */ 4036 for (dep = 0; dep <= depth; ++dep) { 4037 for (p = 0; p < numSplitPoints[dep]; ++p) { 4038 const PetscInt oldp = splitPoints[dep][p]; 4039 const PetscInt newp = depthOffset[dep] + oldp; 4040 const PetscInt splitp = pMaxNew[dep] + p; 4041 const PetscInt *cone, *support, *ornt; 4042 PetscInt coneSize, supportSize, q, v, e, s; 4043 4044 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4045 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4046 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4047 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4048 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4049 if (dep == depth-1) { 4050 const PetscInt ccell = pMaxNew[depth] + p; 4051 const PetscInt *supportF; 4052 4053 /* Split face: copy in old face to new face to start */ 4054 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4055 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4056 /* Split old face: old vertices/edges in cone so no change */ 4057 /* Split new face: new vertices/edges in cone */ 4058 for (q = 0; q < coneSize; ++q) { 4059 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4060 4061 coneNew[2+q] = pMaxNew[dim-2] + v; 4062 } 4063 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4064 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4065 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4066 coneNew[0] = newp; 4067 coneNew[1] = splitp; 4068 for (q = 0; q < coneSize; ++q) { 4069 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4070 } 4071 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4072 4073 4074 for (s = 0; s < supportSize; ++s) { 4075 PetscInt val; 4076 4077 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4078 if (val < 0) { 4079 /* Split old face: Replace negative side cell with cohesive cell */ 4080 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4081 } else { 4082 /* Split new face: Replace positive side cell with cohesive cell */ 4083 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4084 } 4085 } 4086 } else if (dep == 0) { 4087 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4088 4089 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4090 for (e = 0, q = 0; e < supportSize; ++e) { 4091 PetscInt val; 4092 4093 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4094 if ((val == 1) || (val == (shift + 1))) { 4095 supportNew[q++] = depthOffset[1] + support[e]; 4096 } 4097 } 4098 supportNew[q] = cedge; 4099 4100 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4101 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4102 for (e = 0, q = 0; e < supportSize; ++e) { 4103 PetscInt val, edge; 4104 4105 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4106 if (val == 1) { 4107 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4108 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4109 supportNew[q++] = pMaxNew[1] + edge; 4110 } else if (val == -(shift + 1)) { 4111 supportNew[q++] = depthOffset[1] + support[e]; 4112 } 4113 } 4114 supportNew[q] = cedge; 4115 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4116 /* Cohesive edge: Old and new split vertex, punting on support */ 4117 coneNew[0] = newp; 4118 coneNew[1] = splitp; 4119 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4120 } else if (dep == dim-2) { 4121 /* Split old edge: old vertices in cone so no change */ 4122 /* Split new edge: new vertices in cone */ 4123 for (q = 0; q < coneSize; ++q) { 4124 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4125 4126 coneNew[q] = pMaxNew[dim-3] + v; 4127 } 4128 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4129 /* Split old edge: Faces in positive side cells and old split faces */ 4130 for (e = 0, q = 0; e < supportSize; ++e) { 4131 PetscInt val; 4132 4133 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4134 if ((val == dim-1) || (val == (shift + dim-1))) { 4135 supportNew[q++] = depthOffset[dim-1] + support[e]; 4136 } 4137 } 4138 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4139 /* Split new edge: Faces in negative side cells and new split faces */ 4140 for (e = 0, q = 0; e < supportSize; ++e) { 4141 PetscInt val, face; 4142 4143 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4144 if (val == dim-1) { 4145 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4146 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4147 supportNew[q++] = pMaxNew[dim-1] + face; 4148 } else if (val == -(shift + dim-1)) { 4149 supportNew[q++] = depthOffset[dim-1] + support[e]; 4150 } 4151 } 4152 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4153 } 4154 } 4155 } 4156 /* Step 6b: Replace split points in negative side cones */ 4157 for (sp = 0; sp < numSP; ++sp) { 4158 PetscInt dep = values[sp]; 4159 IS pIS; 4160 PetscInt numPoints; 4161 const PetscInt *points; 4162 4163 if (dep >= 0) continue; 4164 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4165 if (!pIS) continue; 4166 dep = -dep - shift; 4167 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4168 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4169 for (p = 0; p < numPoints; ++p) { 4170 const PetscInt oldp = points[p]; 4171 const PetscInt newp = depthOffset[dep] + oldp; 4172 const PetscInt *cone; 4173 PetscInt coneSize, c; 4174 PetscBool replaced = PETSC_FALSE; 4175 4176 /* Negative edge: replace split vertex */ 4177 /* Negative cell: replace split face */ 4178 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4179 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4180 for (c = 0; c < coneSize; ++c) { 4181 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4182 PetscInt csplitp, cp, val; 4183 4184 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4185 if (val == dep-1) { 4186 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4187 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4188 csplitp = pMaxNew[dep-1] + cp; 4189 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4190 replaced = PETSC_TRUE; 4191 } 4192 } 4193 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4194 } 4195 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4196 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4197 } 4198 /* Step 7: Stratify */ 4199 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4200 /* Step 8: Coordinates */ 4201 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4202 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4203 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4204 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4205 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4206 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4207 const PetscInt splitp = pMaxNew[0] + v; 4208 PetscInt dof, off, soff, d; 4209 4210 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4211 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4212 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4213 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4214 } 4215 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4216 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4217 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4218 /* Step 10: Labels */ 4219 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4220 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4221 for (dep = 0; dep <= depth; ++dep) { 4222 for (p = 0; p < numSplitPoints[dep]; ++p) { 4223 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4224 const PetscInt splitp = pMaxNew[dep] + p; 4225 PetscInt l; 4226 4227 for (l = 0; l < numLabels; ++l) { 4228 DMLabel mlabel; 4229 const char *lname; 4230 PetscInt val; 4231 4232 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4233 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4234 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4235 if (val >= 0) { 4236 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4237 if (dep == 0) { 4238 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4239 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4240 } 4241 } 4242 } 4243 } 4244 } 4245 for (sp = 0; sp < numSP; ++sp) { 4246 const PetscInt dep = values[sp]; 4247 4248 if ((dep < 0) || (dep > depth)) continue; 4249 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4250 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4251 } 4252 if (label) { 4253 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4254 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4255 } 4256 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4257 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4258 PetscFunctionReturn(0); 4259 } 4260 4261 #undef __FUNCT__ 4262 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4263 /*@C 4264 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4265 4266 Collective on dm 4267 4268 Input Parameters: 4269 + dm - The original DM 4270 - labelName - The label specifying the boundary faces (this could be auto-generated) 4271 4272 Output Parameters: 4273 - dmSplit - The new DM 4274 4275 Level: developer 4276 4277 .seealso: DMCreate() 4278 */ 4279 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4280 { 4281 DM sdm; 4282 PetscInt dim; 4283 PetscErrorCode ierr; 4284 4285 PetscFunctionBegin; 4286 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4287 PetscValidPointer(dmSplit, 4); 4288 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4289 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4290 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4291 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4292 switch (dim) { 4293 case 2: 4294 case 3: 4295 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4296 break; 4297 default: 4298 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4299 } 4300 *dmSplit = sdm; 4301 PetscFunctionReturn(0); 4302 } 4303 4304 #undef __FUNCT__ 4305 #define __FUNCT__ "DMLabelCohesiveComplete" 4306 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4307 { 4308 IS dimIS; 4309 const PetscInt *points; 4310 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4311 PetscErrorCode ierr; 4312 4313 PetscFunctionBegin; 4314 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4315 /* Cell orientation for face gives the side of the fault */ 4316 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4317 if (!dimIS) PetscFunctionReturn(0); 4318 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4319 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4320 for (p = 0; p < numPoints; ++p) { 4321 const PetscInt *support; 4322 PetscInt supportSize, s; 4323 4324 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4325 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4326 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4327 for (s = 0; s < supportSize; ++s) { 4328 const PetscInt *cone, *ornt; 4329 PetscInt coneSize, c; 4330 PetscBool pos = PETSC_TRUE; 4331 4332 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4333 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4334 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4335 for (c = 0; c < coneSize; ++c) { 4336 if (cone[c] == points[p]) { 4337 if (ornt[c] >= 0) { 4338 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4339 } else { 4340 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4341 pos = PETSC_FALSE; 4342 } 4343 break; 4344 } 4345 } 4346 if (c == coneSize) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]); 4347 /* Put faces touching the fault in the label */ 4348 for (c = 0; c < coneSize; ++c) { 4349 const PetscInt point = cone[c]; 4350 4351 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4352 if (val == -1) { 4353 PetscInt *closure = NULL; 4354 PetscInt closureSize, cl; 4355 4356 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4357 for (cl = 0; cl < closureSize*2; cl += 2) { 4358 const PetscInt clp = closure[cl]; 4359 4360 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4361 if ((val >= 0) && (val < dim-1)) { 4362 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4363 break; 4364 } 4365 } 4366 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4367 } 4368 } 4369 } 4370 } 4371 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4372 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4373 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4374 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4375 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4376 if (!dimIS) PetscFunctionReturn(0); 4377 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4378 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4379 for (p = 0; p < numPoints; ++p) { 4380 PetscInt *star = NULL; 4381 PetscInt starSize, s; 4382 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4383 4384 /* First mark cells connected to the fault */ 4385 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4386 while (again) { 4387 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4388 again = 0; 4389 for (s = 0; s < starSize*2; s += 2) { 4390 const PetscInt point = star[s]; 4391 const PetscInt *cone; 4392 PetscInt coneSize, c; 4393 4394 if ((point < cStart) || (point >= cEnd)) continue; 4395 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4396 if (val != -1) continue; 4397 again = 2; 4398 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4399 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4400 for (c = 0; c < coneSize; ++c) { 4401 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4402 if (val != -1) { 4403 if (abs(val) < shift) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 4404 if (val > 0) { 4405 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4406 } else { 4407 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4408 } 4409 again = 1; 4410 break; 4411 } 4412 } 4413 } 4414 } 4415 /* Classify the rest by cell membership */ 4416 for (s = 0; s < starSize*2; s += 2) { 4417 const PetscInt point = star[s]; 4418 4419 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4420 if (val == -1) { 4421 PetscInt *sstar = NULL; 4422 PetscInt sstarSize, ss; 4423 PetscBool marked = PETSC_FALSE; 4424 4425 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4426 for (ss = 0; ss < sstarSize*2; ss += 2) { 4427 const PetscInt spoint = sstar[ss]; 4428 4429 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4430 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4431 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4432 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4433 if (val > 0) { 4434 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4435 } else { 4436 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4437 } 4438 marked = PETSC_TRUE; 4439 break; 4440 } 4441 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4442 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4443 } 4444 } 4445 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4446 } 4447 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4448 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4449 PetscFunctionReturn(0); 4450 } 4451 4452 #undef __FUNCT__ 4453 #define __FUNCT__ "DMPlexInterpolate_2D" 4454 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4455 { 4456 DM idm; 4457 DM_Plex *mesh; 4458 PetscHashIJ edgeTable; 4459 PetscInt *off; 4460 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4461 PetscInt numEdges, firstEdge, edge, e; 4462 PetscErrorCode ierr; 4463 4464 PetscFunctionBegin; 4465 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4466 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4467 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4468 numCells = cEnd - cStart; 4469 numVertices = vEnd - vStart; 4470 firstEdge = numCells + numVertices; 4471 numEdges = 0; 4472 /* Count edges using algorithm from CreateNeighborCSR */ 4473 ierr = DMPlexCreateNeighborCSR(dm, NULL, &off, NULL);CHKERRQ(ierr); 4474 if (off) { 4475 PetscInt numCorners = 0; 4476 4477 numEdges = off[numCells]/2; 4478 #if 0 4479 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4480 numEdges += 3*numCells - off[numCells]; 4481 #else 4482 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4483 for (c = cStart; c < cEnd; ++c) { 4484 PetscInt coneSize; 4485 4486 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4487 numCorners += coneSize; 4488 } 4489 numEdges += numCorners - off[numCells]; 4490 #endif 4491 } 4492 #if 0 4493 /* Check Euler characteristic V - E + F = 1 */ 4494 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4495 #endif 4496 /* Create interpolated mesh */ 4497 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4498 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4499 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4500 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4501 for (c = 0; c < numCells; ++c) { 4502 PetscInt numCorners; 4503 4504 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4505 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4506 } 4507 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4508 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4509 } 4510 ierr = DMSetUp(idm);CHKERRQ(ierr); 4511 /* Get edge cones from subsets of cell vertices */ 4512 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4513 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4514 4515 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4516 const PetscInt *cellFaces; 4517 PetscInt numCellFaces, faceSize, cf; 4518 4519 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4520 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4521 for (cf = 0; cf < numCellFaces; ++cf) { 4522 #if 1 4523 PetscHashIJKey key; 4524 4525 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4526 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4527 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4528 if (e < 0) { 4529 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4530 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4531 e = edge++; 4532 } 4533 #else 4534 PetscBool found = PETSC_FALSE; 4535 4536 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4537 for (e = firstEdge; e < edge; ++e) { 4538 const PetscInt *cone; 4539 4540 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4541 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4542 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4543 found = PETSC_TRUE; 4544 break; 4545 } 4546 } 4547 if (!found) { 4548 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4549 ++edge; 4550 } 4551 #endif 4552 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4553 } 4554 } 4555 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4556 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4557 ierr = PetscFree(off);CHKERRQ(ierr); 4558 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4559 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4560 mesh = (DM_Plex*) (idm)->data; 4561 /* Orient edges */ 4562 for (c = 0; c < numCells; ++c) { 4563 const PetscInt *cone = NULL, *cellFaces; 4564 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4565 4566 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4567 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4568 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4569 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4570 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4571 for (cf = 0; cf < numCellFaces; ++cf) { 4572 const PetscInt *econe = NULL; 4573 PetscInt esize; 4574 4575 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4576 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4577 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4578 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4579 /* Correctly oriented */ 4580 mesh->coneOrientations[coff+cf] = 0; 4581 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4582 /* Start at index 1, and reverse orientation */ 4583 mesh->coneOrientations[coff+cf] = -(1+1); 4584 } 4585 } 4586 } 4587 *dmInt = idm; 4588 PetscFunctionReturn(0); 4589 } 4590 4591 #undef __FUNCT__ 4592 #define __FUNCT__ "DMPlexInterpolate_3D" 4593 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4594 { 4595 DM idm, fdm; 4596 DM_Plex *mesh; 4597 PetscInt *off; 4598 const PetscInt numCorners = 4; 4599 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4600 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4601 PetscErrorCode ierr; 4602 4603 PetscFunctionBegin; 4604 { 4605 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4606 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4607 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4608 } 4609 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4610 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4611 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4612 numCells = cEnd - cStart; 4613 numVertices = vEnd - vStart; 4614 firstFace = numCells + numVertices; 4615 numFaces = 0; 4616 /* Count faces using algorithm from CreateNeighborCSR */ 4617 ierr = DMPlexCreateNeighborCSR(dm, NULL, &off, NULL);CHKERRQ(ierr); 4618 if (off) { 4619 numFaces = off[numCells]/2; 4620 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4621 numFaces += 4*numCells - off[numCells]; 4622 } 4623 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4624 firstEdge = firstFace + numFaces; 4625 numEdges = numVertices + numFaces - numCells - 1; 4626 /* Create interpolated mesh */ 4627 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4628 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4629 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4630 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4631 for (c = 0; c < numCells; ++c) { 4632 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4633 } 4634 for (f = firstFace; f < firstFace+numFaces; ++f) { 4635 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4636 } 4637 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4638 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4639 } 4640 ierr = DMSetUp(idm);CHKERRQ(ierr); 4641 /* Get face cones from subsets of cell vertices */ 4642 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4643 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4644 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4645 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4646 for (f = firstFace; f < firstFace+numFaces; ++f) { 4647 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4648 } 4649 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4650 for (c = 0, face = firstFace; c < numCells; ++c) { 4651 const PetscInt *cellFaces; 4652 PetscInt numCellFaces, faceSize, cf; 4653 4654 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4655 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4656 for (cf = 0; cf < numCellFaces; ++cf) { 4657 PetscBool found = PETSC_FALSE; 4658 4659 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4660 for (f = firstFace; f < face; ++f) { 4661 const PetscInt *cone = NULL; 4662 4663 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4664 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4665 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4666 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4667 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4668 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4669 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4670 found = PETSC_TRUE; 4671 break; 4672 } 4673 } 4674 if (!found) { 4675 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4676 /* Save the vertices for orientation calculation */ 4677 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4678 ++face; 4679 } 4680 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4681 } 4682 } 4683 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4684 /* Get edge cones from subsets of face vertices */ 4685 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4686 const PetscInt *cellFaces; 4687 PetscInt numCellFaces, faceSize, cf; 4688 4689 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4690 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4691 for (cf = 0; cf < numCellFaces; ++cf) { 4692 PetscBool found = PETSC_FALSE; 4693 4694 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4695 for (e = firstEdge; e < edge; ++e) { 4696 const PetscInt *cone = NULL; 4697 4698 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4699 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4700 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4701 found = PETSC_TRUE; 4702 break; 4703 } 4704 } 4705 if (!found) { 4706 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4707 ++edge; 4708 } 4709 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4710 } 4711 } 4712 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4713 ierr = PetscFree(off);CHKERRQ(ierr); 4714 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4715 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4716 mesh = (DM_Plex*) (idm)->data; 4717 /* Orient edges */ 4718 for (f = firstFace; f < firstFace+numFaces; ++f) { 4719 const PetscInt *cone, *cellFaces; 4720 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4721 4722 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4723 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4724 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4725 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4726 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4727 for (cf = 0; cf < numCellFaces; ++cf) { 4728 const PetscInt *econe; 4729 PetscInt esize; 4730 4731 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4732 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4733 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4734 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4735 /* Correctly oriented */ 4736 mesh->coneOrientations[coff+cf] = 0; 4737 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4738 /* Start at index 1, and reverse orientation */ 4739 mesh->coneOrientations[coff+cf] = -(1+1); 4740 } 4741 } 4742 } 4743 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4744 /* Orient faces */ 4745 for (c = 0; c < numCells; ++c) { 4746 const PetscInt *cone, *cellFaces; 4747 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4748 4749 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4750 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4751 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4752 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4753 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4754 for (cf = 0; cf < numCellFaces; ++cf) { 4755 PetscInt *origClosure = NULL, *closure; 4756 PetscInt closureSize, i; 4757 4758 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4759 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4760 for (i = 4; i < 7; ++i) { 4761 if ((origClosure[i*2] < vStart) || (origClosure[i*2] >= vEnd)) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure point %D should be a vertex in [%D, %D)", origClosure[i*2], vStart, vEnd); 4762 } 4763 closure = &origClosure[4*2]; 4764 /* Remember that this is the orientation for edges, not vertices */ 4765 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4766 /* Correctly oriented */ 4767 mesh->coneOrientations[coff+cf] = 0; 4768 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4769 /* Shifted by 1 */ 4770 mesh->coneOrientations[coff+cf] = 1; 4771 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4772 /* Shifted by 2 */ 4773 mesh->coneOrientations[coff+cf] = 2; 4774 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4775 /* Start at edge 1, and reverse orientation */ 4776 mesh->coneOrientations[coff+cf] = -(1+1); 4777 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4778 /* Start at index 0, and reverse orientation */ 4779 mesh->coneOrientations[coff+cf] = -(0+1); 4780 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4781 /* Start at index 2, and reverse orientation */ 4782 mesh->coneOrientations[coff+cf] = -(2+1); 4783 } else SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Face %D did not match local face %D in cell %D for any orientation", cone[cf], cf, c); 4784 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4785 } 4786 } 4787 { 4788 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4789 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4790 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4791 } 4792 *dmInt = idm; 4793 PetscFunctionReturn(0); 4794 } 4795 4796 #undef __FUNCT__ 4797 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4798 /* 4799 This takes as input the common mesh generator output, a list of the vertices for each cell 4800 */ 4801 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4802 { 4803 PetscInt *cone, c, p; 4804 PetscErrorCode ierr; 4805 4806 PetscFunctionBegin; 4807 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4808 for (c = 0; c < numCells; ++c) { 4809 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4810 } 4811 ierr = DMSetUp(dm);CHKERRQ(ierr); 4812 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4813 for (c = 0; c < numCells; ++c) { 4814 for (p = 0; p < numCorners; ++p) { 4815 cone[p] = cells[c*numCorners+p]+numCells; 4816 } 4817 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4818 } 4819 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4820 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4821 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4822 PetscFunctionReturn(0); 4823 } 4824 4825 #undef __FUNCT__ 4826 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4827 /* 4828 This takes as input the coordinates for each vertex 4829 */ 4830 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4831 { 4832 PetscSection coordSection; 4833 Vec coordinates; 4834 PetscScalar *coords; 4835 PetscInt coordSize, v, d; 4836 PetscErrorCode ierr; 4837 4838 PetscFunctionBegin; 4839 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4840 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4841 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4842 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4843 for (v = numCells; v < numCells+numVertices; ++v) { 4844 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4845 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4846 } 4847 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4848 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4849 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4850 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4851 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4852 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4853 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4854 for (v = 0; v < numVertices; ++v) { 4855 for (d = 0; d < spaceDim; ++d) { 4856 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4857 } 4858 } 4859 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4860 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4861 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4862 PetscFunctionReturn(0); 4863 } 4864 4865 #undef __FUNCT__ 4866 #define __FUNCT__ "DMPlexCreateFromCellList" 4867 /* 4868 This takes as input the common mesh generator output, a list of the vertices for each cell 4869 */ 4870 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4871 { 4872 PetscErrorCode ierr; 4873 4874 PetscFunctionBegin; 4875 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4876 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4877 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4878 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4879 if (interpolate) { 4880 DM idm; 4881 4882 switch (dim) { 4883 case 2: 4884 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4885 case 3: 4886 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4887 default: 4888 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4889 } 4890 ierr = DMDestroy(dm);CHKERRQ(ierr); 4891 *dm = idm; 4892 } 4893 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4894 PetscFunctionReturn(0); 4895 } 4896 4897 #if defined(PETSC_HAVE_TRIANGLE) 4898 #include <triangle.h> 4899 4900 #undef __FUNCT__ 4901 #define __FUNCT__ "InitInput_Triangle" 4902 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4903 { 4904 PetscFunctionBegin; 4905 inputCtx->numberofpoints = 0; 4906 inputCtx->numberofpointattributes = 0; 4907 inputCtx->pointlist = NULL; 4908 inputCtx->pointattributelist = NULL; 4909 inputCtx->pointmarkerlist = NULL; 4910 inputCtx->numberofsegments = 0; 4911 inputCtx->segmentlist = NULL; 4912 inputCtx->segmentmarkerlist = NULL; 4913 inputCtx->numberoftriangleattributes = 0; 4914 inputCtx->trianglelist = NULL; 4915 inputCtx->numberofholes = 0; 4916 inputCtx->holelist = NULL; 4917 inputCtx->numberofregions = 0; 4918 inputCtx->regionlist = NULL; 4919 PetscFunctionReturn(0); 4920 } 4921 4922 #undef __FUNCT__ 4923 #define __FUNCT__ "InitOutput_Triangle" 4924 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4925 { 4926 PetscFunctionBegin; 4927 outputCtx->numberofpoints = 0; 4928 outputCtx->pointlist = NULL; 4929 outputCtx->pointattributelist = NULL; 4930 outputCtx->pointmarkerlist = NULL; 4931 outputCtx->numberoftriangles = 0; 4932 outputCtx->trianglelist = NULL; 4933 outputCtx->triangleattributelist = NULL; 4934 outputCtx->neighborlist = NULL; 4935 outputCtx->segmentlist = NULL; 4936 outputCtx->segmentmarkerlist = NULL; 4937 outputCtx->numberofedges = 0; 4938 outputCtx->edgelist = NULL; 4939 outputCtx->edgemarkerlist = NULL; 4940 PetscFunctionReturn(0); 4941 } 4942 4943 #undef __FUNCT__ 4944 #define __FUNCT__ "FiniOutput_Triangle" 4945 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4946 { 4947 PetscFunctionBegin; 4948 free(outputCtx->pointmarkerlist); 4949 free(outputCtx->edgelist); 4950 free(outputCtx->edgemarkerlist); 4951 free(outputCtx->trianglelist); 4952 free(outputCtx->neighborlist); 4953 PetscFunctionReturn(0); 4954 } 4955 4956 #undef __FUNCT__ 4957 #define __FUNCT__ "DMPlexGenerate_Triangle" 4958 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4959 { 4960 MPI_Comm comm = ((PetscObject) boundary)->comm; 4961 PetscInt dim = 2; 4962 const PetscBool createConvexHull = PETSC_FALSE; 4963 const PetscBool constrained = PETSC_FALSE; 4964 struct triangulateio in; 4965 struct triangulateio out; 4966 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4967 PetscMPIInt rank; 4968 PetscErrorCode ierr; 4969 4970 PetscFunctionBegin; 4971 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4972 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4973 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4974 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4975 4976 in.numberofpoints = vEnd - vStart; 4977 if (in.numberofpoints > 0) { 4978 PetscSection coordSection; 4979 Vec coordinates; 4980 PetscScalar *array; 4981 4982 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4983 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4984 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4985 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4986 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4987 for (v = vStart; v < vEnd; ++v) { 4988 const PetscInt idx = v - vStart; 4989 PetscInt off, d; 4990 4991 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4992 for (d = 0; d < dim; ++d) { 4993 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4994 } 4995 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4996 } 4997 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4998 } 4999 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 5000 in.numberofsegments = eEnd - eStart; 5001 if (in.numberofsegments > 0) { 5002 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 5003 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 5004 for (e = eStart; e < eEnd; ++e) { 5005 const PetscInt idx = e - eStart; 5006 const PetscInt *cone; 5007 5008 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 5009 5010 in.segmentlist[idx*2+0] = cone[0] - vStart; 5011 in.segmentlist[idx*2+1] = cone[1] - vStart; 5012 5013 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5014 } 5015 } 5016 #if 0 /* Do not currently support holes */ 5017 PetscReal *holeCoords; 5018 PetscInt h, d; 5019 5020 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5021 if (in.numberofholes > 0) { 5022 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5023 for (h = 0; h < in.numberofholes; ++h) { 5024 for (d = 0; d < dim; ++d) { 5025 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5026 } 5027 } 5028 } 5029 #endif 5030 if (!rank) { 5031 char args[32]; 5032 5033 /* Take away 'Q' for verbose output */ 5034 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5035 if (createConvexHull) { 5036 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5037 } 5038 if (constrained) { 5039 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5040 } 5041 triangulate(args, &in, &out, NULL); 5042 } 5043 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5044 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5045 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5046 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5047 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5048 5049 { 5050 const PetscInt numCorners = 3; 5051 const PetscInt numCells = out.numberoftriangles; 5052 const PetscInt numVertices = out.numberofpoints; 5053 const int *cells = out.trianglelist; 5054 const double *meshCoords = out.pointlist; 5055 5056 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5057 /* Set labels */ 5058 for (v = 0; v < numVertices; ++v) { 5059 if (out.pointmarkerlist[v]) { 5060 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5061 } 5062 } 5063 if (interpolate) { 5064 for (e = 0; e < out.numberofedges; e++) { 5065 if (out.edgemarkerlist[e]) { 5066 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5067 const PetscInt *edges; 5068 PetscInt numEdges; 5069 5070 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5071 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5072 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5073 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5074 } 5075 } 5076 } 5077 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5078 } 5079 #if 0 /* Do not currently support holes */ 5080 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5081 #endif 5082 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5083 PetscFunctionReturn(0); 5084 } 5085 5086 #undef __FUNCT__ 5087 #define __FUNCT__ "DMPlexRefine_Triangle" 5088 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5089 { 5090 MPI_Comm comm = ((PetscObject) dm)->comm; 5091 PetscInt dim = 2; 5092 struct triangulateio in; 5093 struct triangulateio out; 5094 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5095 PetscMPIInt rank; 5096 PetscErrorCode ierr; 5097 5098 PetscFunctionBegin; 5099 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5100 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5101 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5102 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5103 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5104 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5105 5106 in.numberofpoints = vEnd - vStart; 5107 if (in.numberofpoints > 0) { 5108 PetscSection coordSection; 5109 Vec coordinates; 5110 PetscScalar *array; 5111 5112 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5113 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5114 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5115 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5116 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5117 for (v = vStart; v < vEnd; ++v) { 5118 const PetscInt idx = v - vStart; 5119 PetscInt off, d; 5120 5121 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5122 for (d = 0; d < dim; ++d) { 5123 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5124 } 5125 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5126 } 5127 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5128 } 5129 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5130 5131 in.numberofcorners = 3; 5132 in.numberoftriangles = cEnd - cStart; 5133 5134 in.trianglearealist = (double*) maxVolumes; 5135 if (in.numberoftriangles > 0) { 5136 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5137 for (c = cStart; c < cEnd; ++c) { 5138 const PetscInt idx = c - cStart; 5139 PetscInt *closure = NULL; 5140 PetscInt closureSize; 5141 5142 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5143 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5144 for (v = 0; v < 3; ++v) { 5145 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5146 } 5147 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5148 } 5149 } 5150 /* TODO: Segment markers are missing on input */ 5151 #if 0 /* Do not currently support holes */ 5152 PetscReal *holeCoords; 5153 PetscInt h, d; 5154 5155 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5156 if (in.numberofholes > 0) { 5157 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5158 for (h = 0; h < in.numberofholes; ++h) { 5159 for (d = 0; d < dim; ++d) { 5160 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5161 } 5162 } 5163 } 5164 #endif 5165 if (!rank) { 5166 char args[32]; 5167 5168 /* Take away 'Q' for verbose output */ 5169 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5170 triangulate(args, &in, &out, NULL); 5171 } 5172 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5173 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5174 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5175 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5176 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5177 5178 { 5179 const PetscInt numCorners = 3; 5180 const PetscInt numCells = out.numberoftriangles; 5181 const PetscInt numVertices = out.numberofpoints; 5182 const int *cells = out.trianglelist; 5183 const double *meshCoords = out.pointlist; 5184 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5185 5186 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5187 /* Set labels */ 5188 for (v = 0; v < numVertices; ++v) { 5189 if (out.pointmarkerlist[v]) { 5190 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5191 } 5192 } 5193 if (interpolate) { 5194 PetscInt e; 5195 5196 for (e = 0; e < out.numberofedges; e++) { 5197 if (out.edgemarkerlist[e]) { 5198 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5199 const PetscInt *edges; 5200 PetscInt numEdges; 5201 5202 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5203 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5204 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5205 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5206 } 5207 } 5208 } 5209 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5210 } 5211 #if 0 /* Do not currently support holes */ 5212 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5213 #endif 5214 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5215 PetscFunctionReturn(0); 5216 } 5217 #endif 5218 5219 #if defined(PETSC_HAVE_TETGEN) 5220 #include <tetgen.h> 5221 #undef __FUNCT__ 5222 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5223 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5224 { 5225 MPI_Comm comm = ((PetscObject) boundary)->comm; 5226 const PetscInt dim = 3; 5227 ::tetgenio in; 5228 ::tetgenio out; 5229 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5230 PetscMPIInt rank; 5231 PetscErrorCode ierr; 5232 5233 PetscFunctionBegin; 5234 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5235 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5236 in.numberofpoints = vEnd - vStart; 5237 if (in.numberofpoints > 0) { 5238 PetscSection coordSection; 5239 Vec coordinates; 5240 PetscScalar *array; 5241 5242 in.pointlist = new double[in.numberofpoints*dim]; 5243 in.pointmarkerlist = new int[in.numberofpoints]; 5244 5245 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5246 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5247 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5248 for (v = vStart; v < vEnd; ++v) { 5249 const PetscInt idx = v - vStart; 5250 PetscInt off, d; 5251 5252 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5253 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5254 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5255 } 5256 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5257 } 5258 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5259 5260 in.numberoffacets = fEnd - fStart; 5261 if (in.numberoffacets > 0) { 5262 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5263 in.facetmarkerlist = new int[in.numberoffacets]; 5264 for (f = fStart; f < fEnd; ++f) { 5265 const PetscInt idx = f - fStart; 5266 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 5267 5268 in.facetlist[idx].numberofpolygons = 1; 5269 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5270 in.facetlist[idx].numberofholes = 0; 5271 in.facetlist[idx].holelist = NULL; 5272 5273 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5274 for (p = 0; p < numPoints*2; p += 2) { 5275 const PetscInt point = points[p]; 5276 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5277 } 5278 5279 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5280 poly->numberofvertices = numVertices; 5281 poly->vertexlist = new int[poly->numberofvertices]; 5282 for (v = 0; v < numVertices; ++v) { 5283 const PetscInt vIdx = points[v] - vStart; 5284 poly->vertexlist[v] = vIdx; 5285 } 5286 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5287 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5288 } 5289 } 5290 if (!rank) { 5291 char args[32]; 5292 5293 /* Take away 'Q' for verbose output */ 5294 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5295 ::tetrahedralize(args, &in, &out); 5296 } 5297 { 5298 const PetscInt numCorners = 4; 5299 const PetscInt numCells = out.numberoftetrahedra; 5300 const PetscInt numVertices = out.numberofpoints; 5301 const int *cells = out.tetrahedronlist; 5302 const double *meshCoords = out.pointlist; 5303 5304 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5305 /* Set labels */ 5306 for (v = 0; v < numVertices; ++v) { 5307 if (out.pointmarkerlist[v]) { 5308 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5309 } 5310 } 5311 if (interpolate) { 5312 PetscInt e; 5313 5314 for (e = 0; e < out.numberofedges; e++) { 5315 if (out.edgemarkerlist[e]) { 5316 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5317 const PetscInt *edges; 5318 PetscInt numEdges; 5319 5320 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5321 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5322 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5323 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5324 } 5325 } 5326 for (f = 0; f < out.numberoftrifaces; f++) { 5327 if (out.trifacemarkerlist[f]) { 5328 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5329 const PetscInt *faces; 5330 PetscInt numFaces; 5331 5332 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5333 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5334 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5335 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5336 } 5337 } 5338 } 5339 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5340 } 5341 PetscFunctionReturn(0); 5342 } 5343 5344 #undef __FUNCT__ 5345 #define __FUNCT__ "DMPlexRefine_Tetgen" 5346 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5347 { 5348 MPI_Comm comm = ((PetscObject) dm)->comm; 5349 const PetscInt dim = 3; 5350 ::tetgenio in; 5351 ::tetgenio out; 5352 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5353 PetscMPIInt rank; 5354 PetscErrorCode ierr; 5355 5356 PetscFunctionBegin; 5357 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5358 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5359 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5360 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5361 5362 in.numberofpoints = vEnd - vStart; 5363 if (in.numberofpoints > 0) { 5364 PetscSection coordSection; 5365 Vec coordinates; 5366 PetscScalar *array; 5367 5368 in.pointlist = new double[in.numberofpoints*dim]; 5369 in.pointmarkerlist = new int[in.numberofpoints]; 5370 5371 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5372 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5373 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5374 for (v = vStart; v < vEnd; ++v) { 5375 const PetscInt idx = v - vStart; 5376 PetscInt off, d; 5377 5378 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5379 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5380 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5381 } 5382 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5383 } 5384 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5385 5386 in.numberofcorners = 4; 5387 in.numberoftetrahedra = cEnd - cStart; 5388 in.tetrahedronvolumelist = (double*) maxVolumes; 5389 if (in.numberoftetrahedra > 0) { 5390 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5391 for (c = cStart; c < cEnd; ++c) { 5392 const PetscInt idx = c - cStart; 5393 PetscInt *closure = NULL; 5394 PetscInt closureSize; 5395 5396 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5397 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5398 for (v = 0; v < 4; ++v) { 5399 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5400 } 5401 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5402 } 5403 } 5404 /* TODO: Put in boundary faces with markers */ 5405 if (!rank) { 5406 char args[32]; 5407 5408 /* Take away 'Q' for verbose output */ 5409 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5410 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5411 ::tetrahedralize(args, &in, &out); 5412 } 5413 in.tetrahedronvolumelist = NULL; 5414 5415 { 5416 const PetscInt numCorners = 4; 5417 const PetscInt numCells = out.numberoftetrahedra; 5418 const PetscInt numVertices = out.numberofpoints; 5419 const int *cells = out.tetrahedronlist; 5420 const double *meshCoords = out.pointlist; 5421 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5422 5423 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5424 /* Set labels */ 5425 for (v = 0; v < numVertices; ++v) { 5426 if (out.pointmarkerlist[v]) { 5427 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5428 } 5429 } 5430 if (interpolate) { 5431 PetscInt e, f; 5432 5433 for (e = 0; e < out.numberofedges; e++) { 5434 if (out.edgemarkerlist[e]) { 5435 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5436 const PetscInt *edges; 5437 PetscInt numEdges; 5438 5439 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5440 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5441 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5442 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5443 } 5444 } 5445 for (f = 0; f < out.numberoftrifaces; f++) { 5446 if (out.trifacemarkerlist[f]) { 5447 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5448 const PetscInt *faces; 5449 PetscInt numFaces; 5450 5451 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5452 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5453 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5454 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5455 } 5456 } 5457 } 5458 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5459 } 5460 PetscFunctionReturn(0); 5461 } 5462 #endif 5463 5464 #if defined(PETSC_HAVE_CTETGEN) 5465 #include "ctetgen.h" 5466 5467 #undef __FUNCT__ 5468 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5469 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5470 { 5471 MPI_Comm comm = ((PetscObject) boundary)->comm; 5472 const PetscInt dim = 3; 5473 PLC *in, *out; 5474 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5475 PetscMPIInt rank; 5476 PetscErrorCode ierr; 5477 5478 PetscFunctionBegin; 5479 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5480 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5481 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5482 ierr = PLCCreate(&in);CHKERRQ(ierr); 5483 ierr = PLCCreate(&out);CHKERRQ(ierr); 5484 5485 in->numberofpoints = vEnd - vStart; 5486 if (in->numberofpoints > 0) { 5487 PetscSection coordSection; 5488 Vec coordinates; 5489 PetscScalar *array; 5490 5491 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5492 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5493 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5494 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5495 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5496 for (v = vStart; v < vEnd; ++v) { 5497 const PetscInt idx = v - vStart; 5498 PetscInt off, d, m; 5499 5500 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5501 for (d = 0; d < dim; ++d) { 5502 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5503 } 5504 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5505 5506 in->pointmarkerlist[idx] = (int) m; 5507 } 5508 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5509 } 5510 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5511 5512 in->numberoffacets = fEnd - fStart; 5513 if (in->numberoffacets > 0) { 5514 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5515 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5516 for (f = fStart; f < fEnd; ++f) { 5517 const PetscInt idx = f - fStart; 5518 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5519 polygon *poly; 5520 5521 in->facetlist[idx].numberofpolygons = 1; 5522 5523 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5524 5525 in->facetlist[idx].numberofholes = 0; 5526 in->facetlist[idx].holelist = NULL; 5527 5528 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5529 for (p = 0; p < numPoints*2; p += 2) { 5530 const PetscInt point = points[p]; 5531 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5532 } 5533 5534 poly = in->facetlist[idx].polygonlist; 5535 poly->numberofvertices = numVertices; 5536 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5537 for (v = 0; v < numVertices; ++v) { 5538 const PetscInt vIdx = points[v] - vStart; 5539 poly->vertexlist[v] = vIdx; 5540 } 5541 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5542 in->facetmarkerlist[idx] = (int) m; 5543 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5544 } 5545 } 5546 if (!rank) { 5547 TetGenOpts t; 5548 5549 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5550 t.in = boundary; /* Should go away */ 5551 t.plc = 1; 5552 t.quality = 1; 5553 t.edgesout = 1; 5554 t.zeroindex = 1; 5555 t.quiet = 1; 5556 t.verbose = verbose; 5557 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5558 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5559 } 5560 { 5561 const PetscInt numCorners = 4; 5562 const PetscInt numCells = out->numberoftetrahedra; 5563 const PetscInt numVertices = out->numberofpoints; 5564 const int *cells = out->tetrahedronlist; 5565 const double *meshCoords = out->pointlist; 5566 5567 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5568 /* Set labels */ 5569 for (v = 0; v < numVertices; ++v) { 5570 if (out->pointmarkerlist[v]) { 5571 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5572 } 5573 } 5574 if (interpolate) { 5575 PetscInt e; 5576 5577 for (e = 0; e < out->numberofedges; e++) { 5578 if (out->edgemarkerlist[e]) { 5579 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5580 const PetscInt *edges; 5581 PetscInt numEdges; 5582 5583 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5584 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5585 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5586 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5587 } 5588 } 5589 for (f = 0; f < out->numberoftrifaces; f++) { 5590 if (out->trifacemarkerlist[f]) { 5591 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5592 const PetscInt *faces; 5593 PetscInt numFaces; 5594 5595 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5596 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5597 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5598 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5599 } 5600 } 5601 } 5602 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5603 } 5604 5605 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5606 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5607 PetscFunctionReturn(0); 5608 } 5609 5610 #undef __FUNCT__ 5611 #define __FUNCT__ "DMPlexRefine_CTetgen" 5612 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5613 { 5614 MPI_Comm comm = ((PetscObject) dm)->comm; 5615 const PetscInt dim = 3; 5616 PLC *in, *out; 5617 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5618 PetscMPIInt rank; 5619 PetscErrorCode ierr; 5620 5621 PetscFunctionBegin; 5622 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5623 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5624 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5625 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5626 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5627 ierr = PLCCreate(&in);CHKERRQ(ierr); 5628 ierr = PLCCreate(&out);CHKERRQ(ierr); 5629 5630 in->numberofpoints = vEnd - vStart; 5631 if (in->numberofpoints > 0) { 5632 PetscSection coordSection; 5633 Vec coordinates; 5634 PetscScalar *array; 5635 5636 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5637 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5638 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5639 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5640 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5641 for (v = vStart; v < vEnd; ++v) { 5642 const PetscInt idx = v - vStart; 5643 PetscInt off, d, m; 5644 5645 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5646 for (d = 0; d < dim; ++d) { 5647 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5648 } 5649 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5650 5651 in->pointmarkerlist[idx] = (int) m; 5652 } 5653 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5654 } 5655 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5656 5657 in->numberofcorners = 4; 5658 in->numberoftetrahedra = cEnd - cStart; 5659 in->tetrahedronvolumelist = maxVolumes; 5660 if (in->numberoftetrahedra > 0) { 5661 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5662 for (c = cStart; c < cEnd; ++c) { 5663 const PetscInt idx = c - cStart; 5664 PetscInt *closure = NULL; 5665 PetscInt closureSize; 5666 5667 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5668 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5669 for (v = 0; v < 4; ++v) { 5670 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5671 } 5672 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5673 } 5674 } 5675 if (!rank) { 5676 TetGenOpts t; 5677 5678 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5679 5680 t.in = dm; /* Should go away */ 5681 t.refine = 1; 5682 t.varvolume = 1; 5683 t.quality = 1; 5684 t.edgesout = 1; 5685 t.zeroindex = 1; 5686 t.quiet = 1; 5687 t.verbose = verbose; /* Change this */ 5688 5689 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5690 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5691 } 5692 { 5693 const PetscInt numCorners = 4; 5694 const PetscInt numCells = out->numberoftetrahedra; 5695 const PetscInt numVertices = out->numberofpoints; 5696 const int *cells = out->tetrahedronlist; 5697 const double *meshCoords = out->pointlist; 5698 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5699 5700 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5701 /* Set labels */ 5702 for (v = 0; v < numVertices; ++v) { 5703 if (out->pointmarkerlist[v]) { 5704 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5705 } 5706 } 5707 if (interpolate) { 5708 PetscInt e, f; 5709 5710 for (e = 0; e < out->numberofedges; e++) { 5711 if (out->edgemarkerlist[e]) { 5712 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5713 const PetscInt *edges; 5714 PetscInt numEdges; 5715 5716 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5717 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5718 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5719 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5720 } 5721 } 5722 for (f = 0; f < out->numberoftrifaces; f++) { 5723 if (out->trifacemarkerlist[f]) { 5724 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5725 const PetscInt *faces; 5726 PetscInt numFaces; 5727 5728 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5729 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5730 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5731 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5732 } 5733 } 5734 } 5735 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5736 } 5737 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5738 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5739 PetscFunctionReturn(0); 5740 } 5741 #endif 5742 5743 #undef __FUNCT__ 5744 #define __FUNCT__ "DMPlexGenerate" 5745 /*@C 5746 DMPlexGenerate - Generates a mesh. 5747 5748 Not Collective 5749 5750 Input Parameters: 5751 + boundary - The DMPlex boundary object 5752 . name - The mesh generation package name 5753 - interpolate - Flag to create intermediate mesh elements 5754 5755 Output Parameter: 5756 . mesh - The DMPlex object 5757 5758 Level: intermediate 5759 5760 .keywords: mesh, elements 5761 .seealso: DMPlexCreate(), DMRefine() 5762 @*/ 5763 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5764 { 5765 PetscInt dim; 5766 char genname[1024]; 5767 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5768 PetscErrorCode ierr; 5769 5770 PetscFunctionBegin; 5771 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5772 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5773 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5774 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5775 if (flg) name = genname; 5776 if (name) { 5777 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5778 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5779 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5780 } 5781 switch (dim) { 5782 case 1: 5783 if (!name || isTriangle) { 5784 #if defined(PETSC_HAVE_TRIANGLE) 5785 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5786 #else 5787 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5788 #endif 5789 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5790 break; 5791 case 2: 5792 if (!name || isCTetgen) { 5793 #if defined(PETSC_HAVE_CTETGEN) 5794 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5795 #else 5796 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5797 #endif 5798 } else if (isTetgen) { 5799 #if defined(PETSC_HAVE_TETGEN) 5800 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5801 #else 5802 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5803 #endif 5804 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5805 break; 5806 default: 5807 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5808 } 5809 PetscFunctionReturn(0); 5810 } 5811 5812 typedef PetscInt CellRefiner; 5813 5814 #undef __FUNCT__ 5815 #define __FUNCT__ "GetDepthStart_Private" 5816 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5817 { 5818 PetscFunctionBegin; 5819 if (cStart) *cStart = 0; 5820 if (vStart) *vStart = depthSize[depth]; 5821 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5822 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5823 PetscFunctionReturn(0); 5824 } 5825 5826 #undef __FUNCT__ 5827 #define __FUNCT__ "GetDepthEnd_Private" 5828 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5829 { 5830 PetscFunctionBegin; 5831 if (cEnd) *cEnd = depthSize[depth]; 5832 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5833 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5834 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5835 PetscFunctionReturn(0); 5836 } 5837 5838 #undef __FUNCT__ 5839 #define __FUNCT__ "CellRefinerGetSizes" 5840 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5841 { 5842 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5843 PetscErrorCode ierr; 5844 5845 PetscFunctionBegin; 5846 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5847 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5848 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5849 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5850 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5851 switch (refiner) { 5852 case 1: 5853 /* Simplicial 2D */ 5854 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5855 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5856 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5857 break; 5858 case 3: 5859 /* Hybrid 2D */ 5860 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5861 cMax = PetscMin(cEnd, cMax); 5862 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5863 fMax = PetscMin(fEnd, fMax); 5864 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5865 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 */ 5866 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5867 break; 5868 case 2: 5869 /* Hex 2D */ 5870 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5871 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5872 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5873 break; 5874 default: 5875 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5876 } 5877 PetscFunctionReturn(0); 5878 } 5879 5880 #undef __FUNCT__ 5881 #define __FUNCT__ "CellRefinerSetConeSizes" 5882 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5883 { 5884 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5885 PetscErrorCode ierr; 5886 5887 PetscFunctionBegin; 5888 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5889 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5890 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5891 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5892 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5893 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5894 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5895 switch (refiner) { 5896 case 1: 5897 /* Simplicial 2D */ 5898 /* All cells have 3 faces */ 5899 for (c = cStart; c < cEnd; ++c) { 5900 for (r = 0; r < 4; ++r) { 5901 const PetscInt newp = (c - cStart)*4 + r; 5902 5903 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5904 } 5905 } 5906 /* Split faces have 2 vertices and the same cells as the parent */ 5907 for (f = fStart; f < fEnd; ++f) { 5908 for (r = 0; r < 2; ++r) { 5909 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5910 PetscInt size; 5911 5912 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5913 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5914 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5915 } 5916 } 5917 /* Interior faces have 2 vertices and 2 cells */ 5918 for (c = cStart; c < cEnd; ++c) { 5919 for (r = 0; r < 3; ++r) { 5920 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5921 5922 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5923 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5924 } 5925 } 5926 /* Old vertices have identical supports */ 5927 for (v = vStart; v < vEnd; ++v) { 5928 const PetscInt newp = vStartNew + (v - vStart); 5929 PetscInt size; 5930 5931 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5932 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5933 } 5934 /* Face vertices have 2 + cells*2 supports */ 5935 for (f = fStart; f < fEnd; ++f) { 5936 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5937 PetscInt size; 5938 5939 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5940 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5941 } 5942 break; 5943 case 2: 5944 /* Hex 2D */ 5945 /* All cells have 4 faces */ 5946 for (c = cStart; c < cEnd; ++c) { 5947 for (r = 0; r < 4; ++r) { 5948 const PetscInt newp = (c - cStart)*4 + r; 5949 5950 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5951 } 5952 } 5953 /* Split faces have 2 vertices and the same cells as the parent */ 5954 for (f = fStart; f < fEnd; ++f) { 5955 for (r = 0; r < 2; ++r) { 5956 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5957 PetscInt size; 5958 5959 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5960 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5961 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5962 } 5963 } 5964 /* Interior faces have 2 vertices and 2 cells */ 5965 for (c = cStart; c < cEnd; ++c) { 5966 for (r = 0; r < 4; ++r) { 5967 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5968 5969 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5970 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5971 } 5972 } 5973 /* Old vertices have identical supports */ 5974 for (v = vStart; v < vEnd; ++v) { 5975 const PetscInt newp = vStartNew + (v - vStart); 5976 PetscInt size; 5977 5978 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5979 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5980 } 5981 /* Face vertices have 2 + cells supports */ 5982 for (f = fStart; f < fEnd; ++f) { 5983 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5984 PetscInt size; 5985 5986 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5987 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5988 } 5989 /* Cell vertices have 4 supports */ 5990 for (c = cStart; c < cEnd; ++c) { 5991 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5992 5993 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5994 } 5995 break; 5996 case 3: 5997 /* Hybrid 2D */ 5998 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5999 cMax = PetscMin(cEnd, cMax); 6000 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6001 fMax = PetscMin(fEnd, fMax); 6002 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6003 /* Interior cells have 3 faces */ 6004 for (c = cStart; c < cMax; ++c) { 6005 for (r = 0; r < 4; ++r) { 6006 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 6007 6008 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 6009 } 6010 } 6011 /* Hybrid cells have 4 faces */ 6012 for (c = cMax; c < cEnd; ++c) { 6013 for (r = 0; r < 2; ++r) { 6014 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6015 6016 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6017 } 6018 } 6019 /* Interior split faces have 2 vertices and the same cells as the parent */ 6020 for (f = fStart; f < fMax; ++f) { 6021 for (r = 0; r < 2; ++r) { 6022 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6023 PetscInt size; 6024 6025 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6026 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6027 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6028 } 6029 } 6030 /* Interior cell faces have 2 vertices and 2 cells */ 6031 for (c = cStart; c < cMax; ++c) { 6032 for (r = 0; r < 3; ++r) { 6033 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6034 6035 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6036 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6037 } 6038 } 6039 /* Hybrid faces have 2 vertices and the same cells */ 6040 for (f = fMax; f < fEnd; ++f) { 6041 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6042 PetscInt size; 6043 6044 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6045 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6046 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6047 } 6048 /* Hybrid cell faces have 2 vertices and 2 cells */ 6049 for (c = cMax; c < cEnd; ++c) { 6050 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6051 6052 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6053 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6054 } 6055 /* Old vertices have identical supports */ 6056 for (v = vStart; v < vEnd; ++v) { 6057 const PetscInt newp = vStartNew + (v - vStart); 6058 PetscInt size; 6059 6060 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6061 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6062 } 6063 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6064 for (f = fStart; f < fMax; ++f) { 6065 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6066 const PetscInt *support; 6067 PetscInt size, newSize = 2, s; 6068 6069 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6070 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6071 for (s = 0; s < size; ++s) { 6072 if (support[s] >= cMax) newSize += 1; 6073 else newSize += 2; 6074 } 6075 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6076 } 6077 break; 6078 default: 6079 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6080 } 6081 PetscFunctionReturn(0); 6082 } 6083 6084 #undef __FUNCT__ 6085 #define __FUNCT__ "CellRefinerSetCones" 6086 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6087 { 6088 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; 6089 PetscInt maxSupportSize, *supportRef; 6090 PetscErrorCode ierr; 6091 6092 PetscFunctionBegin; 6093 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6094 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6095 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6096 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6097 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6098 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6099 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6100 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6101 switch (refiner) { 6102 case 1: 6103 /* Simplicial 2D */ 6104 /* 6105 2 6106 |\ 6107 | \ 6108 | \ 6109 | \ 6110 | C \ 6111 | \ 6112 | \ 6113 2---1---1 6114 |\ D / \ 6115 | 2 0 \ 6116 |A \ / B \ 6117 0---0-------1 6118 */ 6119 /* All cells have 3 faces */ 6120 for (c = cStart; c < cEnd; ++c) { 6121 const PetscInt newp = cStartNew + (c - cStart)*4; 6122 const PetscInt *cone, *ornt; 6123 PetscInt coneNew[3], orntNew[3]; 6124 6125 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6126 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6127 /* A triangle */ 6128 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6129 orntNew[0] = ornt[0]; 6130 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6131 orntNew[1] = -2; 6132 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6133 orntNew[2] = ornt[2]; 6134 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6135 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6136 #if 1 6137 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6138 for (p = 0; p < 3; ++p) { 6139 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6140 } 6141 #endif 6142 /* B triangle */ 6143 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6144 orntNew[0] = ornt[0]; 6145 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6146 orntNew[1] = ornt[1]; 6147 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6148 orntNew[2] = -2; 6149 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6150 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6151 #if 1 6152 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6153 for (p = 0; p < 3; ++p) { 6154 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6155 } 6156 #endif 6157 /* C triangle */ 6158 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6159 orntNew[0] = -2; 6160 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6161 orntNew[1] = ornt[1]; 6162 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6163 orntNew[2] = ornt[2]; 6164 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6165 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6166 #if 1 6167 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6168 for (p = 0; p < 3; ++p) { 6169 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6170 } 6171 #endif 6172 /* D triangle */ 6173 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6174 orntNew[0] = 0; 6175 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6176 orntNew[1] = 0; 6177 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6178 orntNew[2] = 0; 6179 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6180 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6181 #if 1 6182 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6183 for (p = 0; p < 3; ++p) { 6184 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6185 } 6186 #endif 6187 } 6188 /* Split faces have 2 vertices and the same cells as the parent */ 6189 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6190 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6191 for (f = fStart; f < fEnd; ++f) { 6192 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6193 6194 for (r = 0; r < 2; ++r) { 6195 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6196 const PetscInt *cone, *support; 6197 PetscInt coneNew[2], coneSize, c, supportSize, s; 6198 6199 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6200 coneNew[0] = vStartNew + (cone[0] - vStart); 6201 coneNew[1] = vStartNew + (cone[1] - vStart); 6202 coneNew[(r+1)%2] = newv; 6203 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6204 #if 1 6205 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6206 for (p = 0; p < 2; ++p) { 6207 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6208 } 6209 #endif 6210 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6211 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6212 for (s = 0; s < supportSize; ++s) { 6213 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6214 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6215 for (c = 0; c < coneSize; ++c) { 6216 if (cone[c] == f) break; 6217 } 6218 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6219 } 6220 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6221 #if 1 6222 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6223 for (p = 0; p < supportSize; ++p) { 6224 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6225 } 6226 #endif 6227 } 6228 } 6229 /* Interior faces have 2 vertices and 2 cells */ 6230 for (c = cStart; c < cEnd; ++c) { 6231 const PetscInt *cone; 6232 6233 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6234 for (r = 0; r < 3; ++r) { 6235 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6236 PetscInt coneNew[2]; 6237 PetscInt supportNew[2]; 6238 6239 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6240 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6241 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6242 #if 1 6243 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6244 for (p = 0; p < 2; ++p) { 6245 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6246 } 6247 #endif 6248 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6249 supportNew[1] = (c - cStart)*4 + 3; 6250 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6251 #if 1 6252 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6253 for (p = 0; p < 2; ++p) { 6254 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6255 } 6256 #endif 6257 } 6258 } 6259 /* Old vertices have identical supports */ 6260 for (v = vStart; v < vEnd; ++v) { 6261 const PetscInt newp = vStartNew + (v - vStart); 6262 const PetscInt *support, *cone; 6263 PetscInt size, s; 6264 6265 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6266 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6267 for (s = 0; s < size; ++s) { 6268 PetscInt r = 0; 6269 6270 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6271 if (cone[1] == v) r = 1; 6272 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6273 } 6274 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6275 #if 1 6276 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6277 for (p = 0; p < size; ++p) { 6278 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6279 } 6280 #endif 6281 } 6282 /* Face vertices have 2 + cells*2 supports */ 6283 for (f = fStart; f < fEnd; ++f) { 6284 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6285 const PetscInt *cone, *support; 6286 PetscInt size, s; 6287 6288 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6289 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6290 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6291 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6292 for (s = 0; s < size; ++s) { 6293 PetscInt r = 0; 6294 6295 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6296 if (cone[1] == f) r = 1; 6297 else if (cone[2] == f) r = 2; 6298 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6299 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6300 } 6301 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6302 #if 1 6303 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6304 for (p = 0; p < 2+size*2; ++p) { 6305 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6306 } 6307 #endif 6308 } 6309 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6310 break; 6311 case 2: 6312 /* Hex 2D */ 6313 /* 6314 3---------2---------2 6315 | | | 6316 | D 2 C | 6317 | | | 6318 3----3----0----1----1 6319 | | | 6320 | A 0 B | 6321 | | | 6322 0---------0---------1 6323 */ 6324 /* All cells have 4 faces */ 6325 for (c = cStart; c < cEnd; ++c) { 6326 const PetscInt newp = (c - cStart)*4; 6327 const PetscInt *cone, *ornt; 6328 PetscInt coneNew[4], orntNew[4]; 6329 6330 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6331 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6332 /* A quad */ 6333 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6334 orntNew[0] = ornt[0]; 6335 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6336 orntNew[1] = 0; 6337 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6338 orntNew[2] = -2; 6339 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6340 orntNew[3] = ornt[3]; 6341 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6342 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6343 #if 1 6344 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6345 for (p = 0; p < 4; ++p) { 6346 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6347 } 6348 #endif 6349 /* B quad */ 6350 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6351 orntNew[0] = ornt[0]; 6352 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6353 orntNew[1] = ornt[1]; 6354 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6355 orntNew[2] = 0; 6356 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6357 orntNew[3] = -2; 6358 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6359 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6360 #if 1 6361 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6362 for (p = 0; p < 4; ++p) { 6363 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6364 } 6365 #endif 6366 /* C quad */ 6367 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6368 orntNew[0] = -2; 6369 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6370 orntNew[1] = ornt[1]; 6371 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6372 orntNew[2] = ornt[2]; 6373 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6374 orntNew[3] = 0; 6375 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6376 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6377 #if 1 6378 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6379 for (p = 0; p < 4; ++p) { 6380 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6381 } 6382 #endif 6383 /* D quad */ 6384 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6385 orntNew[0] = 0; 6386 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6387 orntNew[1] = -2; 6388 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6389 orntNew[2] = ornt[2]; 6390 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6391 orntNew[3] = ornt[3]; 6392 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6393 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6394 #if 1 6395 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6396 for (p = 0; p < 4; ++p) { 6397 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6398 } 6399 #endif 6400 } 6401 /* Split faces have 2 vertices and the same cells as the parent */ 6402 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6403 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6404 for (f = fStart; f < fEnd; ++f) { 6405 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6406 6407 for (r = 0; r < 2; ++r) { 6408 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6409 const PetscInt *cone, *support; 6410 PetscInt coneNew[2], coneSize, c, supportSize, s; 6411 6412 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6413 coneNew[0] = vStartNew + (cone[0] - vStart); 6414 coneNew[1] = vStartNew + (cone[1] - vStart); 6415 coneNew[(r+1)%2] = newv; 6416 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6417 #if 1 6418 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6419 for (p = 0; p < 2; ++p) { 6420 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6421 } 6422 #endif 6423 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6424 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6425 for (s = 0; s < supportSize; ++s) { 6426 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6427 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6428 for (c = 0; c < coneSize; ++c) { 6429 if (cone[c] == f) break; 6430 } 6431 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6432 } 6433 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6434 #if 1 6435 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6436 for (p = 0; p < supportSize; ++p) { 6437 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6438 } 6439 #endif 6440 } 6441 } 6442 /* Interior faces have 2 vertices and 2 cells */ 6443 for (c = cStart; c < cEnd; ++c) { 6444 const PetscInt *cone; 6445 PetscInt coneNew[2], supportNew[2]; 6446 6447 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6448 for (r = 0; r < 4; ++r) { 6449 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6450 6451 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6452 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6453 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6454 #if 1 6455 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6456 for (p = 0; p < 2; ++p) { 6457 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6458 } 6459 #endif 6460 supportNew[0] = (c - cStart)*4 + r; 6461 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6462 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6463 #if 1 6464 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6465 for (p = 0; p < 2; ++p) { 6466 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6467 } 6468 #endif 6469 } 6470 } 6471 /* Old vertices have identical supports */ 6472 for (v = vStart; v < vEnd; ++v) { 6473 const PetscInt newp = vStartNew + (v - vStart); 6474 const PetscInt *support, *cone; 6475 PetscInt size, s; 6476 6477 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6478 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6479 for (s = 0; s < size; ++s) { 6480 PetscInt r = 0; 6481 6482 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6483 if (cone[1] == v) r = 1; 6484 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6485 } 6486 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6487 #if 1 6488 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6489 for (p = 0; p < size; ++p) { 6490 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6491 } 6492 #endif 6493 } 6494 /* Face vertices have 2 + cells supports */ 6495 for (f = fStart; f < fEnd; ++f) { 6496 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6497 const PetscInt *cone, *support; 6498 PetscInt size, s; 6499 6500 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6501 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6502 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6503 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6504 for (s = 0; s < size; ++s) { 6505 PetscInt r = 0; 6506 6507 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6508 if (cone[1] == f) r = 1; 6509 else if (cone[2] == f) r = 2; 6510 else if (cone[3] == f) r = 3; 6511 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6512 } 6513 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6514 #if 1 6515 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6516 for (p = 0; p < 2+size; ++p) { 6517 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6518 } 6519 #endif 6520 } 6521 /* Cell vertices have 4 supports */ 6522 for (c = cStart; c < cEnd; ++c) { 6523 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6524 PetscInt supportNew[4]; 6525 6526 for (r = 0; r < 4; ++r) { 6527 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6528 } 6529 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6530 } 6531 break; 6532 case 3: 6533 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6534 cMax = PetscMin(cEnd, cMax); 6535 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6536 fMax = PetscMin(fEnd, fMax); 6537 /* Interior cells have 3 faces */ 6538 for (c = cStart; c < cMax; ++c) { 6539 const PetscInt newp = cStartNew + (c - cStart)*4; 6540 const PetscInt *cone, *ornt; 6541 PetscInt coneNew[3], orntNew[3]; 6542 6543 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6544 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6545 /* A triangle */ 6546 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6547 orntNew[0] = ornt[0]; 6548 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6549 orntNew[1] = -2; 6550 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6551 orntNew[2] = ornt[2]; 6552 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6553 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6554 #if 1 6555 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6556 for (p = 0; p < 3; ++p) { 6557 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6558 } 6559 #endif 6560 /* B triangle */ 6561 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6562 orntNew[0] = ornt[0]; 6563 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6564 orntNew[1] = ornt[1]; 6565 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6566 orntNew[2] = -2; 6567 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6568 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6569 #if 1 6570 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6571 for (p = 0; p < 3; ++p) { 6572 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6573 } 6574 #endif 6575 /* C triangle */ 6576 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6577 orntNew[0] = -2; 6578 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6579 orntNew[1] = ornt[1]; 6580 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6581 orntNew[2] = ornt[2]; 6582 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6583 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6584 #if 1 6585 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6586 for (p = 0; p < 3; ++p) { 6587 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6588 } 6589 #endif 6590 /* D triangle */ 6591 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6592 orntNew[0] = 0; 6593 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6594 orntNew[1] = 0; 6595 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6596 orntNew[2] = 0; 6597 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6598 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6599 #if 1 6600 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6601 for (p = 0; p < 3; ++p) { 6602 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6603 } 6604 #endif 6605 } 6606 /* 6607 2----3----3 6608 | | 6609 | B | 6610 | | 6611 0----4--- 1 6612 | | 6613 | A | 6614 | | 6615 0----2----1 6616 */ 6617 /* Hybrid cells have 4 faces */ 6618 for (c = cMax; c < cEnd; ++c) { 6619 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6620 const PetscInt *cone, *ornt; 6621 PetscInt coneNew[4], orntNew[4]; 6622 6623 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6624 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6625 /* A quad */ 6626 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6627 orntNew[0] = ornt[0]; 6628 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6629 orntNew[1] = ornt[1]; 6630 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6631 orntNew[2] = 0; 6632 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6633 orntNew[3] = 0; 6634 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6635 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6636 #if 1 6637 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6638 for (p = 0; p < 4; ++p) { 6639 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6640 } 6641 #endif 6642 /* B quad */ 6643 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6644 orntNew[0] = ornt[0]; 6645 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6646 orntNew[1] = ornt[1]; 6647 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6648 orntNew[2] = 0; 6649 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6650 orntNew[3] = 0; 6651 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6652 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6653 #if 1 6654 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6655 for (p = 0; p < 4; ++p) { 6656 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6657 } 6658 #endif 6659 } 6660 /* Interior split faces have 2 vertices and the same cells as the parent */ 6661 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6662 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6663 for (f = fStart; f < fMax; ++f) { 6664 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6665 6666 for (r = 0; r < 2; ++r) { 6667 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6668 const PetscInt *cone, *support; 6669 PetscInt coneNew[2], coneSize, c, supportSize, s; 6670 6671 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6672 coneNew[0] = vStartNew + (cone[0] - vStart); 6673 coneNew[1] = vStartNew + (cone[1] - vStart); 6674 coneNew[(r+1)%2] = newv; 6675 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6676 #if 1 6677 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6678 for (p = 0; p < 2; ++p) { 6679 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6680 } 6681 #endif 6682 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6683 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6684 for (s = 0; s < supportSize; ++s) { 6685 if (support[s] >= cMax) { 6686 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6687 } else { 6688 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6689 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6690 for (c = 0; c < coneSize; ++c) { 6691 if (cone[c] == f) break; 6692 } 6693 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6694 } 6695 } 6696 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6697 #if 1 6698 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6699 for (p = 0; p < supportSize; ++p) { 6700 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6701 } 6702 #endif 6703 } 6704 } 6705 /* Interior cell faces have 2 vertices and 2 cells */ 6706 for (c = cStart; c < cMax; ++c) { 6707 const PetscInt *cone; 6708 6709 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6710 for (r = 0; r < 3; ++r) { 6711 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6712 PetscInt coneNew[2]; 6713 PetscInt supportNew[2]; 6714 6715 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6716 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6717 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6718 #if 1 6719 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6720 for (p = 0; p < 2; ++p) { 6721 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6722 } 6723 #endif 6724 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6725 supportNew[1] = (c - cStart)*4 + 3; 6726 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6727 #if 1 6728 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6729 for (p = 0; p < 2; ++p) { 6730 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6731 } 6732 #endif 6733 } 6734 } 6735 /* Interior hybrid faces have 2 vertices and the same cells */ 6736 for (f = fMax; f < fEnd; ++f) { 6737 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6738 const PetscInt *cone; 6739 const PetscInt *support; 6740 PetscInt coneNew[2]; 6741 PetscInt supportNew[2]; 6742 PetscInt size, s, r; 6743 6744 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6745 coneNew[0] = vStartNew + (cone[0] - vStart); 6746 coneNew[1] = vStartNew + (cone[1] - vStart); 6747 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6748 #if 1 6749 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6750 for (p = 0; p < 2; ++p) { 6751 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6752 } 6753 #endif 6754 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6755 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6756 for (s = 0; s < size; ++s) { 6757 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6758 for (r = 0; r < 2; ++r) { 6759 if (cone[r+2] == f) break; 6760 } 6761 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6762 } 6763 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6764 #if 1 6765 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6766 for (p = 0; p < size; ++p) { 6767 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6768 } 6769 #endif 6770 } 6771 /* Cell hybrid faces have 2 vertices and 2 cells */ 6772 for (c = cMax; c < cEnd; ++c) { 6773 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6774 const PetscInt *cone; 6775 PetscInt coneNew[2]; 6776 PetscInt supportNew[2]; 6777 6778 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6779 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6780 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6781 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6782 #if 1 6783 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6784 for (p = 0; p < 2; ++p) { 6785 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6786 } 6787 #endif 6788 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6789 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6790 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6791 #if 1 6792 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6793 for (p = 0; p < 2; ++p) { 6794 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6795 } 6796 #endif 6797 } 6798 /* Old vertices have identical supports */ 6799 for (v = vStart; v < vEnd; ++v) { 6800 const PetscInt newp = vStartNew + (v - vStart); 6801 const PetscInt *support, *cone; 6802 PetscInt size, s; 6803 6804 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6805 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6806 for (s = 0; s < size; ++s) { 6807 if (support[s] >= fMax) { 6808 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6809 } else { 6810 PetscInt r = 0; 6811 6812 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6813 if (cone[1] == v) r = 1; 6814 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6815 } 6816 } 6817 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6818 #if 1 6819 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6820 for (p = 0; p < size; ++p) { 6821 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6822 } 6823 #endif 6824 } 6825 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6826 for (f = fStart; f < fMax; ++f) { 6827 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6828 const PetscInt *cone, *support; 6829 PetscInt size, newSize = 2, s; 6830 6831 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6832 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6833 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6834 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6835 for (s = 0; s < size; ++s) { 6836 PetscInt r = 0; 6837 6838 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6839 if (support[s] >= cMax) { 6840 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6841 6842 newSize += 1; 6843 } else { 6844 if (cone[1] == f) r = 1; 6845 else if (cone[2] == f) r = 2; 6846 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6847 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6848 6849 newSize += 2; 6850 } 6851 } 6852 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6853 #if 1 6854 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6855 for (p = 0; p < newSize; ++p) { 6856 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6857 } 6858 #endif 6859 } 6860 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6861 break; 6862 default: 6863 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6864 } 6865 PetscFunctionReturn(0); 6866 } 6867 6868 #undef __FUNCT__ 6869 #define __FUNCT__ "CellRefinerSetCoordinates" 6870 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6871 { 6872 PetscSection coordSection, coordSectionNew; 6873 Vec coordinates, coordinatesNew; 6874 PetscScalar *coords, *coordsNew; 6875 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6876 PetscErrorCode ierr; 6877 6878 PetscFunctionBegin; 6879 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6880 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6881 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6882 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6883 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6884 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6885 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6886 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6887 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6888 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6889 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6890 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6891 if (fMax < 0) fMax = fEnd; 6892 switch (refiner) { 6893 case 1: 6894 case 2: 6895 case 3: 6896 /* Simplicial and Hex 2D */ 6897 /* All vertices have the dim coordinates */ 6898 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6899 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6900 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6901 } 6902 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6903 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6904 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6905 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6906 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6907 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6908 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6909 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6910 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6911 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6912 /* Old vertices have the same coordinates */ 6913 for (v = vStart; v < vEnd; ++v) { 6914 const PetscInt newv = vStartNew + (v - vStart); 6915 PetscInt off, offnew, d; 6916 6917 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6918 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6919 for (d = 0; d < dim; ++d) { 6920 coordsNew[offnew+d] = coords[off+d]; 6921 } 6922 } 6923 /* Face vertices have the average of endpoint coordinates */ 6924 for (f = fStart; f < fMax; ++f) { 6925 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6926 const PetscInt *cone; 6927 PetscInt coneSize, offA, offB, offnew, d; 6928 6929 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6930 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6931 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6932 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6933 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6934 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6935 for (d = 0; d < dim; ++d) { 6936 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6937 } 6938 } 6939 /* Just Hex 2D */ 6940 if (refiner == 2) { 6941 /* Cell vertices have the average of corner coordinates */ 6942 for (c = cStart; c < cEnd; ++c) { 6943 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6944 PetscInt *cone = NULL; 6945 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6946 6947 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6948 for (p = 0; p < closureSize*2; p += 2) { 6949 const PetscInt point = cone[p]; 6950 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6951 } 6952 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6953 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6954 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6955 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6956 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6957 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6958 for (d = 0; d < dim; ++d) { 6959 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6960 } 6961 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6962 } 6963 } 6964 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6965 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6966 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6967 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6968 break; 6969 default: 6970 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6971 } 6972 PetscFunctionReturn(0); 6973 } 6974 6975 #undef __FUNCT__ 6976 #define __FUNCT__ "DMPlexCreateProcessSF" 6977 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6978 { 6979 PetscInt numRoots, numLeaves, l; 6980 const PetscInt *localPoints; 6981 const PetscSFNode *remotePoints; 6982 PetscInt *localPointsNew; 6983 PetscSFNode *remotePointsNew; 6984 PetscInt *ranks, *ranksNew; 6985 PetscErrorCode ierr; 6986 6987 PetscFunctionBegin; 6988 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6989 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6990 for (l = 0; l < numLeaves; ++l) { 6991 ranks[l] = remotePoints[l].rank; 6992 } 6993 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6994 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6995 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6996 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6997 for (l = 0; l < numLeaves; ++l) { 6998 ranksNew[l] = ranks[l]; 6999 localPointsNew[l] = l; 7000 remotePointsNew[l].index = 0; 7001 remotePointsNew[l].rank = ranksNew[l]; 7002 } 7003 ierr = PetscFree(ranks);CHKERRQ(ierr); 7004 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 7005 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 7006 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 7007 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7008 PetscFunctionReturn(0); 7009 } 7010 7011 #undef __FUNCT__ 7012 #define __FUNCT__ "CellRefinerCreateSF" 7013 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7014 { 7015 PetscSF sf, sfNew, sfProcess; 7016 IS processRanks; 7017 MPI_Datatype depthType; 7018 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7019 const PetscInt *localPoints, *neighbors; 7020 const PetscSFNode *remotePoints; 7021 PetscInt *localPointsNew; 7022 PetscSFNode *remotePointsNew; 7023 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7024 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7025 PetscErrorCode ierr; 7026 7027 PetscFunctionBegin; 7028 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7029 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7030 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7031 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7032 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7033 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7034 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7035 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7036 switch (refiner) { 7037 case 3: 7038 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7039 cMax = PetscMin(cEnd, cMax); 7040 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7041 fMax = PetscMin(fEnd, fMax); 7042 } 7043 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7044 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7045 /* Caculate size of new SF */ 7046 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7047 if (numRoots < 0) PetscFunctionReturn(0); 7048 for (l = 0; l < numLeaves; ++l) { 7049 const PetscInt p = localPoints[l]; 7050 7051 switch (refiner) { 7052 case 1: 7053 /* Simplicial 2D */ 7054 if ((p >= vStart) && (p < vEnd)) { 7055 /* Old vertices stay the same */ 7056 ++numLeavesNew; 7057 } else if ((p >= fStart) && (p < fEnd)) { 7058 /* Old faces add new faces and vertex */ 7059 numLeavesNew += 1 + 2; 7060 } else if ((p >= cStart) && (p < cEnd)) { 7061 /* Old cells add new cells and interior faces */ 7062 numLeavesNew += 4 + 3; 7063 } 7064 break; 7065 case 2: 7066 /* Hex 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 + 4; 7076 } 7077 break; 7078 default: 7079 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7080 } 7081 } 7082 /* Communicate depthSizes for each remote rank */ 7083 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7084 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7085 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7086 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); 7087 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7088 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7089 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7090 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7091 for (n = 0; n < numNeighbors; ++n) { 7092 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7093 } 7094 depthSizeOld[depth] = cMax; 7095 depthSizeOld[0] = vMax; 7096 depthSizeOld[depth-1] = fMax; 7097 depthSizeOld[1] = eMax; 7098 7099 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7100 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7101 7102 depthSizeOld[depth] = cEnd - cStart; 7103 depthSizeOld[0] = vEnd - vStart; 7104 depthSizeOld[depth-1] = fEnd - fStart; 7105 depthSizeOld[1] = eEnd - eStart; 7106 7107 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7108 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7109 for (n = 0; n < numNeighbors; ++n) { 7110 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7111 } 7112 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7113 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7114 /* Calculate new point SF */ 7115 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7116 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7117 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7118 for (l = 0, m = 0; l < numLeaves; ++l) { 7119 PetscInt p = localPoints[l]; 7120 PetscInt rp = remotePoints[l].index, n; 7121 PetscMPIInt rrank = remotePoints[l].rank; 7122 7123 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7124 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7125 switch (refiner) { 7126 case 1: 7127 /* Simplicial 2D */ 7128 if ((p >= vStart) && (p < vEnd)) { 7129 /* Old vertices stay the same */ 7130 localPointsNew[m] = vStartNew + (p - vStart); 7131 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7132 remotePointsNew[m].rank = rrank; 7133 ++m; 7134 } else if ((p >= fStart) && (p < fEnd)) { 7135 /* Old faces add new faces and vertex */ 7136 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7137 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7138 remotePointsNew[m].rank = rrank; 7139 ++m; 7140 for (r = 0; r < 2; ++r, ++m) { 7141 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7142 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7143 remotePointsNew[m].rank = rrank; 7144 } 7145 } else if ((p >= cStart) && (p < cEnd)) { 7146 /* Old cells add new cells and interior faces */ 7147 for (r = 0; r < 4; ++r, ++m) { 7148 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7149 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7150 remotePointsNew[m].rank = rrank; 7151 } 7152 for (r = 0; r < 3; ++r, ++m) { 7153 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7154 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7155 remotePointsNew[m].rank = rrank; 7156 } 7157 } 7158 break; 7159 case 2: 7160 /* Hex 2D */ 7161 if ((p >= vStart) && (p < vEnd)) { 7162 /* Old vertices stay the same */ 7163 localPointsNew[m] = vStartNew + (p - vStart); 7164 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7165 remotePointsNew[m].rank = rrank; 7166 ++m; 7167 } else if ((p >= fStart) && (p < fEnd)) { 7168 /* Old faces add new faces and vertex */ 7169 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7170 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7171 remotePointsNew[m].rank = rrank; 7172 ++m; 7173 for (r = 0; r < 2; ++r, ++m) { 7174 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7175 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7176 remotePointsNew[m].rank = rrank; 7177 } 7178 } else if ((p >= cStart) && (p < cEnd)) { 7179 /* Old cells add new cells and interior faces */ 7180 for (r = 0; r < 4; ++r, ++m) { 7181 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7182 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7183 remotePointsNew[m].rank = rrank; 7184 } 7185 for (r = 0; r < 4; ++r, ++m) { 7186 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7187 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7188 remotePointsNew[m].rank = rrank; 7189 } 7190 } 7191 break; 7192 case 3: 7193 /* Hybrid simplicial 2D */ 7194 if ((p >= vStart) && (p < vEnd)) { 7195 /* Old vertices stay the same */ 7196 localPointsNew[m] = vStartNew + (p - vStart); 7197 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7198 remotePointsNew[m].rank = rrank; 7199 ++m; 7200 } else if ((p >= fStart) && (p < fMax)) { 7201 /* Old interior faces add new faces and vertex */ 7202 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7203 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7204 remotePointsNew[m].rank = rrank; 7205 ++m; 7206 for (r = 0; r < 2; ++r, ++m) { 7207 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7208 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7209 remotePointsNew[m].rank = rrank; 7210 } 7211 } else if ((p >= fMax) && (p < fEnd)) { 7212 /* Old hybrid faces stay the same */ 7213 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7214 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7215 remotePointsNew[m].rank = rrank; 7216 ++m; 7217 } else if ((p >= cStart) && (p < cMax)) { 7218 /* Old interior cells add new cells and interior faces */ 7219 for (r = 0; r < 4; ++r, ++m) { 7220 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7221 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7222 remotePointsNew[m].rank = rrank; 7223 } 7224 for (r = 0; r < 3; ++r, ++m) { 7225 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7226 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7227 remotePointsNew[m].rank = rrank; 7228 } 7229 } else if ((p >= cStart) && (p < cMax)) { 7230 /* Old hybrid cells add new cells and hybrid face */ 7231 for (r = 0; r < 2; ++r, ++m) { 7232 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7233 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7234 remotePointsNew[m].rank = rrank; 7235 } 7236 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7237 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]); 7238 remotePointsNew[m].rank = rrank; 7239 ++m; 7240 } 7241 break; 7242 default: 7243 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7244 } 7245 } 7246 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7247 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7248 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7249 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7250 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7251 PetscFunctionReturn(0); 7252 } 7253 7254 #undef __FUNCT__ 7255 #define __FUNCT__ "CellRefinerCreateLabels" 7256 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7257 { 7258 PetscInt numLabels, l; 7259 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7260 PetscErrorCode ierr; 7261 7262 PetscFunctionBegin; 7263 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7264 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7265 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7266 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7267 7268 cStartNew = 0; 7269 vStartNew = depthSize[2]; 7270 fStartNew = depthSize[2] + depthSize[0]; 7271 7272 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7273 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7274 switch (refiner) { 7275 case 3: 7276 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7277 cMax = PetscMin(cEnd, cMax); 7278 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7279 fMax = PetscMin(fEnd, fMax); 7280 } 7281 for (l = 0; l < numLabels; ++l) { 7282 DMLabel label, labelNew; 7283 const char *lname; 7284 PetscBool isDepth; 7285 IS valueIS; 7286 const PetscInt *values; 7287 PetscInt numValues, val; 7288 7289 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7290 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7291 if (isDepth) continue; 7292 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7293 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7294 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7295 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7296 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7297 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7298 for (val = 0; val < numValues; ++val) { 7299 IS pointIS; 7300 const PetscInt *points; 7301 PetscInt numPoints, n; 7302 7303 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7304 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7305 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7306 for (n = 0; n < numPoints; ++n) { 7307 const PetscInt p = points[n]; 7308 switch (refiner) { 7309 case 1: 7310 /* Simplicial 2D */ 7311 if ((p >= vStart) && (p < vEnd)) { 7312 /* Old vertices stay the same */ 7313 newp = vStartNew + (p - vStart); 7314 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7315 } else if ((p >= fStart) && (p < fEnd)) { 7316 /* Old faces add new faces and vertex */ 7317 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7318 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7319 for (r = 0; r < 2; ++r) { 7320 newp = fStartNew + (p - fStart)*2 + r; 7321 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7322 } 7323 } else if ((p >= cStart) && (p < cEnd)) { 7324 /* Old cells add new cells and interior faces */ 7325 for (r = 0; r < 4; ++r) { 7326 newp = cStartNew + (p - cStart)*4 + r; 7327 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7328 } 7329 for (r = 0; r < 3; ++r) { 7330 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7331 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7332 } 7333 } 7334 break; 7335 case 2: 7336 /* Hex 2D */ 7337 if ((p >= vStart) && (p < vEnd)) { 7338 /* Old vertices stay the same */ 7339 newp = vStartNew + (p - vStart); 7340 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7341 } else if ((p >= fStart) && (p < fEnd)) { 7342 /* Old faces add new faces and vertex */ 7343 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7344 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7345 for (r = 0; r < 2; ++r) { 7346 newp = fStartNew + (p - fStart)*2 + r; 7347 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7348 } 7349 } else if ((p >= cStart) && (p < cEnd)) { 7350 /* Old cells add new cells and interior faces and vertex */ 7351 for (r = 0; r < 4; ++r) { 7352 newp = cStartNew + (p - cStart)*4 + r; 7353 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7354 } 7355 for (r = 0; r < 4; ++r) { 7356 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7357 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7358 } 7359 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7360 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7361 } 7362 break; 7363 case 3: 7364 /* Hybrid simplicial 2D */ 7365 if ((p >= vStart) && (p < vEnd)) { 7366 /* Old vertices stay the same */ 7367 newp = vStartNew + (p - vStart); 7368 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7369 } else if ((p >= fStart) && (p < fMax)) { 7370 /* Old interior faces add new faces and vertex */ 7371 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7372 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7373 for (r = 0; r < 2; ++r) { 7374 newp = fStartNew + (p - fStart)*2 + r; 7375 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7376 } 7377 } else if ((p >= fMax) && (p < fEnd)) { 7378 /* Old hybrid faces stay the same */ 7379 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7380 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7381 } else if ((p >= cStart) && (p < cMax)) { 7382 /* Old interior cells add new cells and interior faces */ 7383 for (r = 0; r < 4; ++r) { 7384 newp = cStartNew + (p - cStart)*4 + r; 7385 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7386 } 7387 for (r = 0; r < 3; ++r) { 7388 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7389 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7390 } 7391 } else if ((p >= cMax) && (p < cEnd)) { 7392 /* Old hybrid cells add new cells and hybrid face */ 7393 for (r = 0; r < 2; ++r) { 7394 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7395 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7396 } 7397 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7398 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7399 } 7400 break; 7401 default: 7402 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7403 } 7404 } 7405 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7406 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7407 } 7408 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7409 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7410 if (0) { 7411 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7412 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7413 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7414 } 7415 } 7416 PetscFunctionReturn(0); 7417 } 7418 7419 #undef __FUNCT__ 7420 #define __FUNCT__ "DMPlexRefine_Uniform" 7421 /* This will only work for interpolated meshes */ 7422 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7423 { 7424 DM rdm; 7425 PetscInt *depthSize; 7426 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7427 PetscErrorCode ierr; 7428 7429 PetscFunctionBegin; 7430 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7431 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7432 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7433 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7434 /* Calculate number of new points of each depth */ 7435 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7436 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7437 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7438 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7439 /* Step 1: Set chart */ 7440 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7441 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7442 /* Step 2: Set cone/support sizes */ 7443 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7444 /* Step 3: Setup refined DM */ 7445 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7446 /* Step 4: Set cones and supports */ 7447 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7448 /* Step 5: Stratify */ 7449 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7450 /* Step 6: Set coordinates for vertices */ 7451 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7452 /* Step 7: Create pointSF */ 7453 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7454 /* Step 8: Create labels */ 7455 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7456 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7457 7458 *dmRefined = rdm; 7459 PetscFunctionReturn(0); 7460 } 7461 7462 #undef __FUNCT__ 7463 #define __FUNCT__ "DMPlexSetRefinementUniform" 7464 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7465 { 7466 DM_Plex *mesh = (DM_Plex*) dm->data; 7467 7468 PetscFunctionBegin; 7469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7470 mesh->refinementUniform = refinementUniform; 7471 PetscFunctionReturn(0); 7472 } 7473 7474 #undef __FUNCT__ 7475 #define __FUNCT__ "DMPlexGetRefinementUniform" 7476 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7477 { 7478 DM_Plex *mesh = (DM_Plex*) dm->data; 7479 7480 PetscFunctionBegin; 7481 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7482 PetscValidPointer(refinementUniform, 2); 7483 *refinementUniform = mesh->refinementUniform; 7484 PetscFunctionReturn(0); 7485 } 7486 7487 #undef __FUNCT__ 7488 #define __FUNCT__ "DMPlexSetRefinementLimit" 7489 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7490 { 7491 DM_Plex *mesh = (DM_Plex*) dm->data; 7492 7493 PetscFunctionBegin; 7494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7495 mesh->refinementLimit = refinementLimit; 7496 PetscFunctionReturn(0); 7497 } 7498 7499 #undef __FUNCT__ 7500 #define __FUNCT__ "DMPlexGetRefinementLimit" 7501 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7502 { 7503 DM_Plex *mesh = (DM_Plex*) dm->data; 7504 7505 PetscFunctionBegin; 7506 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7507 PetscValidPointer(refinementLimit, 2); 7508 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7509 *refinementLimit = mesh->refinementLimit; 7510 PetscFunctionReturn(0); 7511 } 7512 7513 #undef __FUNCT__ 7514 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7515 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7516 { 7517 PetscInt dim, cStart, coneSize, cMax; 7518 PetscErrorCode ierr; 7519 7520 PetscFunctionBegin; 7521 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7522 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7523 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7524 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7525 switch (dim) { 7526 case 2: 7527 switch (coneSize) { 7528 case 3: 7529 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7530 else *cellRefiner = 1; /* Triangular */ 7531 break; 7532 case 4: 7533 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7534 else *cellRefiner = 2; /* Quadrilateral */ 7535 break; 7536 default: 7537 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7538 } 7539 break; 7540 default: 7541 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7542 } 7543 PetscFunctionReturn(0); 7544 } 7545 7546 #undef __FUNCT__ 7547 #define __FUNCT__ "DMRefine_Plex" 7548 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7549 { 7550 PetscReal refinementLimit; 7551 PetscInt dim, cStart, cEnd; 7552 char genname[1024], *name = NULL; 7553 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7554 PetscErrorCode ierr; 7555 7556 PetscFunctionBegin; 7557 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7558 if (isUniform) { 7559 CellRefiner cellRefiner; 7560 7561 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7562 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7563 PetscFunctionReturn(0); 7564 } 7565 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7566 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7567 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7568 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7569 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7570 if (flg) name = genname; 7571 if (name) { 7572 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7573 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7574 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7575 } 7576 switch (dim) { 7577 case 2: 7578 if (!name || isTriangle) { 7579 #if defined(PETSC_HAVE_TRIANGLE) 7580 double *maxVolumes; 7581 PetscInt c; 7582 7583 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7584 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7585 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7586 #else 7587 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7588 #endif 7589 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7590 break; 7591 case 3: 7592 if (!name || isCTetgen) { 7593 #if defined(PETSC_HAVE_CTETGEN) 7594 PetscReal *maxVolumes; 7595 PetscInt c; 7596 7597 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7598 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7599 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7600 #else 7601 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7602 #endif 7603 } else if (isTetgen) { 7604 #if defined(PETSC_HAVE_TETGEN) 7605 double *maxVolumes; 7606 PetscInt c; 7607 7608 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7609 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7610 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7611 #else 7612 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7613 #endif 7614 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7615 break; 7616 default: 7617 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7618 } 7619 PetscFunctionReturn(0); 7620 } 7621 7622 #undef __FUNCT__ 7623 #define __FUNCT__ "DMPlexGetDepth" 7624 /*@ 7625 DMPlexGetDepth - get the number of strata 7626 7627 Not Collective 7628 7629 Input Parameters: 7630 . dm - The DMPlex object 7631 7632 Output Parameters: 7633 . depth - number of strata 7634 7635 Level: developer 7636 7637 Notes: 7638 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7639 7640 .keywords: mesh, points 7641 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7642 @*/ 7643 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7644 { 7645 PetscInt d; 7646 PetscErrorCode ierr; 7647 7648 PetscFunctionBegin; 7649 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7650 PetscValidPointer(depth, 2); 7651 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7652 *depth = d-1; 7653 PetscFunctionReturn(0); 7654 } 7655 7656 #undef __FUNCT__ 7657 #define __FUNCT__ "DMPlexGetDepthStratum" 7658 /*@ 7659 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7660 7661 Not Collective 7662 7663 Input Parameters: 7664 + dm - The DMPlex object 7665 - stratumValue - The requested depth 7666 7667 Output Parameters: 7668 + start - The first point at this depth 7669 - end - One beyond the last point at this depth 7670 7671 Level: developer 7672 7673 .keywords: mesh, points 7674 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7675 @*/ 7676 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7677 { 7678 DM_Plex *mesh = (DM_Plex*) dm->data; 7679 DMLabel next = mesh->labels; 7680 PetscBool flg = PETSC_FALSE; 7681 PetscInt depth; 7682 PetscErrorCode ierr; 7683 7684 PetscFunctionBegin; 7685 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7686 if (stratumValue < 0) { 7687 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7688 PetscFunctionReturn(0); 7689 } else { 7690 PetscInt pStart, pEnd; 7691 7692 if (start) *start = 0; 7693 if (end) *end = 0; 7694 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7695 if (pStart == pEnd) PetscFunctionReturn(0); 7696 } 7697 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7698 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7699 /* We should have a generic GetLabel() and a Label class */ 7700 while (next) { 7701 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7702 if (flg) break; 7703 next = next->next; 7704 } 7705 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7706 depth = stratumValue; 7707 if ((depth < 0) || (depth >= next->numStrata)) { 7708 if (start) *start = 0; 7709 if (end) *end = 0; 7710 } else { 7711 if (start) *start = next->points[next->stratumOffsets[depth]]; 7712 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7713 } 7714 PetscFunctionReturn(0); 7715 } 7716 7717 #undef __FUNCT__ 7718 #define __FUNCT__ "DMPlexGetHeightStratum" 7719 /*@ 7720 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7721 7722 Not Collective 7723 7724 Input Parameters: 7725 + dm - The DMPlex object 7726 - stratumValue - The requested height 7727 7728 Output Parameters: 7729 + start - The first point at this height 7730 - end - One beyond the last point at this height 7731 7732 Level: developer 7733 7734 .keywords: mesh, points 7735 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7736 @*/ 7737 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7738 { 7739 DM_Plex *mesh = (DM_Plex*) dm->data; 7740 DMLabel next = mesh->labels; 7741 PetscBool flg = PETSC_FALSE; 7742 PetscInt depth; 7743 PetscErrorCode ierr; 7744 7745 PetscFunctionBegin; 7746 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7747 if (stratumValue < 0) { 7748 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7749 } else { 7750 PetscInt pStart, pEnd; 7751 7752 if (start) *start = 0; 7753 if (end) *end = 0; 7754 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7755 if (pStart == pEnd) PetscFunctionReturn(0); 7756 } 7757 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7758 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7759 /* We should have a generic GetLabel() and a Label class */ 7760 while (next) { 7761 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7762 if (flg) break; 7763 next = next->next; 7764 } 7765 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7766 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7767 if ((depth < 0) || (depth >= next->numStrata)) { 7768 if (start) *start = 0; 7769 if (end) *end = 0; 7770 } else { 7771 if (start) *start = next->points[next->stratumOffsets[depth]]; 7772 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7773 } 7774 PetscFunctionReturn(0); 7775 } 7776 7777 #undef __FUNCT__ 7778 #define __FUNCT__ "DMPlexCreateSectionInitial" 7779 /* Set the number of dof on each point and separate by fields */ 7780 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7781 { 7782 PetscInt *numDofTot; 7783 PetscInt pStart = 0, pEnd = 0; 7784 PetscInt p, d, f; 7785 PetscErrorCode ierr; 7786 7787 PetscFunctionBegin; 7788 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7789 for (d = 0; d <= dim; ++d) { 7790 numDofTot[d] = 0; 7791 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7792 } 7793 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7794 if (numFields > 0) { 7795 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7796 if (numComp) { 7797 for (f = 0; f < numFields; ++f) { 7798 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7799 } 7800 } 7801 } 7802 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7803 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7804 for (d = 0; d <= dim; ++d) { 7805 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7806 for (p = pStart; p < pEnd; ++p) { 7807 for (f = 0; f < numFields; ++f) { 7808 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7809 } 7810 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7811 } 7812 } 7813 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7814 PetscFunctionReturn(0); 7815 } 7816 7817 #undef __FUNCT__ 7818 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7819 /* Set the number of dof on each point and separate by fields 7820 If constDof is PETSC_DETERMINE, constrain every dof on the point 7821 */ 7822 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7823 { 7824 PetscInt numFields; 7825 PetscInt bc; 7826 PetscErrorCode ierr; 7827 7828 PetscFunctionBegin; 7829 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7830 for (bc = 0; bc < numBC; ++bc) { 7831 PetscInt field = 0; 7832 const PetscInt *idx; 7833 PetscInt n, i; 7834 7835 if (numFields) field = bcField[bc]; 7836 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7837 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7838 for (i = 0; i < n; ++i) { 7839 const PetscInt p = idx[i]; 7840 PetscInt numConst = constDof; 7841 7842 /* Constrain every dof on the point */ 7843 if (numConst < 0) { 7844 if (numFields) { 7845 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7846 } else { 7847 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7848 } 7849 } 7850 if (numFields) { 7851 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7852 } 7853 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7854 } 7855 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7856 } 7857 PetscFunctionReturn(0); 7858 } 7859 7860 #undef __FUNCT__ 7861 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7862 /* Set the constrained indices on each point and separate by fields */ 7863 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7864 { 7865 PetscInt *maxConstraints; 7866 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7867 PetscErrorCode ierr; 7868 7869 PetscFunctionBegin; 7870 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7871 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7872 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7873 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7874 for (p = pStart; p < pEnd; ++p) { 7875 PetscInt cdof; 7876 7877 if (numFields) { 7878 for (f = 0; f < numFields; ++f) { 7879 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7880 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7881 } 7882 } else { 7883 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7884 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7885 } 7886 } 7887 for (f = 0; f < numFields; ++f) { 7888 maxConstraints[numFields] += maxConstraints[f]; 7889 } 7890 if (maxConstraints[numFields]) { 7891 PetscInt *indices; 7892 7893 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7894 for (p = pStart; p < pEnd; ++p) { 7895 PetscInt cdof, d; 7896 7897 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7898 if (cdof) { 7899 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7900 if (numFields) { 7901 PetscInt numConst = 0, foff = 0; 7902 7903 for (f = 0; f < numFields; ++f) { 7904 PetscInt cfdof, fdof; 7905 7906 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7907 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7908 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7909 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7910 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7911 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7912 numConst += cfdof; 7913 foff += fdof; 7914 } 7915 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7916 } else { 7917 for (d = 0; d < cdof; ++d) indices[d] = d; 7918 } 7919 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7920 } 7921 } 7922 ierr = PetscFree(indices);CHKERRQ(ierr); 7923 } 7924 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7925 PetscFunctionReturn(0); 7926 } 7927 7928 #undef __FUNCT__ 7929 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7930 /* Set the constrained field indices on each point */ 7931 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7932 { 7933 const PetscInt *points, *indices; 7934 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7935 PetscErrorCode ierr; 7936 7937 PetscFunctionBegin; 7938 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7939 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7940 7941 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7942 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7943 if (!constraintIndices) { 7944 PetscInt *idx, i; 7945 7946 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7947 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7948 for (i = 0; i < maxDof; ++i) idx[i] = i; 7949 for (p = 0; p < numPoints; ++p) { 7950 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7951 } 7952 ierr = PetscFree(idx);CHKERRQ(ierr); 7953 } else { 7954 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7955 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7956 for (p = 0; p < numPoints; ++p) { 7957 PetscInt fcdof; 7958 7959 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7960 if (fcdof != numConstraints) SETERRQ4(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 7961 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7962 } 7963 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7964 } 7965 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7966 PetscFunctionReturn(0); 7967 } 7968 7969 #undef __FUNCT__ 7970 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7971 /* Set the constrained indices on each point and separate by fields */ 7972 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7973 { 7974 PetscInt *indices; 7975 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7976 PetscErrorCode ierr; 7977 7978 PetscFunctionBegin; 7979 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7980 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7981 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7982 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7983 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7984 for (p = pStart; p < pEnd; ++p) { 7985 PetscInt cdof, d; 7986 7987 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7988 if (cdof) { 7989 PetscInt numConst = 0, foff = 0; 7990 7991 for (f = 0; f < numFields; ++f) { 7992 const PetscInt *fcind; 7993 PetscInt fdof, fcdof; 7994 7995 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7996 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7997 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7998 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7999 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 8000 foff += fdof; 8001 numConst += fcdof; 8002 } 8003 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8004 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8005 } 8006 } 8007 ierr = PetscFree(indices);CHKERRQ(ierr); 8008 PetscFunctionReturn(0); 8009 } 8010 8011 #undef __FUNCT__ 8012 #define __FUNCT__ "DMPlexCreateSection" 8013 /*@C 8014 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8015 8016 Not Collective 8017 8018 Input Parameters: 8019 + dm - The DMPlex object 8020 . dim - The spatial dimension of the problem 8021 . numFields - The number of fields in the problem 8022 . numComp - An array of size numFields that holds the number of components for each field 8023 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8024 . numBC - The number of boundary conditions 8025 . bcField - An array of size numBC giving the field number for each boundry condition 8026 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8027 8028 Output Parameter: 8029 . section - The PetscSection object 8030 8031 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 8032 nubmer of dof for field 0 on each edge. 8033 8034 Level: developer 8035 8036 .keywords: mesh, elements 8037 .seealso: DMPlexCreate(), PetscSectionCreate() 8038 @*/ 8039 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8040 { 8041 PetscErrorCode ierr; 8042 8043 PetscFunctionBegin; 8044 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8045 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8046 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8047 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8048 { 8049 PetscBool view = PETSC_FALSE; 8050 8051 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8052 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8053 } 8054 PetscFunctionReturn(0); 8055 } 8056 8057 #undef __FUNCT__ 8058 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8059 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8060 { 8061 PetscSection section; 8062 PetscErrorCode ierr; 8063 8064 PetscFunctionBegin; 8065 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8066 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8067 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8068 PetscFunctionReturn(0); 8069 } 8070 8071 #undef __FUNCT__ 8072 #define __FUNCT__ "DMPlexGetCoordinateSection" 8073 /*@ 8074 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8075 8076 Not Collective 8077 8078 Input Parameter: 8079 . dm - The DMPlex object 8080 8081 Output Parameter: 8082 . section - The PetscSection object 8083 8084 Level: intermediate 8085 8086 .keywords: mesh, coordinates 8087 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8088 @*/ 8089 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8090 { 8091 DM cdm; 8092 PetscErrorCode ierr; 8093 8094 PetscFunctionBegin; 8095 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8096 PetscValidPointer(section, 2); 8097 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8098 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8099 PetscFunctionReturn(0); 8100 } 8101 8102 #undef __FUNCT__ 8103 #define __FUNCT__ "DMPlexSetCoordinateSection" 8104 /*@ 8105 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8106 8107 Not Collective 8108 8109 Input Parameters: 8110 + dm - The DMPlex object 8111 - section - The PetscSection object 8112 8113 Level: intermediate 8114 8115 .keywords: mesh, coordinates 8116 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8117 @*/ 8118 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8119 { 8120 DM cdm; 8121 PetscErrorCode ierr; 8122 8123 PetscFunctionBegin; 8124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8125 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8126 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8127 PetscFunctionReturn(0); 8128 } 8129 8130 #undef __FUNCT__ 8131 #define __FUNCT__ "DMPlexGetConeSection" 8132 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8133 { 8134 DM_Plex *mesh = (DM_Plex*) dm->data; 8135 8136 PetscFunctionBegin; 8137 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8138 if (section) *section = mesh->coneSection; 8139 PetscFunctionReturn(0); 8140 } 8141 8142 #undef __FUNCT__ 8143 #define __FUNCT__ "DMPlexGetCones" 8144 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8145 { 8146 DM_Plex *mesh = (DM_Plex*) dm->data; 8147 8148 PetscFunctionBegin; 8149 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8150 if (cones) *cones = mesh->cones; 8151 PetscFunctionReturn(0); 8152 } 8153 8154 #undef __FUNCT__ 8155 #define __FUNCT__ "DMPlexGetConeOrientations" 8156 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8157 { 8158 DM_Plex *mesh = (DM_Plex*) dm->data; 8159 8160 PetscFunctionBegin; 8161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8162 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8163 PetscFunctionReturn(0); 8164 } 8165 8166 #undef __FUNCT__ 8167 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8168 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8169 { 8170 const PetscInt embedDim = 2; 8171 PetscReal x = PetscRealPart(point[0]); 8172 PetscReal y = PetscRealPart(point[1]); 8173 PetscReal v0[2], J[4], invJ[4], detJ; 8174 PetscReal xi, eta; 8175 PetscErrorCode ierr; 8176 8177 PetscFunctionBegin; 8178 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8179 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8180 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8181 8182 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8183 else *cell = -1; 8184 PetscFunctionReturn(0); 8185 } 8186 8187 #undef __FUNCT__ 8188 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8189 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8190 { 8191 PetscSection coordSection; 8192 Vec coordsLocal; 8193 const PetscScalar *coords; 8194 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8195 PetscReal x = PetscRealPart(point[0]); 8196 PetscReal y = PetscRealPart(point[1]); 8197 PetscInt crossings = 0, f; 8198 PetscErrorCode ierr; 8199 8200 PetscFunctionBegin; 8201 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8202 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8203 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8204 for (f = 0; f < 4; ++f) { 8205 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8206 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8207 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8208 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8209 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8210 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8211 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8212 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8213 if ((cond1 || cond2) && above) ++crossings; 8214 } 8215 if (crossings % 2) *cell = c; 8216 else *cell = -1; 8217 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8218 PetscFunctionReturn(0); 8219 } 8220 8221 #undef __FUNCT__ 8222 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8223 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8224 { 8225 const PetscInt embedDim = 3; 8226 PetscReal v0[3], J[9], invJ[9], detJ; 8227 PetscReal x = PetscRealPart(point[0]); 8228 PetscReal y = PetscRealPart(point[1]); 8229 PetscReal z = PetscRealPart(point[2]); 8230 PetscReal xi, eta, zeta; 8231 PetscErrorCode ierr; 8232 8233 PetscFunctionBegin; 8234 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8235 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8236 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8237 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8238 8239 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8240 else *cell = -1; 8241 PetscFunctionReturn(0); 8242 } 8243 8244 #undef __FUNCT__ 8245 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8246 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8247 { 8248 PetscSection coordSection; 8249 Vec coordsLocal; 8250 const PetscScalar *coords; 8251 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8252 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8253 PetscBool found = PETSC_TRUE; 8254 PetscInt f; 8255 PetscErrorCode ierr; 8256 8257 PetscFunctionBegin; 8258 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8259 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8260 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8261 for (f = 0; f < 6; ++f) { 8262 /* Check the point is under plane */ 8263 /* Get face normal */ 8264 PetscReal v_i[3]; 8265 PetscReal v_j[3]; 8266 PetscReal normal[3]; 8267 PetscReal pp[3]; 8268 PetscReal dot; 8269 8270 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8271 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8272 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8273 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8274 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8275 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8276 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8277 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8278 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8279 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8280 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8281 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8282 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8283 8284 /* Check that projected point is in face (2D location problem) */ 8285 if (dot < 0.0) { 8286 found = PETSC_FALSE; 8287 break; 8288 } 8289 } 8290 if (found) *cell = c; 8291 else *cell = -1; 8292 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8293 PetscFunctionReturn(0); 8294 } 8295 8296 #undef __FUNCT__ 8297 #define __FUNCT__ "DMLocatePoints_Plex" 8298 /* 8299 Need to implement using the guess 8300 */ 8301 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8302 { 8303 PetscInt cell = -1 /*, guess = -1*/; 8304 PetscInt bs, numPoints, p; 8305 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8306 PetscInt *cells; 8307 PetscScalar *a; 8308 PetscErrorCode ierr; 8309 8310 PetscFunctionBegin; 8311 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8312 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8313 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 8314 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8315 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8316 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8317 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8318 if (bs != dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 8319 numPoints /= bs; 8320 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8321 for (p = 0; p < numPoints; ++p) { 8322 const PetscScalar *point = &a[p*bs]; 8323 8324 switch (dim) { 8325 case 2: 8326 for (c = cStart; c < cEnd; ++c) { 8327 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8328 switch (coneSize) { 8329 case 3: 8330 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8331 break; 8332 case 4: 8333 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8334 break; 8335 default: 8336 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8337 } 8338 if (cell >= 0) break; 8339 } 8340 break; 8341 case 3: 8342 for (c = cStart; c < cEnd; ++c) { 8343 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8344 switch (coneSize) { 8345 case 4: 8346 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8347 break; 8348 case 8: 8349 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8350 break; 8351 default: 8352 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8353 } 8354 if (cell >= 0) break; 8355 } 8356 break; 8357 default: 8358 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8359 } 8360 cells[p] = cell; 8361 } 8362 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8363 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8364 PetscFunctionReturn(0); 8365 } 8366 8367 /******************************** FEM Support **********************************/ 8368 8369 #undef __FUNCT__ 8370 #define __FUNCT__ "DMPlexVecGetClosure" 8371 /*@C 8372 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8373 8374 Not collective 8375 8376 Input Parameters: 8377 + dm - The DM 8378 . section - The section describing the layout in v, or NULL to use the default section 8379 . v - The local vector 8380 - point - The sieve point in the DM 8381 8382 Output Parameters: 8383 + csize - The number of values in the closure, or NULL 8384 - values - The array of values, which is a borrowed array and should not be freed 8385 8386 Level: intermediate 8387 8388 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8389 @*/ 8390 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8391 { 8392 PetscScalar *array, *vArray; 8393 PetscInt *points = NULL; 8394 PetscInt offsets[32]; 8395 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8396 PetscErrorCode ierr; 8397 8398 PetscFunctionBegin; 8399 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8400 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8401 if (!section) { 8402 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8403 } 8404 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8405 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8406 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8407 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8408 /* Compress out points not in the section */ 8409 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8410 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8411 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8412 points[q*2] = points[p]; 8413 points[q*2+1] = points[p+1]; 8414 ++q; 8415 } 8416 } 8417 numPoints = q; 8418 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8419 PetscInt dof, fdof; 8420 8421 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8422 for (f = 0; f < numFields; ++f) { 8423 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8424 offsets[f+1] += fdof; 8425 } 8426 size += dof; 8427 } 8428 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8429 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8430 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8431 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8432 for (p = 0; p < numPoints*2; p += 2) { 8433 PetscInt o = points[p+1]; 8434 PetscInt dof, off, d; 8435 PetscScalar *varr; 8436 8437 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8438 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8439 varr = &vArray[off]; 8440 if (numFields) { 8441 PetscInt fdof, foff, fcomp, f, c; 8442 8443 for (f = 0, foff = 0; f < numFields; ++f) { 8444 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8445 if (o >= 0) { 8446 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8447 array[offsets[f]] = varr[foff+d]; 8448 } 8449 } else { 8450 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8451 for (d = fdof/fcomp-1; d >= 0; --d) { 8452 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8453 array[offsets[f]] = varr[foff+d*fcomp+c]; 8454 } 8455 } 8456 } 8457 foff += fdof; 8458 } 8459 } else { 8460 if (o >= 0) { 8461 for (d = 0; d < dof; ++d, ++offsets[0]) { 8462 array[offsets[0]] = varr[d]; 8463 } 8464 } else { 8465 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8466 array[offsets[0]] = varr[d]; 8467 } 8468 } 8469 } 8470 } 8471 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8472 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8473 if (csize) *csize = size; 8474 *values = array; 8475 PetscFunctionReturn(0); 8476 } 8477 8478 #undef __FUNCT__ 8479 #define __FUNCT__ "DMPlexVecRestoreClosure" 8480 /*@C 8481 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8482 8483 Not collective 8484 8485 Input Parameters: 8486 + dm - The DM 8487 . section - The section describing the layout in v, or NULL to use the default section 8488 . v - The local vector 8489 . point - The sieve point in the DM 8490 . csize - The number of values in the closure, or NULL 8491 - values - The array of values, which is a borrowed array and should not be freed 8492 8493 Level: intermediate 8494 8495 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8496 @*/ 8497 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8498 { 8499 PetscInt size = 0; 8500 PetscErrorCode ierr; 8501 8502 PetscFunctionBegin; 8503 /* Should work without recalculating size */ 8504 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8505 PetscFunctionReturn(0); 8506 } 8507 8508 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8509 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8510 8511 #undef __FUNCT__ 8512 #define __FUNCT__ "updatePoint_private" 8513 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8514 { 8515 PetscInt cdof; /* The number of constraints on this point */ 8516 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8517 PetscScalar *a; 8518 PetscInt off, cind = 0, k; 8519 PetscErrorCode ierr; 8520 8521 PetscFunctionBegin; 8522 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8523 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8524 a = &array[off]; 8525 if (!cdof || setBC) { 8526 if (orientation >= 0) { 8527 for (k = 0; k < dof; ++k) { 8528 fuse(&a[k], values[k]); 8529 } 8530 } else { 8531 for (k = 0; k < dof; ++k) { 8532 fuse(&a[k], values[dof-k-1]); 8533 } 8534 } 8535 } else { 8536 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8537 if (orientation >= 0) { 8538 for (k = 0; k < dof; ++k) { 8539 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8540 fuse(&a[k], values[k]); 8541 } 8542 } else { 8543 for (k = 0; k < dof; ++k) { 8544 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8545 fuse(&a[k], values[dof-k-1]); 8546 } 8547 } 8548 } 8549 PetscFunctionReturn(0); 8550 } 8551 8552 #undef __FUNCT__ 8553 #define __FUNCT__ "updatePointFields_private" 8554 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8555 { 8556 PetscScalar *a; 8557 PetscInt numFields, off, foff, f; 8558 PetscErrorCode ierr; 8559 8560 PetscFunctionBegin; 8561 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8562 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8563 a = &array[off]; 8564 for (f = 0, foff = 0; f < numFields; ++f) { 8565 PetscInt fdof, fcomp, fcdof; 8566 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8567 PetscInt cind = 0, k, c; 8568 8569 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8570 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8571 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8572 if (!fcdof || setBC) { 8573 if (orientation >= 0) { 8574 for (k = 0; k < fdof; ++k) { 8575 fuse(&a[foff+k], values[foffs[f]+k]); 8576 } 8577 } else { 8578 for (k = fdof/fcomp-1; k >= 0; --k) { 8579 for (c = 0; c < fcomp; ++c) { 8580 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8581 } 8582 } 8583 } 8584 } else { 8585 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8586 if (orientation >= 0) { 8587 for (k = 0; k < fdof; ++k) { 8588 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8589 fuse(&a[foff+k], values[foffs[f]+k]); 8590 } 8591 } else { 8592 for (k = fdof/fcomp-1; k >= 0; --k) { 8593 for (c = 0; c < fcomp; ++c) { 8594 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8595 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8596 } 8597 } 8598 } 8599 } 8600 foff += fdof; 8601 foffs[f] += fdof; 8602 } 8603 PetscFunctionReturn(0); 8604 } 8605 8606 #undef __FUNCT__ 8607 #define __FUNCT__ "DMPlexVecSetClosure" 8608 /*@C 8609 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8610 8611 Not collective 8612 8613 Input Parameters: 8614 + dm - The DM 8615 . section - The section describing the layout in v, or NULL to use the default sectionw 8616 . v - The local vector 8617 . point - The sieve point in the DM 8618 . values - The array of values, which is a borrowed array and should not be freed 8619 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8620 8621 Level: intermediate 8622 8623 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8624 @*/ 8625 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8626 { 8627 PetscScalar *array; 8628 PetscInt *points = NULL; 8629 PetscInt offsets[32]; 8630 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8631 PetscErrorCode ierr; 8632 8633 PetscFunctionBegin; 8634 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8635 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8636 if (!section) { 8637 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8638 } 8639 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8640 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8641 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8642 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8643 /* Compress out points not in the section */ 8644 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8645 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8646 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8647 points[q*2] = points[p]; 8648 points[q*2+1] = points[p+1]; 8649 ++q; 8650 } 8651 } 8652 numPoints = q; 8653 for (p = 0; p < numPoints*2; p += 2) { 8654 PetscInt fdof; 8655 8656 for (f = 0; f < numFields; ++f) { 8657 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8658 offsets[f+1] += fdof; 8659 } 8660 } 8661 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8662 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8663 if (numFields) { 8664 switch (mode) { 8665 case INSERT_VALUES: 8666 for (p = 0; p < numPoints*2; p += 2) { 8667 PetscInt o = points[p+1]; 8668 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8669 } break; 8670 case INSERT_ALL_VALUES: 8671 for (p = 0; p < numPoints*2; p += 2) { 8672 PetscInt o = points[p+1]; 8673 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8674 } break; 8675 case ADD_VALUES: 8676 for (p = 0; p < numPoints*2; p += 2) { 8677 PetscInt o = points[p+1]; 8678 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8679 } break; 8680 case ADD_ALL_VALUES: 8681 for (p = 0; p < numPoints*2; p += 2) { 8682 PetscInt o = points[p+1]; 8683 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8684 } break; 8685 default: 8686 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8687 } 8688 } else { 8689 switch (mode) { 8690 case INSERT_VALUES: 8691 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8692 PetscInt o = points[p+1]; 8693 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8694 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8695 } break; 8696 case INSERT_ALL_VALUES: 8697 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8698 PetscInt o = points[p+1]; 8699 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8700 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8701 } break; 8702 case ADD_VALUES: 8703 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8704 PetscInt o = points[p+1]; 8705 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8706 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8707 } break; 8708 case ADD_ALL_VALUES: 8709 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8710 PetscInt o = points[p+1]; 8711 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8712 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8713 } break; 8714 default: 8715 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8716 } 8717 } 8718 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8719 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8720 PetscFunctionReturn(0); 8721 } 8722 8723 #undef __FUNCT__ 8724 #define __FUNCT__ "DMPlexPrintMatSetValues" 8725 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8726 { 8727 PetscMPIInt rank; 8728 PetscInt i, j; 8729 PetscErrorCode ierr; 8730 8731 PetscFunctionBegin; 8732 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8733 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8734 for (i = 0; i < numIndices; i++) { 8735 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8736 } 8737 for (i = 0; i < numIndices; i++) { 8738 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8739 for (j = 0; j < numIndices; j++) { 8740 #if defined(PETSC_USE_COMPLEX) 8741 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8742 #else 8743 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8744 #endif 8745 } 8746 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8747 } 8748 PetscFunctionReturn(0); 8749 } 8750 8751 #undef __FUNCT__ 8752 #define __FUNCT__ "indicesPoint_private" 8753 /* . off - The global offset of this point */ 8754 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8755 { 8756 PetscInt dof; /* The number of unknowns on this point */ 8757 PetscInt cdof; /* The number of constraints on this point */ 8758 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8759 PetscInt cind = 0, k; 8760 PetscErrorCode ierr; 8761 8762 PetscFunctionBegin; 8763 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8764 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8765 if (!cdof || setBC) { 8766 if (orientation >= 0) { 8767 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8768 } else { 8769 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8770 } 8771 } else { 8772 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8773 if (orientation >= 0) { 8774 for (k = 0; k < dof; ++k) { 8775 if ((cind < cdof) && (k == cdofs[cind])) { 8776 /* Insert check for returning constrained indices */ 8777 indices[*loff+k] = -(off+k+1); 8778 ++cind; 8779 } else { 8780 indices[*loff+k] = off+k-cind; 8781 } 8782 } 8783 } else { 8784 for (k = 0; k < dof; ++k) { 8785 if ((cind < cdof) && (k == cdofs[cind])) { 8786 /* Insert check for returning constrained indices */ 8787 indices[*loff+dof-k-1] = -(off+k+1); 8788 ++cind; 8789 } else { 8790 indices[*loff+dof-k-1] = off+k-cind; 8791 } 8792 } 8793 } 8794 } 8795 *loff += dof; 8796 PetscFunctionReturn(0); 8797 } 8798 8799 #undef __FUNCT__ 8800 #define __FUNCT__ "indicesPointFields_private" 8801 /* . off - The global offset of this point */ 8802 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8803 { 8804 PetscInt numFields, foff, f; 8805 PetscErrorCode ierr; 8806 8807 PetscFunctionBegin; 8808 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8809 for (f = 0, foff = 0; f < numFields; ++f) { 8810 PetscInt fdof, fcomp, cfdof; 8811 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8812 PetscInt cind = 0, k, c; 8813 8814 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8815 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8816 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8817 if (!cfdof || setBC) { 8818 if (orientation >= 0) { 8819 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8820 } else { 8821 for (k = fdof/fcomp-1; k >= 0; --k) { 8822 for (c = 0; c < fcomp; ++c) { 8823 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8824 } 8825 } 8826 } 8827 } else { 8828 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8829 if (orientation >= 0) { 8830 for (k = 0; k < fdof; ++k) { 8831 if ((cind < cfdof) && (k == fcdofs[cind])) { 8832 indices[foffs[f]+k] = -(off+foff+k+1); 8833 ++cind; 8834 } else { 8835 indices[foffs[f]+k] = off+foff+k-cind; 8836 } 8837 } 8838 } else { 8839 for (k = fdof/fcomp-1; k >= 0; --k) { 8840 for (c = 0; c < fcomp; ++c) { 8841 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8842 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8843 ++cind; 8844 } else { 8845 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8846 } 8847 } 8848 } 8849 } 8850 } 8851 foff += fdof - cfdof; 8852 foffs[f] += fdof; 8853 } 8854 PetscFunctionReturn(0); 8855 } 8856 8857 #undef __FUNCT__ 8858 #define __FUNCT__ "DMPlexMatSetClosure" 8859 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8860 { 8861 DM_Plex *mesh = (DM_Plex*) dm->data; 8862 PetscInt *points = NULL; 8863 PetscInt *indices; 8864 PetscInt offsets[32]; 8865 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8866 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8867 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8868 PetscErrorCode ierr; 8869 8870 PetscFunctionBegin; 8871 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8872 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8873 if (useDefault) { 8874 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8875 } 8876 if (useGlobalDefault) { 8877 if (useDefault) { 8878 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8879 } else { 8880 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8881 } 8882 } 8883 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8884 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8885 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8886 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8887 /* Compress out points not in the section */ 8888 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8889 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8890 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8891 points[q*2] = points[p]; 8892 points[q*2+1] = points[p+1]; 8893 ++q; 8894 } 8895 } 8896 numPoints = q; 8897 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8898 PetscInt fdof; 8899 8900 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8901 for (f = 0; f < numFields; ++f) { 8902 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8903 offsets[f+1] += fdof; 8904 } 8905 numIndices += dof; 8906 } 8907 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8908 8909 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8910 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8911 if (numFields) { 8912 for (p = 0; p < numPoints*2; p += 2) { 8913 PetscInt o = points[p+1]; 8914 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8915 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8916 } 8917 } else { 8918 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8919 PetscInt o = points[p+1]; 8920 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8921 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8922 } 8923 } 8924 if (useGlobalDefault && !useDefault) { 8925 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8926 } 8927 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8928 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8929 if (ierr) { 8930 PetscMPIInt rank; 8931 PetscErrorCode ierr2; 8932 8933 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8934 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8935 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8936 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8937 CHKERRQ(ierr); 8938 } 8939 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8940 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8941 PetscFunctionReturn(0); 8942 } 8943 8944 #undef __FUNCT__ 8945 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8946 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8947 { 8948 PetscSection coordSection; 8949 Vec coordinates; 8950 const PetscScalar *coords; 8951 const PetscInt dim = 2; 8952 PetscInt d, f; 8953 PetscErrorCode ierr; 8954 8955 PetscFunctionBegin; 8956 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8957 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8958 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8959 if (v0) { 8960 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8961 } 8962 if (J) { 8963 for (d = 0; d < dim; d++) { 8964 for (f = 0; f < dim; f++) { 8965 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8966 } 8967 } 8968 *detJ = J[0]*J[3] - J[1]*J[2]; 8969 #if 0 8970 if (detJ < 0.0) { 8971 const PetscReal xLength = mesh->periodicity[0]; 8972 8973 if (xLength != 0.0) { 8974 PetscReal v0x = coords[0*dim+0]; 8975 8976 if (v0x == 0.0) v0x = v0[0] = xLength; 8977 for (f = 0; f < dim; f++) { 8978 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8979 8980 J[0*dim+f] = 0.5*(px - v0x); 8981 } 8982 } 8983 detJ = J[0]*J[3] - J[1]*J[2]; 8984 } 8985 #endif 8986 PetscLogFlops(8.0 + 3.0); 8987 } 8988 if (invJ) { 8989 const PetscReal invDet = 1.0/(*detJ); 8990 8991 invJ[0] = invDet*J[3]; 8992 invJ[1] = -invDet*J[1]; 8993 invJ[2] = -invDet*J[2]; 8994 invJ[3] = invDet*J[0]; 8995 PetscLogFlops(5.0); 8996 } 8997 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8998 PetscFunctionReturn(0); 8999 } 9000 9001 #undef __FUNCT__ 9002 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9003 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9004 { 9005 PetscSection coordSection; 9006 Vec coordinates; 9007 const PetscScalar *coords; 9008 const PetscInt dim = 2; 9009 PetscInt d, f; 9010 PetscErrorCode ierr; 9011 9012 PetscFunctionBegin; 9013 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9014 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9015 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9016 if (v0) { 9017 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9018 } 9019 if (J) { 9020 for (d = 0; d < dim; d++) { 9021 for (f = 0; f < dim; f++) { 9022 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9023 } 9024 } 9025 *detJ = J[0]*J[3] - J[1]*J[2]; 9026 PetscLogFlops(8.0 + 3.0); 9027 } 9028 if (invJ) { 9029 const PetscReal invDet = 1.0/(*detJ); 9030 9031 invJ[0] = invDet*J[3]; 9032 invJ[1] = -invDet*J[1]; 9033 invJ[2] = -invDet*J[2]; 9034 invJ[3] = invDet*J[0]; 9035 PetscLogFlops(5.0); 9036 } 9037 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9038 PetscFunctionReturn(0); 9039 } 9040 9041 #undef __FUNCT__ 9042 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9043 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9044 { 9045 PetscSection coordSection; 9046 Vec coordinates; 9047 const PetscScalar *coords; 9048 const PetscInt dim = 3; 9049 PetscInt d, f; 9050 PetscErrorCode ierr; 9051 9052 PetscFunctionBegin; 9053 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9054 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9055 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9056 if (v0) { 9057 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9058 } 9059 if (J) { 9060 for (d = 0; d < dim; d++) { 9061 for (f = 0; f < dim; f++) { 9062 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9063 } 9064 } 9065 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9066 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9067 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9068 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9069 PetscLogFlops(18.0 + 12.0); 9070 } 9071 if (invJ) { 9072 const PetscReal invDet = 1.0/(*detJ); 9073 9074 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9075 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9076 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9077 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9078 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9079 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9080 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9081 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9082 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9083 PetscLogFlops(37.0); 9084 } 9085 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9086 PetscFunctionReturn(0); 9087 } 9088 9089 #undef __FUNCT__ 9090 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9091 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9092 { 9093 PetscSection coordSection; 9094 Vec coordinates; 9095 const PetscScalar *coords; 9096 const PetscInt dim = 3; 9097 PetscInt d; 9098 PetscErrorCode ierr; 9099 9100 PetscFunctionBegin; 9101 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9102 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9103 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9104 if (v0) { 9105 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9106 } 9107 if (J) { 9108 for (d = 0; d < dim; d++) { 9109 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9110 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9111 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9112 } 9113 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9114 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9115 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9116 PetscLogFlops(18.0 + 12.0); 9117 } 9118 if (invJ) { 9119 const PetscReal invDet = -1.0/(*detJ); 9120 9121 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9122 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9123 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9124 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9125 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9126 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9127 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9128 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9129 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9130 PetscLogFlops(37.0); 9131 } 9132 *detJ *= 8.0; 9133 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9134 PetscFunctionReturn(0); 9135 } 9136 9137 #undef __FUNCT__ 9138 #define __FUNCT__ "DMPlexComputeCellGeometry" 9139 /*@C 9140 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9141 9142 Collective on DM 9143 9144 Input Arguments: 9145 + dm - the DM 9146 - cell - the cell 9147 9148 Output Arguments: 9149 + v0 - the translation part of this affine transform 9150 . J - the Jacobian of the transform to the reference element 9151 . invJ - the inverse of the Jacobian 9152 - detJ - the Jacobian determinant 9153 9154 Level: advanced 9155 9156 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9157 @*/ 9158 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9159 { 9160 PetscInt dim, coneSize; 9161 PetscErrorCode ierr; 9162 9163 PetscFunctionBegin; 9164 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9165 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9166 switch (dim) { 9167 case 2: 9168 switch (coneSize) { 9169 case 3: 9170 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9171 break; 9172 case 4: 9173 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9174 break; 9175 default: 9176 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9177 } 9178 break; 9179 case 3: 9180 switch (coneSize) { 9181 case 4: 9182 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9183 break; 9184 case 8: 9185 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9186 break; 9187 default: 9188 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9189 } 9190 break; 9191 default: 9192 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9193 } 9194 PetscFunctionReturn(0); 9195 } 9196 9197 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9198 { 9199 switch (i) { 9200 case 0: 9201 switch (j) { 9202 case 0: return 0; 9203 case 1: 9204 switch (k) { 9205 case 0: return 0; 9206 case 1: return 0; 9207 case 2: return 1; 9208 } 9209 case 2: 9210 switch (k) { 9211 case 0: return 0; 9212 case 1: return -1; 9213 case 2: return 0; 9214 } 9215 } 9216 case 1: 9217 switch (j) { 9218 case 0: 9219 switch (k) { 9220 case 0: return 0; 9221 case 1: return 0; 9222 case 2: return -1; 9223 } 9224 case 1: return 0; 9225 case 2: 9226 switch (k) { 9227 case 0: return 1; 9228 case 1: return 0; 9229 case 2: return 0; 9230 } 9231 } 9232 case 2: 9233 switch (j) { 9234 case 0: 9235 switch (k) { 9236 case 0: return 0; 9237 case 1: return 1; 9238 case 2: return 0; 9239 } 9240 case 1: 9241 switch (k) { 9242 case 0: return -1; 9243 case 1: return 0; 9244 case 2: return 0; 9245 } 9246 case 2: return 0; 9247 } 9248 } 9249 return 0; 9250 } 9251 9252 #undef __FUNCT__ 9253 #define __FUNCT__ "DMPlexCreateRigidBody" 9254 /*@C 9255 DMPlexCreateRigidBody - create rigid body modes from coordinates 9256 9257 Collective on DM 9258 9259 Input Arguments: 9260 + dm - the DM 9261 . section - the local section associated with the rigid field, or NULL for the default section 9262 - globalSection - the global section associated with the rigid field, or NULL for the default section 9263 9264 Output Argument: 9265 . sp - the null space 9266 9267 Note: This is necessary to take account of Dirichlet conditions on the displacements 9268 9269 Level: advanced 9270 9271 .seealso: MatNullSpaceCreate() 9272 @*/ 9273 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9274 { 9275 MPI_Comm comm = ((PetscObject) dm)->comm; 9276 Vec coordinates, localMode, mode[6]; 9277 PetscSection coordSection; 9278 PetscScalar *coords; 9279 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9280 PetscErrorCode ierr; 9281 9282 PetscFunctionBegin; 9283 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9284 if (dim == 1) { 9285 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 9286 PetscFunctionReturn(0); 9287 } 9288 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9289 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9290 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9291 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9292 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9293 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9294 m = (dim*(dim+1))/2; 9295 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9296 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9297 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9298 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9299 /* Assume P1 */ 9300 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9301 for (d = 0; d < dim; ++d) { 9302 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9303 9304 values[d] = 1.0; 9305 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9306 for (v = vStart; v < vEnd; ++v) { 9307 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9308 } 9309 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9310 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9311 } 9312 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9313 for (d = dim; d < dim*(dim+1)/2; ++d) { 9314 PetscInt i, j, k = dim > 2 ? d - dim : d; 9315 9316 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9317 for (v = vStart; v < vEnd; ++v) { 9318 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9319 PetscInt off; 9320 9321 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9322 for (i = 0; i < dim; ++i) { 9323 for (j = 0; j < dim; ++j) { 9324 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9325 } 9326 } 9327 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9328 } 9329 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9330 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9331 } 9332 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9333 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9334 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 9335 /* Orthonormalize system */ 9336 for (i = dim; i < m; ++i) { 9337 PetscScalar dots[6]; 9338 9339 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9340 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9341 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9342 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 9343 } 9344 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9345 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9346 PetscFunctionReturn(0); 9347 } 9348 9349 #undef __FUNCT__ 9350 #define __FUNCT__ "DMPlexGetHybridBounds" 9351 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9352 { 9353 DM_Plex *mesh = (DM_Plex*) dm->data; 9354 PetscInt dim; 9355 PetscErrorCode ierr; 9356 9357 PetscFunctionBegin; 9358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9359 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9360 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9361 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9362 if (eMax) *eMax = mesh->hybridPointMax[1]; 9363 if (vMax) *vMax = mesh->hybridPointMax[0]; 9364 PetscFunctionReturn(0); 9365 } 9366 9367 #undef __FUNCT__ 9368 #define __FUNCT__ "DMPlexSetHybridBounds" 9369 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9370 { 9371 DM_Plex *mesh = (DM_Plex*) dm->data; 9372 PetscInt dim; 9373 PetscErrorCode ierr; 9374 9375 PetscFunctionBegin; 9376 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9377 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9378 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9379 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9380 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9381 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9382 PetscFunctionReturn(0); 9383 } 9384 9385 #undef __FUNCT__ 9386 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9387 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9388 { 9389 DM_Plex *mesh = (DM_Plex*) dm->data; 9390 9391 PetscFunctionBegin; 9392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9393 PetscValidPointer(cellHeight, 2); 9394 *cellHeight = mesh->vtkCellHeight; 9395 PetscFunctionReturn(0); 9396 } 9397 9398 #undef __FUNCT__ 9399 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9400 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9401 { 9402 DM_Plex *mesh = (DM_Plex*) dm->data; 9403 9404 PetscFunctionBegin; 9405 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9406 mesh->vtkCellHeight = cellHeight; 9407 PetscFunctionReturn(0); 9408 } 9409 9410 #undef __FUNCT__ 9411 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9412 /* We can easily have a form that takes an IS instead */ 9413 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9414 { 9415 PetscSection section, globalSection; 9416 PetscInt *numbers, p; 9417 PetscErrorCode ierr; 9418 9419 PetscFunctionBegin; 9420 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9421 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9422 for (p = pStart; p < pEnd; ++p) { 9423 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9424 } 9425 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9426 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9427 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9428 for (p = pStart; p < pEnd; ++p) { 9429 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9430 } 9431 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9432 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9433 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9434 PetscFunctionReturn(0); 9435 } 9436 9437 #undef __FUNCT__ 9438 #define __FUNCT__ "DMPlexGetCellNumbering" 9439 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9440 { 9441 DM_Plex *mesh = (DM_Plex*) dm->data; 9442 PetscInt cellHeight, cStart, cEnd, cMax; 9443 PetscErrorCode ierr; 9444 9445 PetscFunctionBegin; 9446 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9447 if (!mesh->globalCellNumbers) { 9448 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9449 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9450 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 9451 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9452 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9453 } 9454 *globalCellNumbers = mesh->globalCellNumbers; 9455 PetscFunctionReturn(0); 9456 } 9457 9458 #undef __FUNCT__ 9459 #define __FUNCT__ "DMPlexGetVertexNumbering" 9460 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9461 { 9462 DM_Plex *mesh = (DM_Plex*) dm->data; 9463 PetscInt vStart, vEnd, vMax; 9464 PetscErrorCode ierr; 9465 9466 PetscFunctionBegin; 9467 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9468 if (!mesh->globalVertexNumbers) { 9469 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9470 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9471 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9472 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9473 } 9474 *globalVertexNumbers = mesh->globalVertexNumbers; 9475 PetscFunctionReturn(0); 9476 } 9477 9478 #undef __FUNCT__ 9479 #define __FUNCT__ "DMPlexGetScale" 9480 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9481 { 9482 DM_Plex *mesh = (DM_Plex*) dm->data; 9483 9484 PetscFunctionBegin; 9485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9486 PetscValidPointer(scale, 3); 9487 *scale = mesh->scale[unit]; 9488 PetscFunctionReturn(0); 9489 } 9490 9491 #undef __FUNCT__ 9492 #define __FUNCT__ "DMPlexSetScale" 9493 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9494 { 9495 DM_Plex *mesh = (DM_Plex*) dm->data; 9496 9497 PetscFunctionBegin; 9498 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9499 mesh->scale[unit] = scale; 9500 PetscFunctionReturn(0); 9501 } 9502 9503 9504 /******************************************************************************* 9505 This should be in a separate Discretization object, but I am not sure how to lay 9506 it out yet, so I am stuffing things here while I experiment. 9507 *******************************************************************************/ 9508 #undef __FUNCT__ 9509 #define __FUNCT__ "DMPlexSetFEMIntegration" 9510 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9511 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9512 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9513 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9514 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9515 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9516 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9517 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9518 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9519 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9520 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9521 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9522 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9523 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9524 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9525 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9526 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9527 { 9528 DM_Plex *mesh = (DM_Plex*) dm->data; 9529 9530 PetscFunctionBegin; 9531 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9532 mesh->integrateResidualFEM = integrateResidualFEM; 9533 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9534 mesh->integrateJacobianFEM = integrateJacobianFEM; 9535 PetscFunctionReturn(0); 9536 } 9537 9538 #undef __FUNCT__ 9539 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9540 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9541 { 9542 Vec coordinates; 9543 PetscSection section, cSection; 9544 PetscInt dim, vStart, vEnd, v, c, d; 9545 PetscScalar *values, *cArray; 9546 PetscReal *coords; 9547 PetscErrorCode ierr; 9548 9549 PetscFunctionBegin; 9550 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9551 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9552 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9553 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9554 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9555 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9556 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9557 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9558 for (v = vStart; v < vEnd; ++v) { 9559 PetscInt dof, off; 9560 9561 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9562 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9563 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9564 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9565 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9566 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9567 } 9568 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9569 /* Temporary, must be replaced by a projection on the finite element basis */ 9570 { 9571 PetscInt eStart = 0, eEnd = 0, e, depth; 9572 9573 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9574 --depth; 9575 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9576 for (e = eStart; e < eEnd; ++e) { 9577 const PetscInt *cone = NULL; 9578 PetscInt coneSize, d; 9579 PetscScalar *coordsA, *coordsB; 9580 9581 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9582 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9583 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9584 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9585 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9586 for (d = 0; d < dim; ++d) { 9587 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9588 } 9589 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9590 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9591 } 9592 } 9593 9594 ierr = PetscFree(coords);CHKERRQ(ierr); 9595 ierr = PetscFree(values);CHKERRQ(ierr); 9596 #if 0 9597 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9598 PetscReal detJ; 9599 9600 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9601 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9602 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9603 9604 for (PetscInt c = cStart; c < cEnd; ++c) { 9605 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9606 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9607 const int oSize = pV.getSize(); 9608 int v = 0; 9609 9610 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9611 for (PetscInt cl = 0; cl < oSize; ++cl) { 9612 const PetscInt fDim; 9613 9614 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9615 if (pointDim) { 9616 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9617 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9618 } 9619 } 9620 } 9621 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9622 pV.clear(); 9623 } 9624 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9625 ierr = PetscFree(values);CHKERRQ(ierr); 9626 #endif 9627 PetscFunctionReturn(0); 9628 } 9629 9630 #undef __FUNCT__ 9631 #define __FUNCT__ "DMPlexProjectFunction" 9632 /*@C 9633 DMPlexProjectFunction - This projects the given function into the function space provided. 9634 9635 Input Parameters: 9636 + dm - The DM 9637 . numComp - The number of components (functions) 9638 . funcs - The coordinate functions to evaluate 9639 - mode - The insertion mode for values 9640 9641 Output Parameter: 9642 . X - vector 9643 9644 Level: developer 9645 9646 Note: 9647 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9648 We will eventually fix it. 9649 9650 ,seealso: DMPlexComputeL2Diff() 9651 */ 9652 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9653 { 9654 Vec localX; 9655 PetscErrorCode ierr; 9656 9657 PetscFunctionBegin; 9658 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9659 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9660 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9661 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9662 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9663 PetscFunctionReturn(0); 9664 } 9665 9666 #undef __FUNCT__ 9667 #define __FUNCT__ "DMPlexComputeL2Diff" 9668 /*@C 9669 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9670 9671 Input Parameters: 9672 + dm - The DM 9673 . quad - The PetscQuadrature object for each field 9674 . funcs - The functions to evaluate for each field component 9675 - X - The coefficient vector u_h 9676 9677 Output Parameter: 9678 . diff - The diff ||u - u_h||_2 9679 9680 Level: developer 9681 9682 .seealso: DMPlexProjectFunction() 9683 */ 9684 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9685 { 9686 const PetscInt debug = 0; 9687 PetscSection section; 9688 Vec localX; 9689 PetscReal *coords, *v0, *J, *invJ, detJ; 9690 PetscReal localDiff = 0.0; 9691 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9692 PetscErrorCode ierr; 9693 9694 PetscFunctionBegin; 9695 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9696 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9697 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9698 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9699 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9700 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9701 for (field = 0; field < numFields; ++field) { 9702 numComponents += quad[field].numComponents; 9703 } 9704 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9705 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9706 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9707 for (c = cStart; c < cEnd; ++c) { 9708 const PetscScalar *x; 9709 PetscReal elemDiff = 0.0; 9710 9711 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9712 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9713 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9714 9715 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9716 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9717 const PetscReal *quadPoints = quad[field].quadPoints; 9718 const PetscReal *quadWeights = quad[field].quadWeights; 9719 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9720 const PetscInt numBasisComps = quad[field].numComponents; 9721 const PetscReal *basis = quad[field].basis; 9722 PetscInt q, d, e, fc, f; 9723 9724 if (debug) { 9725 char title[1024]; 9726 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9727 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9728 } 9729 for (q = 0; q < numQuadPoints; ++q) { 9730 for (d = 0; d < dim; d++) { 9731 coords[d] = v0[d]; 9732 for (e = 0; e < dim; e++) { 9733 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9734 } 9735 } 9736 for (fc = 0; fc < numBasisComps; ++fc) { 9737 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9738 PetscReal interpolant = 0.0; 9739 for (f = 0; f < numBasisFuncs; ++f) { 9740 const PetscInt fidx = f*numBasisComps+fc; 9741 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9742 } 9743 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9744 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9745 } 9746 } 9747 comp += numBasisComps; 9748 fieldOffset += numBasisFuncs*numBasisComps; 9749 } 9750 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9751 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9752 localDiff += elemDiff; 9753 } 9754 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9755 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9756 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9757 *diff = PetscSqrtReal(*diff); 9758 PetscFunctionReturn(0); 9759 } 9760 9761 #undef __FUNCT__ 9762 #define __FUNCT__ "DMPlexComputeResidualFEM" 9763 /*@ 9764 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9765 9766 Input Parameters: 9767 + dm - The mesh 9768 . X - Local input vector 9769 - user - The user context 9770 9771 Output Parameter: 9772 . F - Local output vector 9773 9774 Note: 9775 The second member of the user context must be an FEMContext. 9776 9777 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9778 like a GPU, or vectorize on a multicore machine. 9779 9780 .seealso: DMPlexComputeJacobianActionFEM() 9781 */ 9782 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9783 { 9784 DM_Plex *mesh = (DM_Plex*) dm->data; 9785 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9786 PetscQuadrature *quad = fem->quad; 9787 PetscSection section; 9788 PetscReal *v0, *J, *invJ, *detJ; 9789 PetscScalar *elemVec, *u; 9790 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9791 PetscInt cellDof = 0, numComponents = 0; 9792 PetscErrorCode ierr; 9793 9794 PetscFunctionBegin; 9795 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9796 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9797 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9798 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9799 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9800 numCells = cEnd - cStart; 9801 for (field = 0; field < numFields; ++field) { 9802 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9803 numComponents += quad[field].numComponents; 9804 } 9805 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9806 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9807 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); 9808 for (c = cStart; c < cEnd; ++c) { 9809 const PetscScalar *x; 9810 PetscInt i; 9811 9812 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9813 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9814 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9815 9816 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9817 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9818 } 9819 for (field = 0; field < numFields; ++field) { 9820 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9821 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9822 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9823 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9824 /* Conforming batches */ 9825 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9826 PetscInt numBlocks = 1; 9827 PetscInt batchSize = numBlocks * blockSize; 9828 PetscInt numBatches = numBatchesTmp; 9829 PetscInt numChunks = numCells / (numBatches*batchSize); 9830 /* Remainder */ 9831 PetscInt numRemainder = numCells % (numBatches * batchSize); 9832 PetscInt offset = numCells - numRemainder; 9833 9834 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9835 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9836 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9837 } 9838 for (c = cStart; c < cEnd; ++c) { 9839 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9840 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9841 } 9842 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9843 if (mesh->printFEM) { 9844 PetscMPIInt rank, numProcs; 9845 PetscInt p; 9846 9847 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9848 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9849 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9850 for (p = 0; p < numProcs; ++p) { 9851 if (p == rank) { 9852 Vec f; 9853 9854 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9855 ierr = VecCopy(F, f);CHKERRQ(ierr); 9856 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9857 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9858 ierr = VecDestroy(&f);CHKERRQ(ierr); 9859 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9860 } 9861 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9862 } 9863 } 9864 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9865 PetscFunctionReturn(0); 9866 } 9867 9868 #undef __FUNCT__ 9869 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9870 /*@C 9871 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9872 9873 Input Parameters: 9874 + dm - The mesh 9875 . J - The Jacobian shell matrix 9876 . X - Local input vector 9877 - user - The user context 9878 9879 Output Parameter: 9880 . F - Local output vector 9881 9882 Note: 9883 The second member of the user context must be an FEMContext. 9884 9885 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9886 like a GPU, or vectorize on a multicore machine. 9887 9888 .seealso: DMPlexComputeResidualFEM() 9889 */ 9890 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9891 { 9892 DM_Plex *mesh = (DM_Plex*) dm->data; 9893 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9894 PetscQuadrature *quad = fem->quad; 9895 PetscSection section; 9896 JacActionCtx *jctx; 9897 PetscReal *v0, *J, *invJ, *detJ; 9898 PetscScalar *elemVec, *u, *a; 9899 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9900 PetscInt cellDof = 0; 9901 PetscErrorCode ierr; 9902 9903 PetscFunctionBegin; 9904 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9905 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9906 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9907 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9908 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9909 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9910 numCells = cEnd - cStart; 9911 for (field = 0; field < numFields; ++field) { 9912 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9913 } 9914 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9915 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); 9916 for (c = cStart; c < cEnd; ++c) { 9917 const PetscScalar *x; 9918 PetscInt i; 9919 9920 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9921 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9922 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9923 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9924 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9925 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9926 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9927 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9928 } 9929 for (field = 0; field < numFields; ++field) { 9930 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9931 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9932 /* Conforming batches */ 9933 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9934 PetscInt numBlocks = 1; 9935 PetscInt batchSize = numBlocks * blockSize; 9936 PetscInt numBatches = numBatchesTmp; 9937 PetscInt numChunks = numCells / (numBatches*batchSize); 9938 /* Remainder */ 9939 PetscInt numRemainder = numCells % (numBatches * batchSize); 9940 PetscInt offset = numCells - numRemainder; 9941 9942 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); 9943 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], 9944 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9945 } 9946 for (c = cStart; c < cEnd; ++c) { 9947 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9948 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9949 } 9950 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9951 if (mesh->printFEM) { 9952 PetscMPIInt rank, numProcs; 9953 PetscInt p; 9954 9955 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9956 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9957 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9958 for (p = 0; p < numProcs; ++p) { 9959 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9960 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9961 } 9962 } 9963 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9964 PetscFunctionReturn(0); 9965 } 9966 9967 #undef __FUNCT__ 9968 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9969 /*@ 9970 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9971 9972 Input Parameters: 9973 + dm - The mesh 9974 . X - Local input vector 9975 - user - The user context 9976 9977 Output Parameter: 9978 . Jac - Jacobian matrix 9979 9980 Note: 9981 The second member of the user context must be an FEMContext. 9982 9983 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9984 like a GPU, or vectorize on a multicore machine. 9985 9986 .seealso: FormFunctionLocal() 9987 */ 9988 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9989 { 9990 DM_Plex *mesh = (DM_Plex*) dm->data; 9991 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9992 PetscQuadrature *quad = fem->quad; 9993 PetscSection section; 9994 PetscReal *v0, *J, *invJ, *detJ; 9995 PetscScalar *elemMat, *u; 9996 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9997 PetscInt cellDof = 0, numComponents = 0; 9998 PetscBool isShell; 9999 PetscErrorCode ierr; 10000 10001 PetscFunctionBegin; 10002 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10003 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10004 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10005 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10006 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10007 numCells = cEnd - cStart; 10008 for (field = 0; field < numFields; ++field) { 10009 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10010 numComponents += quad[field].numComponents; 10011 } 10012 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10013 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10014 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); 10015 for (c = cStart; c < cEnd; ++c) { 10016 const PetscScalar *x; 10017 PetscInt i; 10018 10019 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10020 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10021 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 10022 10023 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10024 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 10025 } 10026 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10027 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10028 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10029 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10030 PetscInt fieldJ; 10031 10032 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10033 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10034 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10035 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10036 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10037 /* Conforming batches */ 10038 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10039 PetscInt numBlocks = 1; 10040 PetscInt batchSize = numBlocks * blockSize; 10041 PetscInt numBatches = numBatchesTmp; 10042 PetscInt numChunks = numCells / (numBatches*batchSize); 10043 /* Remainder */ 10044 PetscInt numRemainder = numCells % (numBatches * batchSize); 10045 PetscInt offset = numCells - numRemainder; 10046 10047 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10048 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10049 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10050 } 10051 } 10052 for (c = cStart; c < cEnd; ++c) { 10053 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10054 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10055 } 10056 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10057 10058 /* Assemble matrix, using the 2-step process: 10059 MatAssemblyBegin(), MatAssemblyEnd(). */ 10060 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10061 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10062 10063 if (mesh->printFEM) { 10064 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10065 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10066 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10067 } 10068 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10069 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10070 if (isShell) { 10071 JacActionCtx *jctx; 10072 10073 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10074 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10075 } 10076 *str = SAME_NONZERO_PATTERN; 10077 PetscFunctionReturn(0); 10078 } 10079 10080 10081 #undef __FUNCT__ 10082 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10083 /*@C 10084 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10085 the local section and an SF describing the section point overlap. 10086 10087 Input Parameters: 10088 + s - The PetscSection for the local field layout 10089 . sf - The SF describing parallel layout of the section points 10090 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10091 . label - The label specifying the points 10092 - labelValue - The label stratum specifying the points 10093 10094 Output Parameter: 10095 . gsection - The PetscSection for the global field layout 10096 10097 Note: This gives negative sizes and offsets to points not owned by this process 10098 10099 Level: developer 10100 10101 .seealso: PetscSectionCreate() 10102 @*/ 10103 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10104 { 10105 PetscInt *neg; 10106 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10107 PetscErrorCode ierr; 10108 10109 PetscFunctionBegin; 10110 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10111 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10112 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10113 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10114 /* Mark ghost points with negative dof */ 10115 for (p = pStart; p < pEnd; ++p) { 10116 PetscInt value; 10117 10118 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10119 if (value != labelValue) continue; 10120 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10121 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10122 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10123 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10124 neg[p-pStart] = -(dof+1); 10125 } 10126 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10127 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 10128 if (nroots >= 0) { 10129 if (nroots > pEnd - pStart) { 10130 PetscInt *tmpDof; 10131 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10132 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10133 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10134 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10135 for (p = pStart; p < pEnd; ++p) { 10136 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 10137 } 10138 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10139 } else { 10140 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10141 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10142 } 10143 } 10144 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10145 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10146 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10147 10148 (*gsection)->atlasOff[p] = off; 10149 10150 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10151 } 10152 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10153 globalOff -= off; 10154 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10155 (*gsection)->atlasOff[p] += globalOff; 10156 10157 neg[p] = -((*gsection)->atlasOff[p]+1); 10158 } 10159 /* Put in negative offsets for ghost points */ 10160 if (nroots >= 0) { 10161 if (nroots > pEnd - pStart) { 10162 PetscInt *tmpOff; 10163 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10164 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10165 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10166 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10167 for (p = pStart; p < pEnd; ++p) { 10168 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 10169 } 10170 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10171 } else { 10172 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10173 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10174 } 10175 } 10176 ierr = PetscFree(neg);CHKERRQ(ierr); 10177 PetscFunctionReturn(0); 10178 } 10179