1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/vecimpl.h> 4 #include <petsc-private/isimpl.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 8 9 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "VecView_Plex_Local" 14 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 15 { 16 DM dm; 17 PetscBool isvtk; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 22 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 23 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 24 if (isvtk) { 25 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 26 PetscSection section; 27 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 28 29 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 30 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 33 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 34 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 35 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 36 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 37 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 38 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 39 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 40 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 41 } else if (cdof && vdof) { 42 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 43 } else if (cdof) { 44 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 45 * vector or just happens to have the same number of dofs as the dimension. */ 46 if (cdof == dim) { 47 ft = PETSC_VTK_CELL_VECTOR_FIELD; 48 } else { 49 ft = PETSC_VTK_CELL_FIELD; 50 } 51 } else if (vdof) { 52 if (vdof == dim) { 53 ft = PETSC_VTK_POINT_VECTOR_FIELD; 54 } else { 55 ft = PETSC_VTK_POINT_FIELD; 56 } 57 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 58 59 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 61 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 62 } else { 63 PetscBool isseq; 64 65 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 66 if (isseq) { 67 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 68 } else { 69 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "VecView_Plex" 77 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 78 { 79 DM dm; 80 PetscBool isvtk; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 85 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 86 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 87 if (isvtk) { 88 Vec locv; 89 const char *name; 90 91 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 92 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 93 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 96 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 97 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 98 } else { 99 PetscBool isseq; 100 101 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 102 if (isseq) { 103 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 104 } else { 105 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexView_Ascii" 113 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 114 { 115 DM_Plex *mesh = (DM_Plex*) dm->data; 116 DM cdm; 117 DMLabel markers; 118 PetscSection coordSection; 119 Vec coordinates; 120 PetscViewerFormat format; 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 125 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 126 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 127 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 128 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 129 const char *name; 130 PetscInt maxConeSize, maxSupportSize; 131 PetscInt pStart, pEnd, p; 132 PetscMPIInt rank, size; 133 134 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 135 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 136 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 137 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 138 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 143 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 144 for (p = pStart; p < pEnd; ++p) { 145 PetscInt dof, off, s; 146 147 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 148 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 149 for (s = off; s < off+dof; ++s) { 150 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 151 } 152 } 153 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 154 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 155 for (p = pStart; p < pEnd; ++p) { 156 PetscInt dof, off, c; 157 158 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 159 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 160 for (c = off; c < off+dof; ++c) { 161 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 162 } 163 } 164 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 165 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 166 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 167 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 168 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for (c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 284 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 285 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 286 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 287 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 288 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 289 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 290 if (depth == 1) { 291 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 292 pEnd = pEnd - pStart; 293 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 294 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 295 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 296 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 297 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 298 pEnd = pEnd - pStart; 299 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 300 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 301 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 302 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 303 } else { 304 for (d = 0; d <= dim; d++) { 305 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 306 pEnd = pEnd - pStart; 307 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 308 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 309 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 310 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 311 } 312 } 313 ierr = PetscFree(sizes);CHKERRQ(ierr); 314 } 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "DMView_Plex" 320 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 321 { 322 PetscBool iascii, isbinary; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 327 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 330 if (iascii) { 331 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 332 #if 0 333 } else if (isbinary) { 334 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 335 #endif 336 } 337 PetscFunctionReturn(0); 338 } 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "DMDestroy_Plex" 342 PetscErrorCode DMDestroy_Plex(DM dm) 343 { 344 DM_Plex *mesh = (DM_Plex*) dm->data; 345 DMLabel next = mesh->labels; 346 PetscErrorCode ierr; 347 348 PetscFunctionBegin; 349 if (--mesh->refct > 0) PetscFunctionReturn(0); 350 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 353 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 355 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 356 while (next) { 357 DMLabel tmp = next->next; 358 359 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 360 next = tmp; 361 } 362 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 364 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 365 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 366 ierr = PetscFree(mesh);CHKERRQ(ierr); 367 PetscFunctionReturn(0); 368 } 369 370 #undef __FUNCT__ 371 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 372 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 373 { 374 const PetscInt *support = NULL; 375 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 376 PetscErrorCode ierr; 377 378 PetscFunctionBegin; 379 if (useClosure) { 380 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 381 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 382 for (s = 0; s < supportSize; ++s) { 383 const PetscInt *cone = NULL; 384 PetscInt coneSize, c, q; 385 386 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 387 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 388 for (c = 0; c < coneSize; ++c) { 389 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 390 if (cone[c] == adj[q]) break; 391 } 392 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 393 } 394 } 395 } else { 396 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 397 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 398 for (s = 0; s < supportSize; ++s) { 399 const PetscInt *cone = NULL; 400 PetscInt coneSize, c, q; 401 402 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 403 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 404 for (c = 0; c < coneSize; ++c) { 405 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 406 if (cone[c] == adj[q]) break; 407 } 408 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 409 } 410 } 411 } 412 *adjSize = numAdj; 413 PetscFunctionReturn(0); 414 } 415 416 #undef __FUNCT__ 417 #define __FUNCT__ "DMPlexGetAdjacency_Private" 418 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 419 { 420 const PetscInt *star = tmpClosure; 421 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 422 PetscErrorCode ierr; 423 424 PetscFunctionBegin; 425 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 426 for (s = 2; s < starSize*2; s += 2) { 427 const PetscInt *closure = NULL; 428 PetscInt closureSize, c, q; 429 430 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 431 for (c = 0; c < closureSize*2; c += 2) { 432 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 433 if (closure[c] == adj[q]) break; 434 } 435 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 436 } 437 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 438 } 439 *adjSize = numAdj; 440 PetscFunctionReturn(0); 441 } 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 445 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 446 { 447 DM_Plex *mesh = (DM_Plex*) dm->data; 448 449 PetscFunctionBegin; 450 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 451 mesh->preallocCenterDim = preallocCenterDim; 452 PetscFunctionReturn(0); 453 } 454 455 #undef __FUNCT__ 456 #define __FUNCT__ "DMPlexPreallocateOperator" 457 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 458 { 459 DM_Plex *mesh = (DM_Plex*) dm->data; 460 MPI_Comm comm; 461 PetscSF sf, sfDof, sfAdj; 462 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 463 PetscInt nleaves, l, p; 464 const PetscInt *leaves; 465 const PetscSFNode *remotes; 466 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 467 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 468 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 469 PetscLayout rLayout; 470 PetscInt locRows, rStart, rEnd, r; 471 PetscMPIInt size; 472 PetscBool useClosure, debug = PETSC_FALSE; 473 PetscErrorCode ierr; 474 475 PetscFunctionBegin; 476 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 477 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 478 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 479 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 480 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 481 /* Create dof SF based on point SF */ 482 if (debug) { 483 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 487 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 488 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 489 } 490 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 491 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 492 if (debug) { 493 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 494 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 495 } 496 /* Create section for dof adjacency (dof ==> # adj dof) */ 497 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 498 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 499 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 500 if (mesh->preallocCenterDim == dim) { 501 useClosure = PETSC_FALSE; 502 } else if (mesh->preallocCenterDim == 0) { 503 useClosure = PETSC_TRUE; 504 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 505 506 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 507 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 510 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 511 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 512 /* Fill in the ghost dofs on the interface */ 513 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 514 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 515 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 516 517 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 518 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 519 520 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 521 522 /* 523 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 524 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 525 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 526 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 527 Create sfAdj connecting rootSectionAdj and leafSectionAdj 528 3. Visit unowned points on interface, write adjacencies to adj 529 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 530 4. Visit owned points on interface, write adjacencies to rootAdj 531 Remove redundancy in rootAdj 532 ** The last two traversals use transitive closure 533 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 534 Allocate memory addressed by sectionAdj (cols) 535 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 536 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 537 */ 538 539 for (l = 0; l < nleaves; ++l) { 540 PetscInt dof, off, d, q; 541 PetscInt p = leaves[l], numAdj = maxAdjSize; 542 543 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 544 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 545 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 546 for (q = 0; q < numAdj; ++q) { 547 const PetscInt padj = tmpAdj[q]; 548 PetscInt ndof, ncdof; 549 550 if ((padj < pStart) || (padj >= pEnd)) continue; 551 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 552 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 553 for (d = off; d < off+dof; ++d) { 554 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 555 } 556 } 557 } 558 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 559 if (debug) { 560 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 561 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 562 } 563 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 564 if (size > 1) { 565 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 566 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 567 } 568 if (debug) { 569 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 570 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 571 } 572 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 573 for (p = pStart; p < pEnd; ++p) { 574 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 575 576 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 577 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 578 if (!dof) continue; 579 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 580 if (adof <= 0) continue; 581 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 582 for (q = 0; q < numAdj; ++q) { 583 const PetscInt padj = tmpAdj[q]; 584 PetscInt ndof, ncdof; 585 586 if ((padj < pStart) || (padj >= pEnd)) continue; 587 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 588 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 589 for (d = off; d < off+dof; ++d) { 590 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 591 } 592 } 593 } 594 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 595 if (debug) { 596 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 597 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 598 } 599 /* Create adj SF based on dof SF */ 600 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 601 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 602 if (debug) { 603 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 604 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 605 } 606 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 607 /* Create leaf adjacency */ 608 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 609 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 610 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 611 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 612 for (l = 0; l < nleaves; ++l) { 613 PetscInt dof, off, d, q; 614 PetscInt p = leaves[l], numAdj = maxAdjSize; 615 616 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 617 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 618 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 619 for (d = off; d < off+dof; ++d) { 620 PetscInt aoff, i = 0; 621 622 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 623 for (q = 0; q < numAdj; ++q) { 624 const PetscInt padj = tmpAdj[q]; 625 PetscInt ndof, ncdof, ngoff, nd; 626 627 if ((padj < pStart) || (padj >= pEnd)) continue; 628 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 629 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 630 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 631 for (nd = 0; nd < ndof-ncdof; ++nd) { 632 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 633 ++i; 634 } 635 } 636 } 637 } 638 /* Debugging */ 639 if (debug) { 640 IS tmp; 641 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 642 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 643 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 644 } 645 /* Gather adjacenct indices to root */ 646 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 647 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 648 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 649 if (size > 1) { 650 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 651 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 652 } 653 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 654 ierr = PetscFree(adj);CHKERRQ(ierr); 655 /* Debugging */ 656 if (debug) { 657 IS tmp; 658 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 659 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 660 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 661 } 662 /* Add in local adjacency indices for owned dofs on interface (roots) */ 663 for (p = pStart; p < pEnd; ++p) { 664 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 665 666 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 667 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 668 if (!dof) continue; 669 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 670 if (adof <= 0) continue; 671 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 672 for (d = off; d < off+dof; ++d) { 673 PetscInt adof, aoff, i; 674 675 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 676 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 677 i = adof-1; 678 for (q = 0; q < numAdj; ++q) { 679 const PetscInt padj = tmpAdj[q]; 680 PetscInt ndof, ncdof, ngoff, nd; 681 682 if ((padj < pStart) || (padj >= pEnd)) continue; 683 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 684 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 685 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 686 for (nd = 0; nd < ndof-ncdof; ++nd) { 687 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 688 --i; 689 } 690 } 691 } 692 } 693 /* Debugging */ 694 if (debug) { 695 IS tmp; 696 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 697 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 698 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 699 } 700 /* Compress indices */ 701 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 702 for (p = pStart; p < pEnd; ++p) { 703 PetscInt dof, cdof, off, d; 704 PetscInt adof, aoff; 705 706 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 707 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 708 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 709 if (!dof) continue; 710 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 711 if (adof <= 0) continue; 712 for (d = off; d < off+dof-cdof; ++d) { 713 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 714 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 715 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 716 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 717 } 718 } 719 /* Debugging */ 720 if (debug) { 721 IS tmp; 722 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 723 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 724 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 725 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 726 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 727 } 728 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 729 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 730 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 731 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 732 for (p = pStart; p < pEnd; ++p) { 733 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 734 PetscBool found = PETSC_TRUE; 735 736 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 737 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 738 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 739 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 740 for (d = 0; d < dof-cdof; ++d) { 741 PetscInt ldof, rdof; 742 743 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 744 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 745 if (ldof > 0) { 746 /* We do not own this point */ 747 } else if (rdof > 0) { 748 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 749 } else { 750 found = PETSC_FALSE; 751 } 752 } 753 if (found) continue; 754 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 755 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 756 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 757 for (q = 0; q < numAdj; ++q) { 758 const PetscInt padj = tmpAdj[q]; 759 PetscInt ndof, ncdof, noff; 760 761 if ((padj < pStart) || (padj >= pEnd)) continue; 762 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 763 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 764 ierr = PetscSectionGetOffset(section, padj, &noff);CHKERRQ(ierr); 765 for (d = goff; d < goff+dof-cdof; ++d) { 766 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 767 } 768 } 769 } 770 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 771 if (debug) { 772 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 773 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 774 } 775 /* Get adjacent indices */ 776 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 777 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 778 for (p = pStart; p < pEnd; ++p) { 779 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 780 PetscBool found = PETSC_TRUE; 781 782 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 783 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 784 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 786 for (d = 0; d < dof-cdof; ++d) { 787 PetscInt ldof, rdof; 788 789 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 790 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 791 if (ldof > 0) { 792 /* We do not own this point */ 793 } else if (rdof > 0) { 794 PetscInt aoff, roff; 795 796 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 797 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 798 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 799 } else { 800 found = PETSC_FALSE; 801 } 802 } 803 if (found) continue; 804 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 805 for (d = goff; d < goff+dof-cdof; ++d) { 806 PetscInt adof, aoff, i = 0; 807 808 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 809 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 810 for (q = 0; q < numAdj; ++q) { 811 const PetscInt padj = tmpAdj[q]; 812 PetscInt ndof, ncdof, ngoff, nd; 813 const PetscInt *ncind; 814 815 /* Adjacent points may not be in the section chart */ 816 if ((padj < pStart) || (padj >= pEnd)) continue; 817 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 818 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 819 ierr = PetscSectionGetConstraintIndices(section, padj, &ncind);CHKERRQ(ierr); 820 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 821 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 822 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 823 } 824 } 825 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 826 } 827 } 828 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 829 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 830 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 831 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 832 /* Debugging */ 833 if (debug) { 834 IS tmp; 835 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 836 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 837 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 838 } 839 /* Create allocation vectors from adjacency graph */ 840 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 841 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr); 842 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 843 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 844 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 845 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 846 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 847 /* Only loop over blocks of rows */ 848 if (rStart%bs || rEnd%bs) SETERRQ3(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 849 for (r = rStart/bs; r < rEnd/bs; ++r) { 850 const PetscInt row = r*bs; 851 PetscInt numCols, cStart, c; 852 853 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 854 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 855 for (c = cStart; c < cStart+numCols; ++c) { 856 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 857 ++dnz[r-rStart]; 858 if (cols[c] >= row) ++dnzu[r-rStart]; 859 } else { 860 ++onz[r-rStart]; 861 if (cols[c] >= row) ++onzu[r-rStart]; 862 } 863 } 864 } 865 if (bs > 1) { 866 for (r = 0; r < locRows/bs; ++r) { 867 dnz[r] /= bs; 868 onz[r] /= bs; 869 dnzu[r] /= bs; 870 onzu[r] /= bs; 871 } 872 } 873 /* Set matrix pattern */ 874 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 875 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 876 /* Fill matrix with zeros */ 877 if (fillMatrix) { 878 PetscScalar *values; 879 PetscInt maxRowLen = 0; 880 881 for (r = rStart; r < rEnd; ++r) { 882 PetscInt len; 883 884 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 885 maxRowLen = PetscMax(maxRowLen, len); 886 } 887 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 888 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 889 for (r = rStart; r < rEnd; ++r) { 890 PetscInt numCols, cStart; 891 892 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 893 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 894 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 895 } 896 ierr = PetscFree(values);CHKERRQ(ierr); 897 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 898 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 899 } 900 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 901 ierr = PetscFree(cols);CHKERRQ(ierr); 902 PetscFunctionReturn(0); 903 } 904 905 #if 0 906 #undef __FUNCT__ 907 #define __FUNCT__ "DMPlexPreallocateOperator_2" 908 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 909 { 910 PetscInt *tmpClosure,*tmpAdj,*visits; 911 PetscInt c,cStart,cEnd,pStart,pEnd; 912 PetscErrorCode ierr; 913 914 PetscFunctionBegin; 915 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 916 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 917 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 918 919 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 920 921 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 922 npoints = pEnd - pStart; 923 924 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 925 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 926 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 927 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 928 for (c=cStart; c<cEnd; c++) { 929 PetscInt *support = tmpClosure; 930 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 931 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 932 } 933 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 934 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 935 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 936 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 937 938 ierr = PetscSFGetRanks();CHKERRQ(ierr); 939 940 941 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 942 for (c=cStart; c<cEnd; c++) { 943 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 944 /* 945 Depth-first walk of transitive closure. 946 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. 947 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 948 */ 949 } 950 951 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 952 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 953 PetscFunctionReturn(0); 954 } 955 #endif 956 957 #undef __FUNCT__ 958 #define __FUNCT__ "DMCreateMatrix_Plex" 959 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 960 { 961 PetscSection section, sectionGlobal; 962 PetscInt bs = -1; 963 PetscInt localSize; 964 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 965 PetscErrorCode ierr; 966 967 PetscFunctionBegin; 968 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 969 ierr = MatInitializePackage(NULL);CHKERRQ(ierr); 970 #endif 971 if (!mtype) mtype = MATAIJ; 972 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 973 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 974 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 975 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 976 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 977 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 978 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 979 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 980 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 981 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 982 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 983 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 984 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 985 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 986 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 987 /* Check for symmetric storage */ 988 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 989 if (isSymmetric) { 990 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 991 } 992 if (!isShell) { 993 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 994 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 995 996 if (bs < 0) { 997 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 998 PetscInt pStart, pEnd, p, dof, cdof; 999 1000 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1001 for (p = pStart; p < pEnd; ++p) { 1002 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1003 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 1004 if (dof-cdof) { 1005 if (bs < 0) { 1006 bs = dof-cdof; 1007 } else if (bs != dof-cdof) { 1008 /* Layout does not admit a pointwise block size */ 1009 bs = 1; 1010 break; 1011 } 1012 } 1013 } 1014 /* Must have same blocksize on all procs (some might have no points) */ 1015 bsLocal = bs; 1016 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1017 bsLocal = bs < 0 ? bsMax : bs; 1018 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1019 if (bsMin != bsMax) { 1020 bs = 1; 1021 } else { 1022 bs = bsMax; 1023 } 1024 } else { 1025 bs = 1; 1026 } 1027 } 1028 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1029 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1030 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1031 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1032 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1033 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1034 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1035 } 1036 PetscFunctionReturn(0); 1037 } 1038 1039 #undef __FUNCT__ 1040 #define __FUNCT__ "DMPlexGetDimension" 1041 /*@ 1042 DMPlexGetDimension - Return the topological mesh dimension 1043 1044 Not collective 1045 1046 Input Parameter: 1047 . mesh - The DMPlex 1048 1049 Output Parameter: 1050 . dim - The topological mesh dimension 1051 1052 Level: beginner 1053 1054 .seealso: DMPlexCreate() 1055 @*/ 1056 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1057 { 1058 DM_Plex *mesh = (DM_Plex*) dm->data; 1059 1060 PetscFunctionBegin; 1061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1062 PetscValidPointer(dim, 2); 1063 *dim = mesh->dim; 1064 PetscFunctionReturn(0); 1065 } 1066 1067 #undef __FUNCT__ 1068 #define __FUNCT__ "DMPlexSetDimension" 1069 /*@ 1070 DMPlexSetDimension - Set the topological mesh dimension 1071 1072 Collective on mesh 1073 1074 Input Parameters: 1075 + mesh - The DMPlex 1076 - dim - The topological mesh dimension 1077 1078 Level: beginner 1079 1080 .seealso: DMPlexCreate() 1081 @*/ 1082 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1083 { 1084 DM_Plex *mesh = (DM_Plex*) dm->data; 1085 1086 PetscFunctionBegin; 1087 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1088 PetscValidLogicalCollectiveInt(dm, dim, 2); 1089 mesh->dim = dim; 1090 mesh->preallocCenterDim = dim; 1091 PetscFunctionReturn(0); 1092 } 1093 1094 #undef __FUNCT__ 1095 #define __FUNCT__ "DMPlexGetChart" 1096 /*@ 1097 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1098 1099 Not collective 1100 1101 Input Parameter: 1102 . mesh - The DMPlex 1103 1104 Output Parameters: 1105 + pStart - The first mesh point 1106 - pEnd - The upper bound for mesh points 1107 1108 Level: beginner 1109 1110 .seealso: DMPlexCreate(), DMPlexSetChart() 1111 @*/ 1112 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1113 { 1114 DM_Plex *mesh = (DM_Plex*) dm->data; 1115 PetscErrorCode ierr; 1116 1117 PetscFunctionBegin; 1118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1119 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1120 PetscFunctionReturn(0); 1121 } 1122 1123 #undef __FUNCT__ 1124 #define __FUNCT__ "DMPlexSetChart" 1125 /*@ 1126 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1127 1128 Not collective 1129 1130 Input Parameters: 1131 + mesh - The DMPlex 1132 . pStart - The first mesh point 1133 - pEnd - The upper bound for mesh points 1134 1135 Output Parameters: 1136 1137 Level: beginner 1138 1139 .seealso: DMPlexCreate(), DMPlexGetChart() 1140 @*/ 1141 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1142 { 1143 DM_Plex *mesh = (DM_Plex*) dm->data; 1144 PetscErrorCode ierr; 1145 1146 PetscFunctionBegin; 1147 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1148 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1149 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1150 PetscFunctionReturn(0); 1151 } 1152 1153 #undef __FUNCT__ 1154 #define __FUNCT__ "DMPlexGetConeSize" 1155 /*@ 1156 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1157 1158 Not collective 1159 1160 Input Parameters: 1161 + mesh - The DMPlex 1162 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1163 1164 Output Parameter: 1165 . size - The cone size for point p 1166 1167 Level: beginner 1168 1169 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1170 @*/ 1171 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1172 { 1173 DM_Plex *mesh = (DM_Plex*) dm->data; 1174 PetscErrorCode ierr; 1175 1176 PetscFunctionBegin; 1177 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1178 PetscValidPointer(size, 3); 1179 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1180 PetscFunctionReturn(0); 1181 } 1182 1183 #undef __FUNCT__ 1184 #define __FUNCT__ "DMPlexSetConeSize" 1185 /*@ 1186 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1187 1188 Not collective 1189 1190 Input Parameters: 1191 + mesh - The DMPlex 1192 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1193 - size - The cone size for point p 1194 1195 Output Parameter: 1196 1197 Note: 1198 This should be called after DMPlexSetChart(). 1199 1200 Level: beginner 1201 1202 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1203 @*/ 1204 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1205 { 1206 DM_Plex *mesh = (DM_Plex*) dm->data; 1207 PetscErrorCode ierr; 1208 1209 PetscFunctionBegin; 1210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1211 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1212 1213 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1214 PetscFunctionReturn(0); 1215 } 1216 1217 #undef __FUNCT__ 1218 #define __FUNCT__ "DMPlexGetCone" 1219 /*@C 1220 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1221 1222 Not collective 1223 1224 Input Parameters: 1225 + mesh - The DMPlex 1226 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1227 1228 Output Parameter: 1229 . cone - An array of points which are on the in-edges for point p 1230 1231 Level: beginner 1232 1233 Note: 1234 This routine is not available in Fortran. 1235 1236 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1237 @*/ 1238 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1239 { 1240 DM_Plex *mesh = (DM_Plex*) dm->data; 1241 PetscInt off; 1242 PetscErrorCode ierr; 1243 1244 PetscFunctionBegin; 1245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1246 PetscValidPointer(cone, 3); 1247 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1248 *cone = &mesh->cones[off]; 1249 PetscFunctionReturn(0); 1250 } 1251 1252 #undef __FUNCT__ 1253 #define __FUNCT__ "DMPlexSetCone" 1254 /*@ 1255 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1256 1257 Not collective 1258 1259 Input Parameters: 1260 + mesh - The DMPlex 1261 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1262 - cone - An array of points which are on the in-edges for point p 1263 1264 Output Parameter: 1265 1266 Note: 1267 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1268 1269 Level: beginner 1270 1271 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1272 @*/ 1273 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1274 { 1275 DM_Plex *mesh = (DM_Plex*) dm->data; 1276 PetscInt pStart, pEnd; 1277 PetscInt dof, off, c; 1278 PetscErrorCode ierr; 1279 1280 PetscFunctionBegin; 1281 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1282 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1283 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1284 if (dof) PetscValidPointer(cone, 3); 1285 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1286 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1287 for (c = 0; c < dof; ++c) { 1288 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1289 mesh->cones[off+c] = cone[c]; 1290 } 1291 PetscFunctionReturn(0); 1292 } 1293 1294 #undef __FUNCT__ 1295 #define __FUNCT__ "DMPlexGetConeOrientation" 1296 /*@C 1297 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1298 1299 Not collective 1300 1301 Input Parameters: 1302 + mesh - The DMPlex 1303 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1304 1305 Output Parameter: 1306 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1307 integer giving the prescription for cone traversal. If it is negative, the cone is 1308 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1309 the index of the cone point on which to start. 1310 1311 Level: beginner 1312 1313 Note: 1314 This routine is not available in Fortran. 1315 1316 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1317 @*/ 1318 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1319 { 1320 DM_Plex *mesh = (DM_Plex*) dm->data; 1321 PetscInt off; 1322 PetscErrorCode ierr; 1323 1324 PetscFunctionBegin; 1325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1326 #if defined(PETSC_USE_DEBUG) 1327 { 1328 PetscInt dof; 1329 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1330 if (dof) PetscValidPointer(coneOrientation, 3); 1331 } 1332 #endif 1333 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1334 1335 *coneOrientation = &mesh->coneOrientations[off]; 1336 PetscFunctionReturn(0); 1337 } 1338 1339 #undef __FUNCT__ 1340 #define __FUNCT__ "DMPlexSetConeOrientation" 1341 /*@ 1342 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1343 1344 Not collective 1345 1346 Input Parameters: 1347 + mesh - The DMPlex 1348 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1349 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1350 integer giving the prescription for cone traversal. If it is negative, the cone is 1351 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1352 the index of the cone point on which to start. 1353 1354 Output Parameter: 1355 1356 Note: 1357 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1358 1359 Level: beginner 1360 1361 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1362 @*/ 1363 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1364 { 1365 DM_Plex *mesh = (DM_Plex*) dm->data; 1366 PetscInt pStart, pEnd; 1367 PetscInt dof, off, c; 1368 PetscErrorCode ierr; 1369 1370 PetscFunctionBegin; 1371 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1372 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1373 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1374 if (dof) PetscValidPointer(coneOrientation, 3); 1375 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1376 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1377 for (c = 0; c < dof; ++c) { 1378 PetscInt cdof, o = coneOrientation[c]; 1379 1380 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1381 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1382 mesh->coneOrientations[off+c] = o; 1383 } 1384 PetscFunctionReturn(0); 1385 } 1386 1387 #undef __FUNCT__ 1388 #define __FUNCT__ "DMPlexInsertCone" 1389 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1390 { 1391 DM_Plex *mesh = (DM_Plex*) dm->data; 1392 PetscInt pStart, pEnd; 1393 PetscInt dof, off; 1394 PetscErrorCode ierr; 1395 1396 PetscFunctionBegin; 1397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1398 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1399 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1400 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1401 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1402 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1403 if (conePos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1404 mesh->cones[off+conePos] = conePoint; 1405 PetscFunctionReturn(0); 1406 } 1407 1408 #undef __FUNCT__ 1409 #define __FUNCT__ "DMPlexGetSupportSize" 1410 /*@ 1411 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1412 1413 Not collective 1414 1415 Input Parameters: 1416 + mesh - The DMPlex 1417 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1418 1419 Output Parameter: 1420 . size - The support size for point p 1421 1422 Level: beginner 1423 1424 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1425 @*/ 1426 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1427 { 1428 DM_Plex *mesh = (DM_Plex*) dm->data; 1429 PetscErrorCode ierr; 1430 1431 PetscFunctionBegin; 1432 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1433 PetscValidPointer(size, 3); 1434 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1435 PetscFunctionReturn(0); 1436 } 1437 1438 #undef __FUNCT__ 1439 #define __FUNCT__ "DMPlexSetSupportSize" 1440 /*@ 1441 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1442 1443 Not collective 1444 1445 Input Parameters: 1446 + mesh - The DMPlex 1447 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1448 - size - The support size for point p 1449 1450 Output Parameter: 1451 1452 Note: 1453 This should be called after DMPlexSetChart(). 1454 1455 Level: beginner 1456 1457 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1458 @*/ 1459 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1460 { 1461 DM_Plex *mesh = (DM_Plex*) dm->data; 1462 PetscErrorCode ierr; 1463 1464 PetscFunctionBegin; 1465 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1466 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1467 1468 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1469 PetscFunctionReturn(0); 1470 } 1471 1472 #undef __FUNCT__ 1473 #define __FUNCT__ "DMPlexGetSupport" 1474 /*@C 1475 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1476 1477 Not collective 1478 1479 Input Parameters: 1480 + mesh - The DMPlex 1481 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1482 1483 Output Parameter: 1484 . support - An array of points which are on the out-edges for point p 1485 1486 Level: beginner 1487 1488 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1489 @*/ 1490 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1491 { 1492 DM_Plex *mesh = (DM_Plex*) dm->data; 1493 PetscInt off; 1494 PetscErrorCode ierr; 1495 1496 PetscFunctionBegin; 1497 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1498 PetscValidPointer(support, 3); 1499 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1500 *support = &mesh->supports[off]; 1501 PetscFunctionReturn(0); 1502 } 1503 1504 #undef __FUNCT__ 1505 #define __FUNCT__ "DMPlexSetSupport" 1506 /*@ 1507 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1508 1509 Not collective 1510 1511 Input Parameters: 1512 + mesh - The DMPlex 1513 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1514 - support - An array of points which are on the in-edges for point p 1515 1516 Output Parameter: 1517 1518 Note: 1519 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1520 1521 Level: beginner 1522 1523 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1524 @*/ 1525 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1526 { 1527 DM_Plex *mesh = (DM_Plex*) dm->data; 1528 PetscInt pStart, pEnd; 1529 PetscInt dof, off, c; 1530 PetscErrorCode ierr; 1531 1532 PetscFunctionBegin; 1533 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1534 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1535 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1536 if (dof) PetscValidPointer(support, 3); 1537 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1538 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1539 for (c = 0; c < dof; ++c) { 1540 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1541 mesh->supports[off+c] = support[c]; 1542 } 1543 PetscFunctionReturn(0); 1544 } 1545 1546 #undef __FUNCT__ 1547 #define __FUNCT__ "DMPlexInsertSupport" 1548 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1549 { 1550 DM_Plex *mesh = (DM_Plex*) dm->data; 1551 PetscInt pStart, pEnd; 1552 PetscInt dof, off; 1553 PetscErrorCode ierr; 1554 1555 PetscFunctionBegin; 1556 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1557 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1558 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1559 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1560 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1561 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1562 if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1563 mesh->supports[off+supportPos] = supportPoint; 1564 PetscFunctionReturn(0); 1565 } 1566 1567 #undef __FUNCT__ 1568 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1569 /*@C 1570 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1571 1572 Not collective 1573 1574 Input Parameters: 1575 + mesh - The DMPlex 1576 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1577 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1578 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1579 1580 Output Parameters: 1581 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1582 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1583 1584 Note: 1585 If using internal storage (points is NULL on input), each call overwrites the last output. 1586 1587 Level: beginner 1588 1589 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1590 @*/ 1591 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1592 { 1593 DM_Plex *mesh = (DM_Plex*) dm->data; 1594 PetscInt *closure, *fifo; 1595 const PetscInt *tmp = NULL, *tmpO = NULL; 1596 PetscInt tmpSize, t; 1597 PetscInt depth = 0, maxSize; 1598 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1599 PetscErrorCode ierr; 1600 1601 PetscFunctionBegin; 1602 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1603 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1604 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1605 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1606 if (*points) { 1607 closure = *points; 1608 } else { 1609 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1610 } 1611 closure[0] = p; closure[1] = 0; 1612 /* This is only 1-level */ 1613 if (useCone) { 1614 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1615 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1616 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1617 } else { 1618 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1619 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1620 } 1621 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1622 const PetscInt cp = tmp[t]; 1623 const PetscInt co = tmpO ? tmpO[t] : 0; 1624 1625 closure[closureSize] = cp; 1626 closure[closureSize+1] = co; 1627 fifo[fifoSize] = cp; 1628 fifo[fifoSize+1] = co; 1629 } 1630 while (fifoSize - fifoStart) { 1631 const PetscInt q = fifo[fifoStart]; 1632 const PetscInt o = fifo[fifoStart+1]; 1633 const PetscInt rev = o >= 0 ? 0 : 1; 1634 const PetscInt off = rev ? -(o+1) : o; 1635 1636 if (useCone) { 1637 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1638 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1639 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1640 } else { 1641 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1642 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1643 tmpO = NULL; 1644 } 1645 for (t = 0; t < tmpSize; ++t) { 1646 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1647 const PetscInt cp = tmp[i]; 1648 /* Must propogate orientation */ 1649 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1650 PetscInt c; 1651 1652 /* Check for duplicate */ 1653 for (c = 0; c < closureSize; c += 2) { 1654 if (closure[c] == cp) break; 1655 } 1656 if (c == closureSize) { 1657 closure[closureSize] = cp; 1658 closure[closureSize+1] = co; 1659 fifo[fifoSize] = cp; 1660 fifo[fifoSize+1] = co; 1661 closureSize += 2; 1662 fifoSize += 2; 1663 } 1664 } 1665 fifoStart += 2; 1666 } 1667 if (numPoints) *numPoints = closureSize/2; 1668 if (points) *points = closure; 1669 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1670 PetscFunctionReturn(0); 1671 } 1672 1673 #undef __FUNCT__ 1674 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1675 /*@C 1676 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1677 1678 Not collective 1679 1680 Input Parameters: 1681 + mesh - The DMPlex 1682 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1683 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1684 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1685 1686 Output Parameters: 1687 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1688 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1689 1690 Note: 1691 If not using internal storage (points is not NULL on input), this call is unnecessary 1692 1693 Level: beginner 1694 1695 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1696 @*/ 1697 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1698 { 1699 PetscErrorCode ierr; 1700 1701 PetscFunctionBegin; 1702 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1703 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1704 PetscFunctionReturn(0); 1705 } 1706 1707 #undef __FUNCT__ 1708 #define __FUNCT__ "DMPlexGetMaxSizes" 1709 /*@ 1710 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1711 1712 Not collective 1713 1714 Input Parameter: 1715 . mesh - The DMPlex 1716 1717 Output Parameters: 1718 + maxConeSize - The maximum number of in-edges 1719 - maxSupportSize - The maximum number of out-edges 1720 1721 Level: beginner 1722 1723 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1724 @*/ 1725 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1726 { 1727 DM_Plex *mesh = (DM_Plex*) dm->data; 1728 1729 PetscFunctionBegin; 1730 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1731 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1732 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1733 PetscFunctionReturn(0); 1734 } 1735 1736 #undef __FUNCT__ 1737 #define __FUNCT__ "DMSetUp_Plex" 1738 PetscErrorCode DMSetUp_Plex(DM dm) 1739 { 1740 DM_Plex *mesh = (DM_Plex*) dm->data; 1741 PetscInt size; 1742 PetscErrorCode ierr; 1743 1744 PetscFunctionBegin; 1745 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1746 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1747 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1748 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1749 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1750 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1751 if (mesh->maxSupportSize) { 1752 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1753 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1754 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1755 } 1756 PetscFunctionReturn(0); 1757 } 1758 1759 #undef __FUNCT__ 1760 #define __FUNCT__ "DMCreateSubDM_Plex" 1761 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1762 { 1763 PetscSection section, sectionGlobal; 1764 PetscInt *subIndices; 1765 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1766 PetscErrorCode ierr; 1767 1768 PetscFunctionBegin; 1769 if (!numFields) PetscFunctionReturn(0); 1770 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1771 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1772 if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1773 if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1774 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1775 if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1776 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1777 for (p = pStart; p < pEnd; ++p) { 1778 PetscInt gdof; 1779 1780 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1781 if (gdof > 0) { 1782 for (f = 0; f < numFields; ++f) { 1783 PetscInt fdof, fcdof; 1784 1785 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1786 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1787 subSize += fdof-fcdof; 1788 } 1789 } 1790 } 1791 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1792 for (p = pStart; p < pEnd; ++p) { 1793 PetscInt gdof, goff; 1794 1795 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1796 if (gdof > 0) { 1797 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1798 for (f = 0; f < numFields; ++f) { 1799 PetscInt fdof, fcdof, fc, f2, poff = 0; 1800 1801 /* Can get rid of this loop by storing field information in the global section */ 1802 for (f2 = 0; f2 < fields[f]; ++f2) { 1803 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1804 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1805 poff += fdof-fcdof; 1806 } 1807 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1808 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1809 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1810 subIndices[subOff] = goff+poff+fc; 1811 } 1812 } 1813 } 1814 } 1815 if (is) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1816 if (subdm) { 1817 PetscSection subsection; 1818 PetscBool haveNull = PETSC_FALSE; 1819 PetscInt f, nf = 0; 1820 1821 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1822 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1823 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1824 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 1825 for (f = 0; f < numFields; ++f) { 1826 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1827 if ((*subdm)->nullspaceConstructors[f]) { 1828 haveNull = PETSC_TRUE; 1829 nf = f; 1830 } 1831 } 1832 if (haveNull) { 1833 MatNullSpace nullSpace; 1834 1835 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1836 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1837 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1838 } 1839 if (dm->fields) { 1840 if (nF != dm->numFields) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1841 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1842 for (f = 0; f < numFields; ++f) { 1843 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1844 } 1845 if (numFields == 1) { 1846 MatNullSpace space; 1847 Mat pmat; 1848 1849 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1850 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1851 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1852 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1853 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1854 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1855 } 1856 } 1857 } 1858 PetscFunctionReturn(0); 1859 } 1860 1861 #undef __FUNCT__ 1862 #define __FUNCT__ "DMPlexSymmetrize" 1863 /*@ 1864 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1865 1866 Not collective 1867 1868 Input Parameter: 1869 . mesh - The DMPlex 1870 1871 Output Parameter: 1872 1873 Note: 1874 This should be called after all calls to DMPlexSetCone() 1875 1876 Level: beginner 1877 1878 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1879 @*/ 1880 PetscErrorCode DMPlexSymmetrize(DM dm) 1881 { 1882 DM_Plex *mesh = (DM_Plex*) dm->data; 1883 PetscInt *offsets; 1884 PetscInt supportSize; 1885 PetscInt pStart, pEnd, p; 1886 PetscErrorCode ierr; 1887 1888 PetscFunctionBegin; 1889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1890 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1891 /* Calculate support sizes */ 1892 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1893 for (p = pStart; p < pEnd; ++p) { 1894 PetscInt dof, off, c; 1895 1896 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1897 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1898 for (c = off; c < off+dof; ++c) { 1899 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1900 } 1901 } 1902 for (p = pStart; p < pEnd; ++p) { 1903 PetscInt dof; 1904 1905 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1906 1907 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1908 } 1909 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1910 /* Calculate supports */ 1911 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1912 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1913 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1914 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1915 for (p = pStart; p < pEnd; ++p) { 1916 PetscInt dof, off, c; 1917 1918 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1919 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1920 for (c = off; c < off+dof; ++c) { 1921 const PetscInt q = mesh->cones[c]; 1922 PetscInt offS; 1923 1924 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1925 1926 mesh->supports[offS+offsets[q]] = p; 1927 ++offsets[q]; 1928 } 1929 } 1930 ierr = PetscFree(offsets);CHKERRQ(ierr); 1931 PetscFunctionReturn(0); 1932 } 1933 1934 #undef __FUNCT__ 1935 #define __FUNCT__ "DMPlexSetDepth_Private" 1936 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1937 { 1938 PetscInt d; 1939 PetscErrorCode ierr; 1940 1941 PetscFunctionBegin; 1942 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1943 if (d < 0) { 1944 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1945 const PetscInt *cone = NULL; 1946 PetscInt dCone; 1947 1948 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1949 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1950 d = dCone+1; 1951 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1952 } 1953 *depth = d; 1954 PetscFunctionReturn(0); 1955 } 1956 1957 #undef __FUNCT__ 1958 #define __FUNCT__ "DMPlexStratify" 1959 /*@ 1960 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 1961 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 1962 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 1963 the DAG. 1964 1965 Not collective 1966 1967 Input Parameter: 1968 . mesh - The DMPlex 1969 1970 Output Parameter: 1971 1972 Notes: 1973 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 1974 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 1975 1976 This should be called after all calls to DMPlexSymmetrize() 1977 1978 Level: beginner 1979 1980 .seealso: DMPlexCreate(), DMPlexSymmetrize() 1981 @*/ 1982 PetscErrorCode DMPlexStratify(DM dm) 1983 { 1984 DM_Plex *mesh = (DM_Plex*) dm->data; 1985 PetscInt pStart, pEnd, p; 1986 PetscInt numRoots = 0, numLeaves = 0; 1987 PetscErrorCode ierr; 1988 1989 PetscFunctionBegin; 1990 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1991 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1992 /* Calculate depth */ 1993 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1994 /* Initialize roots and count leaves */ 1995 for (p = pStart; p < pEnd; ++p) { 1996 PetscInt coneSize, supportSize; 1997 1998 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1999 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2000 if (!coneSize && supportSize) { 2001 ++numRoots; 2002 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2003 } else if (!supportSize && coneSize) { 2004 ++numLeaves; 2005 } else if (!supportSize && !coneSize) { 2006 /* Isolated points */ 2007 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2008 } 2009 } 2010 if (numRoots + numLeaves == (pEnd - pStart)) { 2011 for (p = pStart; p < pEnd; ++p) { 2012 PetscInt coneSize, supportSize; 2013 2014 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2015 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2016 if (!supportSize && coneSize) { 2017 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2018 } 2019 } 2020 } else { 2021 /* This might be slow since lookup is not fast */ 2022 for (p = pStart; p < pEnd; ++p) { 2023 PetscInt depth; 2024 2025 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2026 } 2027 } 2028 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2029 PetscFunctionReturn(0); 2030 } 2031 2032 #undef __FUNCT__ 2033 #define __FUNCT__ "DMPlexGetJoin" 2034 /*@C 2035 DMPlexGetJoin - Get an array for the join of the set of points 2036 2037 Not Collective 2038 2039 Input Parameters: 2040 + dm - The DMPlex object 2041 . numPoints - The number of input points for the join 2042 - points - The input points 2043 2044 Output Parameters: 2045 + numCoveredPoints - The number of points in the join 2046 - coveredPoints - The points in the join 2047 2048 Level: intermediate 2049 2050 Note: Currently, this is restricted to a single level join 2051 2052 .keywords: mesh 2053 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2054 @*/ 2055 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2056 { 2057 DM_Plex *mesh = (DM_Plex*) dm->data; 2058 PetscInt *join[2]; 2059 PetscInt joinSize, i = 0; 2060 PetscInt dof, off, p, c, m; 2061 PetscErrorCode ierr; 2062 2063 PetscFunctionBegin; 2064 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2065 PetscValidPointer(points, 2); 2066 PetscValidPointer(numCoveredPoints, 3); 2067 PetscValidPointer(coveredPoints, 4); 2068 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2069 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2070 /* Copy in support of first point */ 2071 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2072 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2073 for (joinSize = 0; joinSize < dof; ++joinSize) { 2074 join[i][joinSize] = mesh->supports[off+joinSize]; 2075 } 2076 /* Check each successive support */ 2077 for (p = 1; p < numPoints; ++p) { 2078 PetscInt newJoinSize = 0; 2079 2080 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2081 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2082 for (c = 0; c < dof; ++c) { 2083 const PetscInt point = mesh->supports[off+c]; 2084 2085 for (m = 0; m < joinSize; ++m) { 2086 if (point == join[i][m]) { 2087 join[1-i][newJoinSize++] = point; 2088 break; 2089 } 2090 } 2091 } 2092 joinSize = newJoinSize; 2093 i = 1-i; 2094 } 2095 *numCoveredPoints = joinSize; 2096 *coveredPoints = join[i]; 2097 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2098 PetscFunctionReturn(0); 2099 } 2100 2101 #undef __FUNCT__ 2102 #define __FUNCT__ "DMPlexRestoreJoin" 2103 /*@C 2104 DMPlexRestoreJoin - Restore an array for the join of the set of points 2105 2106 Not Collective 2107 2108 Input Parameters: 2109 + dm - The DMPlex object 2110 . numPoints - The number of input points for the join 2111 - points - The input points 2112 2113 Output Parameters: 2114 + numCoveredPoints - The number of points in the join 2115 - coveredPoints - The points in the join 2116 2117 Level: intermediate 2118 2119 .keywords: mesh 2120 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2121 @*/ 2122 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2123 { 2124 PetscErrorCode ierr; 2125 2126 PetscFunctionBegin; 2127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2128 PetscValidPointer(coveredPoints, 4); 2129 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2130 PetscFunctionReturn(0); 2131 } 2132 2133 #undef __FUNCT__ 2134 #define __FUNCT__ "DMPlexGetFullJoin" 2135 /*@C 2136 DMPlexGetFullJoin - Get an array for the join of the set of points 2137 2138 Not Collective 2139 2140 Input Parameters: 2141 + dm - The DMPlex object 2142 . numPoints - The number of input points for the join 2143 - points - The input points 2144 2145 Output Parameters: 2146 + numCoveredPoints - The number of points in the join 2147 - coveredPoints - The points in the join 2148 2149 Level: intermediate 2150 2151 .keywords: mesh 2152 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2153 @*/ 2154 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2155 { 2156 DM_Plex *mesh = (DM_Plex*) dm->data; 2157 PetscInt *offsets, **closures; 2158 PetscInt *join[2]; 2159 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2160 PetscInt p, d, c, m; 2161 PetscErrorCode ierr; 2162 2163 PetscFunctionBegin; 2164 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2165 PetscValidPointer(points, 2); 2166 PetscValidPointer(numCoveredPoints, 3); 2167 PetscValidPointer(coveredPoints, 4); 2168 2169 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2170 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2171 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2172 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2173 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2174 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2175 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2176 2177 for (p = 0; p < numPoints; ++p) { 2178 PetscInt closureSize; 2179 2180 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2181 2182 offsets[p*(depth+2)+0] = 0; 2183 for (d = 0; d < depth+1; ++d) { 2184 PetscInt pStart, pEnd, i; 2185 2186 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2187 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2188 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2189 offsets[p*(depth+2)+d+1] = i; 2190 break; 2191 } 2192 } 2193 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2194 } 2195 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2196 } 2197 for (d = 0; d < depth+1; ++d) { 2198 PetscInt dof; 2199 2200 /* Copy in support of first point */ 2201 dof = offsets[d+1] - offsets[d]; 2202 for (joinSize = 0; joinSize < dof; ++joinSize) { 2203 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2204 } 2205 /* Check each successive cone */ 2206 for (p = 1; p < numPoints && joinSize; ++p) { 2207 PetscInt newJoinSize = 0; 2208 2209 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2210 for (c = 0; c < dof; ++c) { 2211 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2212 2213 for (m = 0; m < joinSize; ++m) { 2214 if (point == join[i][m]) { 2215 join[1-i][newJoinSize++] = point; 2216 break; 2217 } 2218 } 2219 } 2220 joinSize = newJoinSize; 2221 i = 1-i; 2222 } 2223 if (joinSize) break; 2224 } 2225 *numCoveredPoints = joinSize; 2226 *coveredPoints = join[i]; 2227 for (p = 0; p < numPoints; ++p) { 2228 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2229 } 2230 ierr = PetscFree(closures);CHKERRQ(ierr); 2231 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2232 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2233 PetscFunctionReturn(0); 2234 } 2235 2236 #undef __FUNCT__ 2237 #define __FUNCT__ "DMPlexGetMeet" 2238 /*@C 2239 DMPlexGetMeet - Get an array for the meet of the set of points 2240 2241 Not Collective 2242 2243 Input Parameters: 2244 + dm - The DMPlex object 2245 . numPoints - The number of input points for the meet 2246 - points - The input points 2247 2248 Output Parameters: 2249 + numCoveredPoints - The number of points in the meet 2250 - coveredPoints - The points in the meet 2251 2252 Level: intermediate 2253 2254 Note: Currently, this is restricted to a single level meet 2255 2256 .keywords: mesh 2257 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2258 @*/ 2259 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2260 { 2261 DM_Plex *mesh = (DM_Plex*) dm->data; 2262 PetscInt *meet[2]; 2263 PetscInt meetSize, i = 0; 2264 PetscInt dof, off, p, c, m; 2265 PetscErrorCode ierr; 2266 2267 PetscFunctionBegin; 2268 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2269 PetscValidPointer(points, 2); 2270 PetscValidPointer(numCoveringPoints, 3); 2271 PetscValidPointer(coveringPoints, 4); 2272 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2273 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2274 /* Copy in cone of first point */ 2275 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2276 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2277 for (meetSize = 0; meetSize < dof; ++meetSize) { 2278 meet[i][meetSize] = mesh->cones[off+meetSize]; 2279 } 2280 /* Check each successive cone */ 2281 for (p = 1; p < numPoints; ++p) { 2282 PetscInt newMeetSize = 0; 2283 2284 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2285 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2286 for (c = 0; c < dof; ++c) { 2287 const PetscInt point = mesh->cones[off+c]; 2288 2289 for (m = 0; m < meetSize; ++m) { 2290 if (point == meet[i][m]) { 2291 meet[1-i][newMeetSize++] = point; 2292 break; 2293 } 2294 } 2295 } 2296 meetSize = newMeetSize; 2297 i = 1-i; 2298 } 2299 *numCoveringPoints = meetSize; 2300 *coveringPoints = meet[i]; 2301 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2302 PetscFunctionReturn(0); 2303 } 2304 2305 #undef __FUNCT__ 2306 #define __FUNCT__ "DMPlexRestoreMeet" 2307 /*@C 2308 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2309 2310 Not Collective 2311 2312 Input Parameters: 2313 + dm - The DMPlex object 2314 . numPoints - The number of input points for the meet 2315 - points - The input points 2316 2317 Output Parameters: 2318 + numCoveredPoints - The number of points in the meet 2319 - coveredPoints - The points in the meet 2320 2321 Level: intermediate 2322 2323 .keywords: mesh 2324 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2325 @*/ 2326 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2327 { 2328 PetscErrorCode ierr; 2329 2330 PetscFunctionBegin; 2331 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2332 PetscValidPointer(coveredPoints, 4); 2333 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2334 PetscFunctionReturn(0); 2335 } 2336 2337 #undef __FUNCT__ 2338 #define __FUNCT__ "DMPlexGetFullMeet" 2339 /*@C 2340 DMPlexGetFullMeet - Get an array for the meet of the set of points 2341 2342 Not Collective 2343 2344 Input Parameters: 2345 + dm - The DMPlex object 2346 . numPoints - The number of input points for the meet 2347 - points - The input points 2348 2349 Output Parameters: 2350 + numCoveredPoints - The number of points in the meet 2351 - coveredPoints - The points in the meet 2352 2353 Level: intermediate 2354 2355 .keywords: mesh 2356 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2357 @*/ 2358 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2359 { 2360 DM_Plex *mesh = (DM_Plex*) dm->data; 2361 PetscInt *offsets, **closures; 2362 PetscInt *meet[2]; 2363 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2364 PetscInt p, h, c, m; 2365 PetscErrorCode ierr; 2366 2367 PetscFunctionBegin; 2368 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2369 PetscValidPointer(points, 2); 2370 PetscValidPointer(numCoveredPoints, 3); 2371 PetscValidPointer(coveredPoints, 4); 2372 2373 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2374 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2375 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2376 maxSize = PetscPowInt(mesh->maxConeSize,height); 2377 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2378 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2379 2380 for (p = 0; p < numPoints; ++p) { 2381 PetscInt closureSize; 2382 2383 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2384 2385 offsets[p*(height+2)+0] = 0; 2386 for (h = 0; h < height+1; ++h) { 2387 PetscInt pStart, pEnd, i; 2388 2389 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2390 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2391 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2392 offsets[p*(height+2)+h+1] = i; 2393 break; 2394 } 2395 } 2396 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2397 } 2398 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2399 } 2400 for (h = 0; h < height+1; ++h) { 2401 PetscInt dof; 2402 2403 /* Copy in cone of first point */ 2404 dof = offsets[h+1] - offsets[h]; 2405 for (meetSize = 0; meetSize < dof; ++meetSize) { 2406 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2407 } 2408 /* Check each successive cone */ 2409 for (p = 1; p < numPoints && meetSize; ++p) { 2410 PetscInt newMeetSize = 0; 2411 2412 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2413 for (c = 0; c < dof; ++c) { 2414 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2415 2416 for (m = 0; m < meetSize; ++m) { 2417 if (point == meet[i][m]) { 2418 meet[1-i][newMeetSize++] = point; 2419 break; 2420 } 2421 } 2422 } 2423 meetSize = newMeetSize; 2424 i = 1-i; 2425 } 2426 if (meetSize) break; 2427 } 2428 *numCoveredPoints = meetSize; 2429 *coveredPoints = meet[i]; 2430 for (p = 0; p < numPoints; ++p) { 2431 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2432 } 2433 ierr = PetscFree(closures);CHKERRQ(ierr); 2434 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2435 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2436 PetscFunctionReturn(0); 2437 } 2438 2439 #undef __FUNCT__ 2440 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2441 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2442 { 2443 MPI_Comm comm; 2444 PetscInt cellDim; 2445 PetscErrorCode ierr; 2446 2447 PetscFunctionBegin; 2448 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2449 PetscValidPointer(numFaceVertices,3); 2450 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2451 switch (cellDim) { 2452 case 0: 2453 *numFaceVertices = 0; 2454 break; 2455 case 1: 2456 *numFaceVertices = 1; 2457 break; 2458 case 2: 2459 switch (numCorners) { 2460 case 3: /* triangle */ 2461 *numFaceVertices = 2; /* Edge has 2 vertices */ 2462 break; 2463 case 4: /* quadrilateral */ 2464 *numFaceVertices = 2; /* Edge has 2 vertices */ 2465 break; 2466 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2467 *numFaceVertices = 3; /* Edge has 3 vertices */ 2468 break; 2469 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2470 *numFaceVertices = 3; /* Edge has 3 vertices */ 2471 break; 2472 default: 2473 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2474 } 2475 break; 2476 case 3: 2477 switch (numCorners) { 2478 case 4: /* tetradehdron */ 2479 *numFaceVertices = 3; /* Face has 3 vertices */ 2480 break; 2481 case 6: /* tet cohesive cells */ 2482 *numFaceVertices = 4; /* Face has 4 vertices */ 2483 break; 2484 case 8: /* hexahedron */ 2485 *numFaceVertices = 4; /* Face has 4 vertices */ 2486 break; 2487 case 9: /* tet cohesive Lagrange cells */ 2488 *numFaceVertices = 6; /* Face has 6 vertices */ 2489 break; 2490 case 10: /* quadratic tetrahedron */ 2491 *numFaceVertices = 6; /* Face has 6 vertices */ 2492 break; 2493 case 12: /* hex cohesive Lagrange cells */ 2494 *numFaceVertices = 6; /* Face has 6 vertices */ 2495 break; 2496 case 18: /* quadratic tet cohesive Lagrange cells */ 2497 *numFaceVertices = 6; /* Face has 6 vertices */ 2498 break; 2499 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2500 *numFaceVertices = 9; /* Face has 9 vertices */ 2501 break; 2502 default: 2503 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2504 } 2505 break; 2506 default: 2507 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2508 } 2509 PetscFunctionReturn(0); 2510 } 2511 2512 #undef __FUNCT__ 2513 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2514 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2515 { 2516 const PetscInt maxFaceCases = 30; 2517 PetscInt numFaceCases = 0; 2518 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2519 PetscInt *off, *adj; 2520 PetscInt *neighborCells, *tmpClosure; 2521 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2522 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2523 PetscErrorCode ierr; 2524 2525 PetscFunctionBegin; 2526 /* For parallel partitioning, I think you have to communicate supports */ 2527 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2528 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2529 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2530 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2531 if (cEnd - cStart == 0) { 2532 if (numVertices) *numVertices = 0; 2533 if (offsets) *offsets = NULL; 2534 if (adjacency) *adjacency = NULL; 2535 PetscFunctionReturn(0); 2536 } 2537 numCells = cEnd - cStart; 2538 /* Setup face recognition */ 2539 if (depth == 1) { 2540 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 */ 2541 2542 for (c = cStart; c < cEnd; ++c) { 2543 PetscInt corners; 2544 2545 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2546 if (!cornersSeen[corners]) { 2547 PetscInt nFV; 2548 2549 if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2550 cornersSeen[corners] = 1; 2551 2552 ierr = DMPlexGetNumFaceVertices_Internal(dm, corners, &nFV);CHKERRQ(ierr); 2553 2554 numFaceVertices[numFaceCases++] = nFV; 2555 } 2556 } 2557 } 2558 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2559 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2560 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2561 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2562 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2563 /* Count neighboring cells */ 2564 for (cell = cStart; cell < cEnd; ++cell) { 2565 PetscInt numNeighbors = maxNeighbors, n; 2566 2567 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2568 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2569 for (n = 0; n < numNeighbors; ++n) { 2570 PetscInt cellPair[2]; 2571 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2572 PetscInt meetSize = 0; 2573 const PetscInt *meet = NULL; 2574 2575 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2576 if (cellPair[0] == cellPair[1]) continue; 2577 if (!found) { 2578 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2579 if (meetSize) { 2580 PetscInt f; 2581 2582 for (f = 0; f < numFaceCases; ++f) { 2583 if (numFaceVertices[f] == meetSize) { 2584 found = PETSC_TRUE; 2585 break; 2586 } 2587 } 2588 } 2589 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2590 } 2591 if (found) ++off[cell-cStart+1]; 2592 } 2593 } 2594 /* Prefix sum */ 2595 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2596 2597 if (adjacency) { 2598 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2599 /* Get neighboring cells */ 2600 for (cell = cStart; cell < cEnd; ++cell) { 2601 PetscInt numNeighbors = maxNeighbors, n; 2602 PetscInt cellOffset = 0; 2603 2604 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2605 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2606 for (n = 0; n < numNeighbors; ++n) { 2607 PetscInt cellPair[2]; 2608 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2609 PetscInt meetSize = 0; 2610 const PetscInt *meet = NULL; 2611 2612 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2613 if (cellPair[0] == cellPair[1]) continue; 2614 if (!found) { 2615 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2616 if (meetSize) { 2617 PetscInt f; 2618 2619 for (f = 0; f < numFaceCases; ++f) { 2620 if (numFaceVertices[f] == meetSize) { 2621 found = PETSC_TRUE; 2622 break; 2623 } 2624 } 2625 } 2626 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2627 } 2628 if (found) { 2629 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2630 ++cellOffset; 2631 } 2632 } 2633 } 2634 } 2635 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2636 if (numVertices) *numVertices = numCells; 2637 if (offsets) *offsets = off; 2638 if (adjacency) *adjacency = adj; 2639 PetscFunctionReturn(0); 2640 } 2641 2642 #if defined(PETSC_HAVE_CHACO) 2643 #if defined(PETSC_HAVE_UNISTD_H) 2644 #include <unistd.h> 2645 #endif 2646 /* Chaco does not have an include file */ 2647 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2648 float *ewgts, float *x, float *y, float *z, char *outassignname, 2649 char *outfilename, short *assignment, int architecture, int ndims_tot, 2650 int mesh_dims[3], double *goal, int global_method, int local_method, 2651 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2652 2653 extern int FREE_GRAPH; 2654 2655 #undef __FUNCT__ 2656 #define __FUNCT__ "DMPlexPartition_Chaco" 2657 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2658 { 2659 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2660 MPI_Comm comm; 2661 int nvtxs = numVertices; /* number of vertices in full graph */ 2662 int *vwgts = NULL; /* weights for all vertices */ 2663 float *ewgts = NULL; /* weights for all edges */ 2664 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2665 char *outassignname = NULL; /* name of assignment output file */ 2666 char *outfilename = NULL; /* output file name */ 2667 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2668 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2669 int mesh_dims[3]; /* dimensions of mesh of processors */ 2670 double *goal = NULL; /* desired set sizes for each set */ 2671 int global_method = 1; /* global partitioning algorithm */ 2672 int local_method = 1; /* local partitioning algorithm */ 2673 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2674 int vmax = 200; /* how many vertices to coarsen down to? */ 2675 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2676 double eigtol = 0.001; /* tolerance on eigenvectors */ 2677 long seed = 123636512; /* for random graph mutations */ 2678 short int *assignment; /* Output partition */ 2679 int fd_stdout, fd_pipe[2]; 2680 PetscInt *points; 2681 PetscMPIInt commSize; 2682 int i, v, p; 2683 PetscErrorCode ierr; 2684 2685 PetscFunctionBegin; 2686 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2687 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2688 if (!numVertices) { 2689 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2690 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2691 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2692 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2693 PetscFunctionReturn(0); 2694 } 2695 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2696 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2697 2698 if (global_method == INERTIAL_METHOD) { 2699 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2700 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2701 } 2702 mesh_dims[0] = commSize; 2703 mesh_dims[1] = 1; 2704 mesh_dims[2] = 1; 2705 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2706 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2707 /* TODO: check error codes for UNIX calls */ 2708 #if defined(PETSC_HAVE_UNISTD_H) 2709 { 2710 int piperet; 2711 piperet = pipe(fd_pipe); 2712 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2713 fd_stdout = dup(1); 2714 close(1); 2715 dup2(fd_pipe[1], 1); 2716 } 2717 #endif 2718 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2719 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2720 vmax, ndims, eigtol, seed); 2721 #if defined(PETSC_HAVE_UNISTD_H) 2722 { 2723 char msgLog[10000]; 2724 int count; 2725 2726 fflush(stdout); 2727 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2728 if (count < 0) count = 0; 2729 msgLog[count] = 0; 2730 close(1); 2731 dup2(fd_stdout, 1); 2732 close(fd_stdout); 2733 close(fd_pipe[0]); 2734 close(fd_pipe[1]); 2735 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2736 } 2737 #endif 2738 /* Convert to PetscSection+IS */ 2739 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2740 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2741 for (v = 0; v < nvtxs; ++v) { 2742 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2743 } 2744 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2745 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2746 for (p = 0, i = 0; p < commSize; ++p) { 2747 for (v = 0; v < nvtxs; ++v) { 2748 if (assignment[v] == p) points[i++] = v; 2749 } 2750 } 2751 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2752 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2753 if (global_method == INERTIAL_METHOD) { 2754 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2755 } 2756 ierr = PetscFree(assignment);CHKERRQ(ierr); 2757 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2758 PetscFunctionReturn(0); 2759 } 2760 #endif 2761 2762 #if defined(PETSC_HAVE_PARMETIS) 2763 #undef __FUNCT__ 2764 #define __FUNCT__ "DMPlexPartition_ParMetis" 2765 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2766 { 2767 PetscFunctionBegin; 2768 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ParMetis not yet supported"); 2769 PetscFunctionReturn(0); 2770 } 2771 #endif 2772 2773 #undef __FUNCT__ 2774 #define __FUNCT__ "DMPlexEnlargePartition" 2775 /* Expand the partition by BFS on the adjacency graph */ 2776 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2777 { 2778 PetscHashI h; 2779 const PetscInt *points; 2780 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2781 PetscInt pStart, pEnd, part, q; 2782 PetscErrorCode ierr; 2783 2784 PetscFunctionBegin; 2785 PetscHashICreate(h); 2786 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2787 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2788 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2789 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2790 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2791 for (part = pStart; part < pEnd; ++part) { 2792 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2793 2794 PetscHashIClear(h); 2795 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2796 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2797 /* Add all existing points to h */ 2798 for (p = 0; p < numPoints; ++p) { 2799 const PetscInt point = points[off+p]; 2800 PetscHashIAdd(h, point, 1); 2801 } 2802 PetscHashISize(h, nP); 2803 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2804 /* Add all points in next BFS level */ 2805 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2806 for (p = 0; p < numPoints; ++p) { 2807 const PetscInt point = points[off+p]; 2808 PetscInt s = start[point], e = start[point+1], a; 2809 2810 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2811 } 2812 PetscHashISize(h, numNewPoints); 2813 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2814 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2815 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2816 totPoints += numNewPoints; 2817 } 2818 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2819 PetscHashIDestroy(h); 2820 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2821 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2822 for (part = pStart, q = 0; part < pEnd; ++part) { 2823 PetscInt numPoints, p; 2824 2825 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2826 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2827 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2828 } 2829 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2830 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2831 PetscFunctionReturn(0); 2832 } 2833 2834 #undef __FUNCT__ 2835 #define __FUNCT__ "DMPlexCreatePartition" 2836 /* 2837 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2838 2839 Collective on DM 2840 2841 Input Parameters: 2842 + dm - The DM 2843 . height - The height for points in the partition 2844 - enlarge - Expand each partition with neighbors 2845 2846 Output Parameters: 2847 + partSection - The PetscSection giving the division of points by partition 2848 . partition - The list of points by partition 2849 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2850 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2851 2852 Level: developer 2853 2854 .seealso DMPlexDistribute() 2855 */ 2856 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2857 { 2858 PetscMPIInt size; 2859 PetscErrorCode ierr; 2860 2861 PetscFunctionBegin; 2862 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2863 2864 *origPartSection = NULL; 2865 *origPartition = NULL; 2866 if (size == 1) { 2867 PetscInt *points; 2868 PetscInt cStart, cEnd, c; 2869 2870 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2871 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2872 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2873 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2874 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2875 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2876 for (c = cStart; c < cEnd; ++c) points[c] = c; 2877 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2878 PetscFunctionReturn(0); 2879 } 2880 if (height == 0) { 2881 PetscInt numVertices; 2882 PetscInt *start = NULL; 2883 PetscInt *adjacency = NULL; 2884 2885 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2886 if (1) { 2887 #if defined(PETSC_HAVE_CHACO) 2888 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2889 #endif 2890 } else { 2891 #if defined(PETSC_HAVE_PARMETIS) 2892 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2893 #endif 2894 } 2895 if (enlarge) { 2896 *origPartSection = *partSection; 2897 *origPartition = *partition; 2898 2899 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2900 } 2901 ierr = PetscFree(start);CHKERRQ(ierr); 2902 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2903 # if 0 2904 } else if (height == 1) { 2905 /* Build the dual graph for faces and partition the hypergraph */ 2906 PetscInt numEdges; 2907 2908 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2909 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2910 destroyCSR(numEdges, start, adjacency); 2911 #endif 2912 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2913 PetscFunctionReturn(0); 2914 } 2915 2916 #undef __FUNCT__ 2917 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2918 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2919 { 2920 /* const PetscInt height = 0; */ 2921 const PetscInt *partArray; 2922 PetscInt *allPoints, *partPoints = NULL; 2923 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2924 PetscErrorCode ierr; 2925 2926 PetscFunctionBegin; 2927 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2928 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2929 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2930 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2931 for (rank = rStart; rank < rEnd; ++rank) { 2932 PetscInt partSize = 0; 2933 PetscInt numPoints, offset, p; 2934 2935 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2936 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2937 for (p = 0; p < numPoints; ++p) { 2938 PetscInt point = partArray[offset+p], closureSize, c; 2939 PetscInt *closure = NULL; 2940 2941 /* TODO Include support for height > 0 case */ 2942 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2943 /* Merge into existing points */ 2944 if (partSize+closureSize > maxPartSize) { 2945 PetscInt *tmpPoints; 2946 2947 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2948 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2949 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2950 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2951 2952 partPoints = tmpPoints; 2953 } 2954 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 2955 partSize += closureSize; 2956 2957 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 2958 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2959 } 2960 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 2961 } 2962 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2963 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 2964 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 2965 2966 for (rank = rStart; rank < rEnd; ++rank) { 2967 PetscInt partSize = 0, newOffset; 2968 PetscInt numPoints, offset, p; 2969 2970 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2971 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2972 for (p = 0; p < numPoints; ++p) { 2973 PetscInt point = partArray[offset+p], closureSize, c; 2974 PetscInt *closure = NULL; 2975 2976 /* TODO Include support for height > 0 case */ 2977 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2978 /* Merge into existing points */ 2979 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 2980 partSize += closureSize; 2981 2982 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 2983 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2984 } 2985 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 2986 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2987 } 2988 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 2989 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2990 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2991 PetscFunctionReturn(0); 2992 } 2993 2994 #undef __FUNCT__ 2995 #define __FUNCT__ "DMPlexDistributeField" 2996 /* 2997 Input Parameters: 2998 . originalSection 2999 , originalVec 3000 3001 Output Parameters: 3002 . newSection 3003 . newVec 3004 */ 3005 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3006 { 3007 PetscSF fieldSF; 3008 PetscInt *remoteOffsets, fieldSize; 3009 PetscScalar *originalValues, *newValues; 3010 PetscErrorCode ierr; 3011 3012 PetscFunctionBegin; 3013 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3014 3015 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3016 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3017 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3018 3019 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3020 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3021 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3022 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3023 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3024 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3025 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3026 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3027 PetscFunctionReturn(0); 3028 } 3029 3030 #undef __FUNCT__ 3031 #define __FUNCT__ "DMPlexDistribute" 3032 /*@C 3033 DMPlexDistribute - Distributes the mesh and any associated sections. 3034 3035 Not Collective 3036 3037 Input Parameter: 3038 + dm - The original DMPlex object 3039 . partitioner - The partitioning package, or NULL for the default 3040 - overlap - The overlap of partitions, 0 is the default 3041 3042 Output Parameter: 3043 . parallelMesh - The distributed DMPlex object, or NULL 3044 3045 Note: If the mesh was not distributed, the return value is NULL 3046 3047 Level: intermediate 3048 3049 .keywords: mesh, elements 3050 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3051 @*/ 3052 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3053 { 3054 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3055 MPI_Comm comm; 3056 const PetscInt height = 0; 3057 PetscInt dim, numRemoteRanks; 3058 IS origCellPart, cellPart, part; 3059 PetscSection origCellPartSection, cellPartSection, partSection; 3060 PetscSFNode *remoteRanks; 3061 PetscSF partSF, pointSF, coneSF; 3062 ISLocalToGlobalMapping renumbering; 3063 PetscSection originalConeSection, newConeSection; 3064 PetscInt *remoteOffsets; 3065 PetscInt *cones, *newCones, newConesSize; 3066 PetscBool flg; 3067 PetscMPIInt rank, numProcs, p; 3068 PetscErrorCode ierr; 3069 3070 PetscFunctionBegin; 3071 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3072 PetscValidPointer(dmParallel,4); 3073 3074 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3075 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3076 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3077 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3078 3079 *dmParallel = NULL; 3080 if (numProcs == 1) PetscFunctionReturn(0); 3081 3082 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3083 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3084 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3085 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3086 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3087 if (!rank) numRemoteRanks = numProcs; 3088 else numRemoteRanks = 0; 3089 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3090 for (p = 0; p < numRemoteRanks; ++p) { 3091 remoteRanks[p].rank = p; 3092 remoteRanks[p].index = 0; 3093 } 3094 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3095 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3096 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3097 if (flg) { 3098 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3099 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3100 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3101 if (origCellPart) { 3102 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3103 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3104 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3105 } 3106 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3107 } 3108 /* Close the partition over the mesh */ 3109 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3110 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3111 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3112 /* Create new mesh */ 3113 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3114 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3115 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3116 pmesh = (DM_Plex*) (*dmParallel)->data; 3117 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3118 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3119 if (flg) { 3120 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3121 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3122 ierr = ISView(part, NULL);CHKERRQ(ierr); 3123 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3124 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3125 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3126 } 3127 /* Distribute cone section */ 3128 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3129 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3130 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3131 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3132 { 3133 PetscInt pStart, pEnd, p; 3134 3135 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3136 for (p = pStart; p < pEnd; ++p) { 3137 PetscInt coneSize; 3138 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3139 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3140 } 3141 } 3142 /* Communicate and renumber cones */ 3143 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3144 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3145 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3146 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3147 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3148 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3149 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3150 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3151 if (flg) { 3152 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3153 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3154 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3155 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3156 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3157 } 3158 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3159 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3160 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3161 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3162 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3163 /* Create supports and stratify sieve */ 3164 { 3165 PetscInt pStart, pEnd; 3166 3167 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3168 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3169 } 3170 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3171 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3172 /* Distribute Coordinates */ 3173 { 3174 PetscSection originalCoordSection, newCoordSection; 3175 Vec originalCoordinates, newCoordinates; 3176 const char *name; 3177 3178 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3179 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3180 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3181 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3182 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3183 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3184 3185 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3186 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3187 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3188 } 3189 /* Distribute labels */ 3190 { 3191 DMLabel next = mesh->labels, newNext = pmesh->labels; 3192 PetscInt numLabels = 0, l; 3193 3194 /* Bcast number of labels */ 3195 while (next) { 3196 ++numLabels; next = next->next; 3197 } 3198 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3199 next = mesh->labels; 3200 for (l = 0; l < numLabels; ++l) { 3201 DMLabel newLabel; 3202 const PetscInt *partArray; 3203 char *name; 3204 PetscInt *stratumSizes = NULL, *points = NULL; 3205 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3206 PetscInt nameSize, s, p; 3207 PetscBool isdepth; 3208 size_t len = 0; 3209 3210 /* Bcast name (could filter for no points) */ 3211 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3212 nameSize = len; 3213 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3214 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3215 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3216 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3217 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3218 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3219 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3220 newLabel->name = name; 3221 /* Bcast numStrata (could filter for no points in stratum) */ 3222 if (!rank) newLabel->numStrata = next->numStrata; 3223 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3224 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3225 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3226 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3227 /* Bcast stratumValues (could filter for no points in stratum) */ 3228 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3229 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3230 /* Find size on each process and Scatter */ 3231 if (!rank) { 3232 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3233 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3234 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3235 for (s = 0; s < next->numStrata; ++s) { 3236 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3237 const PetscInt point = next->points[p]; 3238 PetscInt proc; 3239 3240 for (proc = 0; proc < numProcs; ++proc) { 3241 PetscInt dof, off, pPart; 3242 3243 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3244 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3245 for (pPart = off; pPart < off+dof; ++pPart) { 3246 if (partArray[pPart] == point) { 3247 ++stratumSizes[proc*next->numStrata+s]; 3248 break; 3249 } 3250 } 3251 } 3252 } 3253 } 3254 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3255 } 3256 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3257 /* Calculate stratumOffsets */ 3258 newLabel->stratumOffsets[0] = 0; 3259 for (s = 0; s < newLabel->numStrata; ++s) { 3260 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3261 } 3262 /* Pack points and Scatter */ 3263 if (!rank) { 3264 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3265 displs[0] = 0; 3266 for (p = 0; p < numProcs; ++p) { 3267 sendcnts[p] = 0; 3268 for (s = 0; s < next->numStrata; ++s) { 3269 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3270 } 3271 offsets[p] = displs[p]; 3272 displs[p+1] = displs[p] + sendcnts[p]; 3273 } 3274 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3275 for (s = 0; s < next->numStrata; ++s) { 3276 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3277 const PetscInt point = next->points[p]; 3278 PetscInt proc; 3279 3280 for (proc = 0; proc < numProcs; ++proc) { 3281 PetscInt dof, off, pPart; 3282 3283 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3284 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3285 for (pPart = off; pPart < off+dof; ++pPart) { 3286 if (partArray[pPart] == point) { 3287 points[offsets[proc]++] = point; 3288 break; 3289 } 3290 } 3291 } 3292 } 3293 } 3294 } 3295 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3296 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3297 ierr = PetscFree(points);CHKERRQ(ierr); 3298 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3299 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3300 /* Renumber points */ 3301 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3302 /* Sort points */ 3303 for (s = 0; s < newLabel->numStrata; ++s) { 3304 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3305 } 3306 /* Insert into list */ 3307 if (newNext) newNext->next = newLabel; 3308 else pmesh->labels = newLabel; 3309 newNext = newLabel; 3310 if (!rank) next = next->next; 3311 } 3312 } 3313 /* Cleanup Partition */ 3314 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3315 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3316 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3317 ierr = ISDestroy(&part);CHKERRQ(ierr); 3318 /* Create point SF for parallel mesh */ 3319 { 3320 const PetscInt *leaves; 3321 PetscSFNode *remotePoints, *rowners, *lowners; 3322 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3323 PetscInt pStart, pEnd; 3324 3325 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3326 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3327 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3328 for (p=0; p<numRoots; p++) { 3329 rowners[p].rank = -1; 3330 rowners[p].index = -1; 3331 } 3332 if (origCellPart) { 3333 /* Make sure cells in the original partition are not assigned to other procs */ 3334 const PetscInt *origCells; 3335 3336 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3337 for (p = 0; p < numProcs; ++p) { 3338 PetscInt dof, off, d; 3339 3340 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3341 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3342 for (d = off; d < off+dof; ++d) { 3343 rowners[origCells[d]].rank = p; 3344 } 3345 } 3346 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3347 } 3348 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3349 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3350 3351 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3352 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3353 for (p = 0; p < numLeaves; ++p) { 3354 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3355 lowners[p].rank = rank; 3356 lowners[p].index = leaves ? leaves[p] : p; 3357 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3358 lowners[p].rank = -2; 3359 lowners[p].index = -2; 3360 } 3361 } 3362 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3363 rowners[p].rank = -3; 3364 rowners[p].index = -3; 3365 } 3366 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3367 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3368 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3369 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3370 for (p = 0; p < numLeaves; ++p) { 3371 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3372 if (lowners[p].rank != rank) ++numGhostPoints; 3373 } 3374 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3375 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3376 for (p = 0, gp = 0; p < numLeaves; ++p) { 3377 if (lowners[p].rank != rank) { 3378 ghostPoints[gp] = leaves ? leaves[p] : p; 3379 remotePoints[gp].rank = lowners[p].rank; 3380 remotePoints[gp].index = lowners[p].index; 3381 ++gp; 3382 } 3383 } 3384 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3385 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3386 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3387 } 3388 /* Cleanup */ 3389 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3390 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3391 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3392 PetscFunctionReturn(0); 3393 } 3394 3395 #undef __FUNCT__ 3396 #define __FUNCT__ "DMPlexRenumber_Private" 3397 /* 3398 Reasons to renumber: 3399 3400 1) Permute points, e.g. bandwidth reduction (Renumber) 3401 3402 a) Must not mix strata 3403 3404 2) Shift numbers for point insertion (Shift) 3405 3406 a) Want operation brken into parts so that insertion can be interleaved 3407 3408 renumbering - An IS which provides the new numbering 3409 */ 3410 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3411 { 3412 PetscFunctionBegin; 3413 PetscFunctionReturn(0); 3414 } 3415 3416 #undef __FUNCT__ 3417 #define __FUNCT__ "DMPlexShiftPoint_Private" 3418 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3419 { 3420 if (depth < 0) return p; 3421 /* Cells */ if (p < depthEnd[depth]) return p; 3422 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3423 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3424 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3425 } 3426 3427 #undef __FUNCT__ 3428 #define __FUNCT__ "DMPlexShiftSizes_Private" 3429 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3430 { 3431 PetscInt *depthEnd; 3432 PetscInt depth = 0, d, pStart, pEnd, p; 3433 PetscErrorCode ierr; 3434 3435 PetscFunctionBegin; 3436 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3437 if (depth < 0) PetscFunctionReturn(0); 3438 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3439 /* Step 1: Expand chart */ 3440 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3441 for (d = 0; d <= depth; ++d) { 3442 pEnd += depthShift[d]; 3443 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3444 } 3445 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3446 /* Step 2: Set cone and support sizes */ 3447 for (d = 0; d <= depth; ++d) { 3448 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3449 for (p = pStart; p < pEnd; ++p) { 3450 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3451 PetscInt size; 3452 3453 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3454 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3455 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3456 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3457 } 3458 } 3459 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3460 PetscFunctionReturn(0); 3461 } 3462 3463 #undef __FUNCT__ 3464 #define __FUNCT__ "DMPlexShiftPoints_Private" 3465 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3466 { 3467 PetscInt *depthEnd, *newpoints; 3468 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3469 PetscErrorCode ierr; 3470 3471 PetscFunctionBegin; 3472 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3473 if (depth < 0) PetscFunctionReturn(0); 3474 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3475 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3476 for (d = 0; d <= depth; ++d) { 3477 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3478 } 3479 /* Step 5: Set cones and supports */ 3480 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3481 for (p = pStart; p < pEnd; ++p) { 3482 const PetscInt *points = NULL, *orientations = NULL; 3483 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3484 3485 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3486 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3487 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3488 for (i = 0; i < size; ++i) { 3489 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3490 } 3491 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3492 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3493 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3494 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3495 for (i = 0; i < size; ++i) { 3496 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3497 } 3498 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3499 } 3500 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3501 PetscFunctionReturn(0); 3502 } 3503 3504 #undef __FUNCT__ 3505 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3506 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3507 { 3508 PetscSection coordSection, newCoordSection; 3509 Vec coordinates, newCoordinates; 3510 PetscScalar *coords, *newCoords; 3511 PetscInt *depthEnd, coordSize; 3512 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3513 PetscErrorCode ierr; 3514 3515 PetscFunctionBegin; 3516 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3517 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3518 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3519 for (d = 0; d <= depth; ++d) { 3520 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3521 } 3522 /* Step 8: Convert coordinates */ 3523 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3524 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3525 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3526 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);CHKERRQ(ierr); 3527 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3528 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3529 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3530 for (v = vStartNew; v < vEndNew; ++v) { 3531 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3532 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3533 } 3534 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3535 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3536 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3537 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &newCoordinates);CHKERRQ(ierr); 3538 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3539 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3540 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3541 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3542 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3543 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3544 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3545 for (v = vStart; v < vEnd; ++v) { 3546 PetscInt dof, off, noff, d; 3547 3548 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3549 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3550 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3551 for (d = 0; d < dof; ++d) { 3552 newCoords[noff+d] = coords[off+d]; 3553 } 3554 } 3555 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3556 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3557 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3558 ierr = PetscSectionDestroy(&newCoordSection);CHKERRQ(ierr); 3559 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3560 PetscFunctionReturn(0); 3561 } 3562 3563 #undef __FUNCT__ 3564 #define __FUNCT__ "DMPlexShiftSF_Private" 3565 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3566 { 3567 PetscInt *depthEnd; 3568 PetscInt depth = 0, d; 3569 PetscSF sfPoint, sfPointNew; 3570 const PetscSFNode *remotePoints; 3571 PetscSFNode *gremotePoints; 3572 const PetscInt *localPoints; 3573 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3574 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3575 PetscMPIInt numProcs; 3576 PetscErrorCode ierr; 3577 3578 PetscFunctionBegin; 3579 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3580 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3581 for (d = 0; d <= depth; ++d) { 3582 totShift += depthShift[d]; 3583 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3584 } 3585 /* Step 9: Convert pointSF */ 3586 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 3587 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3588 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3589 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3590 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3591 if (numRoots >= 0) { 3592 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3593 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3594 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3595 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3596 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3597 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3598 for (l = 0; l < numLeaves; ++l) { 3599 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3600 gremotePoints[l].rank = remotePoints[l].rank; 3601 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3602 } 3603 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3604 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3605 } 3606 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3607 PetscFunctionReturn(0); 3608 } 3609 3610 #undef __FUNCT__ 3611 #define __FUNCT__ "DMPlexShiftLabels_Private" 3612 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3613 { 3614 PetscSF sfPoint; 3615 DMLabel vtkLabel, ghostLabel; 3616 PetscInt *depthEnd; 3617 const PetscSFNode *leafRemote; 3618 const PetscInt *leafLocal; 3619 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3620 PetscMPIInt rank; 3621 PetscErrorCode ierr; 3622 3623 PetscFunctionBegin; 3624 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3625 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3626 for (d = 0; d <= depth; ++d) { 3627 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3628 } 3629 /* Step 10: Convert labels */ 3630 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3631 for (l = 0; l < numLabels; ++l) { 3632 DMLabel label, newlabel; 3633 const char *lname; 3634 PetscBool isDepth; 3635 IS valueIS; 3636 const PetscInt *values; 3637 PetscInt numValues, val; 3638 3639 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3640 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3641 if (isDepth) continue; 3642 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3643 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3644 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3645 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3646 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3647 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3648 for (val = 0; val < numValues; ++val) { 3649 IS pointIS; 3650 const PetscInt *points; 3651 PetscInt numPoints, p; 3652 3653 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3654 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3655 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3656 for (p = 0; p < numPoints; ++p) { 3657 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3658 3659 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3660 } 3661 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3662 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3663 } 3664 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3665 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3666 } 3667 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3668 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3669 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 3670 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3671 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3672 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3673 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3674 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3675 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3676 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3677 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3678 for (; c < leafLocal[l] && c < cEnd; ++c) { 3679 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3680 } 3681 if (leafLocal[l] >= cEnd) break; 3682 if (leafRemote[l].rank == rank) { 3683 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3684 } else { 3685 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3686 } 3687 } 3688 for (; c < cEnd; ++c) { 3689 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3690 } 3691 if (0) { 3692 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3693 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3694 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3695 } 3696 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3697 for (f = fStart; f < fEnd; ++f) { 3698 PetscInt numCells; 3699 3700 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3701 if (numCells < 2) { 3702 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3703 } else { 3704 const PetscInt *cells = NULL; 3705 PetscInt vA, vB; 3706 3707 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3708 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3709 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3710 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3711 } 3712 } 3713 if (0) { 3714 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3715 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3716 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3717 } 3718 PetscFunctionReturn(0); 3719 } 3720 3721 #undef __FUNCT__ 3722 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3723 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3724 { 3725 DMLabel label; 3726 IS valueIS; 3727 const PetscInt *values; 3728 PetscInt *depthShift; 3729 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3730 PetscErrorCode ierr; 3731 3732 PetscFunctionBegin; 3733 /* Count ghost cells */ 3734 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3735 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3736 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3737 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3738 3739 *numGhostCells = 0; 3740 for (fs = 0; fs < numFS; ++fs) { 3741 PetscInt numBdFaces; 3742 3743 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3744 3745 *numGhostCells += numBdFaces; 3746 } 3747 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3748 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3749 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3750 if (depth >= 0) depthShift[depth] = *numGhostCells; 3751 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3752 /* Step 3: Set cone/support sizes for new points */ 3753 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3754 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3755 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3756 } 3757 for (fs = 0; fs < numFS; ++fs) { 3758 IS faceIS; 3759 const PetscInt *faces; 3760 PetscInt numFaces, f; 3761 3762 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3763 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3764 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3765 for (f = 0; f < numFaces; ++f) { 3766 PetscInt size; 3767 3768 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3769 if (size != 1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3770 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3771 } 3772 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3773 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3774 } 3775 /* Step 4: Setup ghosted DM */ 3776 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3777 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3778 /* Step 6: Set cones and supports for new points */ 3779 ghostCell = cEnd; 3780 for (fs = 0; fs < numFS; ++fs) { 3781 IS faceIS; 3782 const PetscInt *faces; 3783 PetscInt numFaces, f; 3784 3785 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3786 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3787 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3788 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3789 PetscInt newFace = faces[f] + *numGhostCells; 3790 3791 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3792 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3793 } 3794 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3795 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3796 } 3797 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3798 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3799 /* Step 7: Stratify */ 3800 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3801 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3802 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3803 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3804 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3805 PetscFunctionReturn(0); 3806 } 3807 3808 #undef __FUNCT__ 3809 #define __FUNCT__ "DMPlexConstructGhostCells" 3810 /*@C 3811 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3812 3813 Collective on dm 3814 3815 Input Parameters: 3816 + dm - The original DM 3817 - labelName - The label specifying the boundary faces (this could be auto-generated) 3818 3819 Output Parameters: 3820 + numGhostCells - The number of ghost cells added to the DM 3821 - dmGhosted - The new DM 3822 3823 Level: developer 3824 3825 .seealso: DMCreate() 3826 */ 3827 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3828 { 3829 DM gdm; 3830 PetscInt dim; 3831 PetscErrorCode ierr; 3832 3833 PetscFunctionBegin; 3834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3835 PetscValidPointer(numGhostCells, 3); 3836 PetscValidPointer(dmGhosted, 4); 3837 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &gdm);CHKERRQ(ierr); 3838 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3839 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3840 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3841 switch (dim) { 3842 case 2: 3843 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3844 break; 3845 default: 3846 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3847 } 3848 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3849 *dmGhosted = gdm; 3850 PetscFunctionReturn(0); 3851 } 3852 3853 #undef __FUNCT__ 3854 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3855 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3856 { 3857 MPI_Comm comm; 3858 IS valueIS, *pointIS; 3859 const PetscInt *values, **splitPoints; 3860 PetscSection coordSection; 3861 Vec coordinates; 3862 PetscScalar *coords; 3863 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3864 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3865 PetscErrorCode ierr; 3866 3867 PetscFunctionBegin; 3868 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3869 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3870 /* Count split points and add cohesive cells */ 3871 if (label) { 3872 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3873 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3874 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3875 } 3876 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3877 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3878 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3879 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3880 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3881 for (d = 0; d <= depth; ++d) { 3882 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3883 numSplitPoints[d] = 0; 3884 splitPoints[d] = NULL; 3885 pointIS[d] = NULL; 3886 } 3887 for (sp = 0; sp < numSP; ++sp) { 3888 const PetscInt dep = values[sp]; 3889 3890 if ((dep < 0) || (dep > depth)) continue; 3891 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3892 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3893 if (pointIS[dep]) { 3894 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3895 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3896 } 3897 } 3898 if (depth >= 0) { 3899 /* Calculate number of additional points */ 3900 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3901 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3902 /* Calculate hybrid bound for each dimension */ 3903 pMaxNew[0] += depthShift[depth]; 3904 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3905 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3906 3907 /* Calculate point offset for each dimension */ 3908 depthOffset[depth] = 0; 3909 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3910 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3911 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3912 } 3913 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3914 /* Step 3: Set cone/support sizes for new points */ 3915 for (dep = 0; dep <= depth; ++dep) { 3916 for (p = 0; p < numSplitPoints[dep]; ++p) { 3917 const PetscInt oldp = splitPoints[dep][p]; 3918 const PetscInt newp = depthOffset[dep] + oldp; 3919 const PetscInt splitp = pMaxNew[dep] + p; 3920 const PetscInt *support; 3921 PetscInt coneSize, supportSize, q, e; 3922 3923 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3924 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3925 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3926 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3927 if (dep == depth-1) { 3928 const PetscInt ccell = pMaxNew[depth] + p; 3929 /* Add cohesive cells, they are prisms */ 3930 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3931 } else if (dep == 0) { 3932 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3933 3934 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3935 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3936 for (e = 0, q = 0; e < supportSize; ++e) { 3937 PetscInt val; 3938 3939 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3940 if ((val == 1) || (val == (shift + 1))) ++q; 3941 } 3942 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3943 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3944 for (e = 0, q = 0; e < supportSize; ++e) { 3945 PetscInt val; 3946 3947 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3948 if ((val == 1) || (val == -(shift + 1))) ++q; 3949 } 3950 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3951 /* Add cohesive edges */ 3952 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3953 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3954 } else if (dep == dim-2) { 3955 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3956 /* Split old edge: Faces in positive side cells and old split faces */ 3957 for (e = 0, q = 0; e < supportSize; ++e) { 3958 PetscInt val; 3959 3960 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3961 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 3962 } 3963 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 3964 /* Split new edge: Faces in negative side cells and new split faces */ 3965 for (e = 0, q = 0; e < supportSize; ++e) { 3966 PetscInt val; 3967 3968 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3969 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 3970 } 3971 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 3972 } 3973 } 3974 } 3975 /* Step 4: Setup split DM */ 3976 ierr = DMSetUp(sdm);CHKERRQ(ierr); 3977 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3978 /* Step 6: Set cones and supports for new points */ 3979 for (dep = 0; dep <= depth; ++dep) { 3980 for (p = 0; p < numSplitPoints[dep]; ++p) { 3981 const PetscInt oldp = splitPoints[dep][p]; 3982 const PetscInt newp = depthOffset[dep] + oldp; 3983 const PetscInt splitp = pMaxNew[dep] + p; 3984 const PetscInt *cone, *support, *ornt; 3985 PetscInt coneSize, supportSize, q, v, e, s; 3986 3987 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3988 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 3989 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 3990 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3991 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3992 if (dep == depth-1) { 3993 const PetscInt ccell = pMaxNew[depth] + p; 3994 const PetscInt *supportF; 3995 3996 /* Split face: copy in old face to new face to start */ 3997 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 3998 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 3999 /* Split old face: old vertices/edges in cone so no change */ 4000 /* Split new face: new vertices/edges in cone */ 4001 for (q = 0; q < coneSize; ++q) { 4002 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4003 4004 coneNew[2+q] = pMaxNew[dim-2] + v; 4005 } 4006 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4007 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4008 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4009 coneNew[0] = newp; 4010 coneNew[1] = splitp; 4011 for (q = 0; q < coneSize; ++q) { 4012 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4013 } 4014 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4015 4016 4017 for (s = 0; s < supportSize; ++s) { 4018 PetscInt val; 4019 4020 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4021 if (val < 0) { 4022 /* Split old face: Replace negative side cell with cohesive cell */ 4023 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4024 } else { 4025 /* Split new face: Replace positive side cell with cohesive cell */ 4026 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4027 } 4028 } 4029 } else if (dep == 0) { 4030 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4031 4032 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4033 for (e = 0, q = 0; e < supportSize; ++e) { 4034 PetscInt val; 4035 4036 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4037 if ((val == 1) || (val == (shift + 1))) { 4038 supportNew[q++] = depthOffset[1] + support[e]; 4039 } 4040 } 4041 supportNew[q] = cedge; 4042 4043 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4044 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4045 for (e = 0, q = 0; e < supportSize; ++e) { 4046 PetscInt val, edge; 4047 4048 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4049 if (val == 1) { 4050 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4051 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4052 supportNew[q++] = pMaxNew[1] + edge; 4053 } else if (val == -(shift + 1)) { 4054 supportNew[q++] = depthOffset[1] + support[e]; 4055 } 4056 } 4057 supportNew[q] = cedge; 4058 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4059 /* Cohesive edge: Old and new split vertex, punting on support */ 4060 coneNew[0] = newp; 4061 coneNew[1] = splitp; 4062 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4063 } else if (dep == dim-2) { 4064 /* Split old edge: old vertices in cone so no change */ 4065 /* Split new edge: new vertices in cone */ 4066 for (q = 0; q < coneSize; ++q) { 4067 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4068 4069 coneNew[q] = pMaxNew[dim-3] + v; 4070 } 4071 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4072 /* Split old edge: Faces in positive side cells and old split faces */ 4073 for (e = 0, q = 0; e < supportSize; ++e) { 4074 PetscInt val; 4075 4076 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4077 if ((val == dim-1) || (val == (shift + dim-1))) { 4078 supportNew[q++] = depthOffset[dim-1] + support[e]; 4079 } 4080 } 4081 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4082 /* Split new edge: Faces in negative side cells and new split faces */ 4083 for (e = 0, q = 0; e < supportSize; ++e) { 4084 PetscInt val, face; 4085 4086 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4087 if (val == dim-1) { 4088 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4089 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4090 supportNew[q++] = pMaxNew[dim-1] + face; 4091 } else if (val == -(shift + dim-1)) { 4092 supportNew[q++] = depthOffset[dim-1] + support[e]; 4093 } 4094 } 4095 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4096 } 4097 } 4098 } 4099 /* Step 6b: Replace split points in negative side cones */ 4100 for (sp = 0; sp < numSP; ++sp) { 4101 PetscInt dep = values[sp]; 4102 IS pIS; 4103 PetscInt numPoints; 4104 const PetscInt *points; 4105 4106 if (dep >= 0) continue; 4107 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4108 if (!pIS) continue; 4109 dep = -dep - shift; 4110 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4111 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4112 for (p = 0; p < numPoints; ++p) { 4113 const PetscInt oldp = points[p]; 4114 const PetscInt newp = depthOffset[dep] + oldp; 4115 const PetscInt *cone; 4116 PetscInt coneSize, c; 4117 PetscBool replaced = PETSC_FALSE; 4118 4119 /* Negative edge: replace split vertex */ 4120 /* Negative cell: replace split face */ 4121 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4122 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4123 for (c = 0; c < coneSize; ++c) { 4124 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4125 PetscInt csplitp, cp, val; 4126 4127 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4128 if (val == dep-1) { 4129 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4130 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4131 csplitp = pMaxNew[dep-1] + cp; 4132 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4133 replaced = PETSC_TRUE; 4134 } 4135 } 4136 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4137 } 4138 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4139 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4140 } 4141 /* Step 7: Stratify */ 4142 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4143 /* Step 8: Coordinates */ 4144 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4145 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4146 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4147 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4148 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4149 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4150 const PetscInt splitp = pMaxNew[0] + v; 4151 PetscInt dof, off, soff, d; 4152 4153 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4154 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4155 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4156 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4157 } 4158 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4159 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4160 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4161 /* Step 10: Labels */ 4162 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4163 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4164 for (dep = 0; dep <= depth; ++dep) { 4165 for (p = 0; p < numSplitPoints[dep]; ++p) { 4166 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4167 const PetscInt splitp = pMaxNew[dep] + p; 4168 PetscInt l; 4169 4170 for (l = 0; l < numLabels; ++l) { 4171 DMLabel mlabel; 4172 const char *lname; 4173 PetscInt val; 4174 4175 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4176 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4177 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4178 if (val >= 0) { 4179 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4180 if (dep == 0) { 4181 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4182 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4183 } 4184 } 4185 } 4186 } 4187 } 4188 for (sp = 0; sp < numSP; ++sp) { 4189 const PetscInt dep = values[sp]; 4190 4191 if ((dep < 0) || (dep > depth)) continue; 4192 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4193 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4194 } 4195 if (label) { 4196 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4197 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4198 } 4199 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4200 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4201 PetscFunctionReturn(0); 4202 } 4203 4204 #undef __FUNCT__ 4205 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4206 /*@C 4207 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4208 4209 Collective on dm 4210 4211 Input Parameters: 4212 + dm - The original DM 4213 - labelName - The label specifying the boundary faces (this could be auto-generated) 4214 4215 Output Parameters: 4216 - dmSplit - The new DM 4217 4218 Level: developer 4219 4220 .seealso: DMCreate() 4221 */ 4222 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4223 { 4224 DM sdm; 4225 PetscInt dim; 4226 PetscErrorCode ierr; 4227 4228 PetscFunctionBegin; 4229 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4230 PetscValidPointer(dmSplit, 4); 4231 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 4232 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4233 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4234 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4235 switch (dim) { 4236 case 2: 4237 case 3: 4238 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4239 break; 4240 default: 4241 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4242 } 4243 *dmSplit = sdm; 4244 PetscFunctionReturn(0); 4245 } 4246 4247 #undef __FUNCT__ 4248 #define __FUNCT__ "DMLabelCohesiveComplete" 4249 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4250 { 4251 IS dimIS; 4252 const PetscInt *points; 4253 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4254 PetscErrorCode ierr; 4255 4256 PetscFunctionBegin; 4257 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4258 /* Cell orientation for face gives the side of the fault */ 4259 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4260 if (!dimIS) PetscFunctionReturn(0); 4261 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4262 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4263 for (p = 0; p < numPoints; ++p) { 4264 const PetscInt *support; 4265 PetscInt supportSize, s; 4266 4267 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4268 if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4269 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4270 for (s = 0; s < supportSize; ++s) { 4271 const PetscInt *cone, *ornt; 4272 PetscInt coneSize, c; 4273 PetscBool pos = PETSC_TRUE; 4274 4275 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4276 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4277 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4278 for (c = 0; c < coneSize; ++c) { 4279 if (cone[c] == points[p]) { 4280 if (ornt[c] >= 0) { 4281 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4282 } else { 4283 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4284 pos = PETSC_FALSE; 4285 } 4286 break; 4287 } 4288 } 4289 if (c == coneSize) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]); 4290 /* Put faces touching the fault in the label */ 4291 for (c = 0; c < coneSize; ++c) { 4292 const PetscInt point = cone[c]; 4293 4294 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4295 if (val == -1) { 4296 PetscInt *closure = NULL; 4297 PetscInt closureSize, cl; 4298 4299 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4300 for (cl = 0; cl < closureSize*2; cl += 2) { 4301 const PetscInt clp = closure[cl]; 4302 4303 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4304 if ((val >= 0) && (val < dim-1)) { 4305 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4306 break; 4307 } 4308 } 4309 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4310 } 4311 } 4312 } 4313 } 4314 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4315 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4316 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4317 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4318 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4319 if (!dimIS) PetscFunctionReturn(0); 4320 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4321 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4322 for (p = 0; p < numPoints; ++p) { 4323 PetscInt *star = NULL; 4324 PetscInt starSize, s; 4325 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4326 4327 /* First mark cells connected to the fault */ 4328 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4329 while (again) { 4330 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4331 again = 0; 4332 for (s = 0; s < starSize*2; s += 2) { 4333 const PetscInt point = star[s]; 4334 const PetscInt *cone; 4335 PetscInt coneSize, c; 4336 4337 if ((point < cStart) || (point >= cEnd)) continue; 4338 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4339 if (val != -1) continue; 4340 again = 2; 4341 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4342 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4343 for (c = 0; c < coneSize; ++c) { 4344 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4345 if (val != -1) { 4346 if (abs(val) < shift) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 4347 if (val > 0) { 4348 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4349 } else { 4350 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4351 } 4352 again = 1; 4353 break; 4354 } 4355 } 4356 } 4357 } 4358 /* Classify the rest by cell membership */ 4359 for (s = 0; s < starSize*2; s += 2) { 4360 const PetscInt point = star[s]; 4361 4362 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4363 if (val == -1) { 4364 PetscInt *sstar = NULL; 4365 PetscInt sstarSize, ss; 4366 PetscBool marked = PETSC_FALSE; 4367 4368 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4369 for (ss = 0; ss < sstarSize*2; ss += 2) { 4370 const PetscInt spoint = sstar[ss]; 4371 4372 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4373 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4374 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4375 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4376 if (val > 0) { 4377 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4378 } else { 4379 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4380 } 4381 marked = PETSC_TRUE; 4382 break; 4383 } 4384 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4385 if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 4386 } 4387 } 4388 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4389 } 4390 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4391 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4392 PetscFunctionReturn(0); 4393 } 4394 4395 #undef __FUNCT__ 4396 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4397 /* 4398 This takes as input the common mesh generator output, a list of the vertices for each cell 4399 */ 4400 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4401 { 4402 PetscInt *cone, c, p; 4403 PetscErrorCode ierr; 4404 4405 PetscFunctionBegin; 4406 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4407 for (c = 0; c < numCells; ++c) { 4408 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4409 } 4410 ierr = DMSetUp(dm);CHKERRQ(ierr); 4411 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4412 for (c = 0; c < numCells; ++c) { 4413 for (p = 0; p < numCorners; ++p) { 4414 cone[p] = cells[c*numCorners+p]+numCells; 4415 } 4416 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4417 } 4418 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4419 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4420 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4421 PetscFunctionReturn(0); 4422 } 4423 4424 #undef __FUNCT__ 4425 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4426 /* 4427 This takes as input the coordinates for each vertex 4428 */ 4429 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4430 { 4431 PetscSection coordSection; 4432 Vec coordinates; 4433 PetscScalar *coords; 4434 PetscInt coordSize, v, d; 4435 PetscErrorCode ierr; 4436 4437 PetscFunctionBegin; 4438 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4439 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4440 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4441 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4442 for (v = numCells; v < numCells+numVertices; ++v) { 4443 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4444 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4445 } 4446 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4447 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4448 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4449 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4450 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4451 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4452 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4453 for (v = 0; v < numVertices; ++v) { 4454 for (d = 0; d < spaceDim; ++d) { 4455 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4456 } 4457 } 4458 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4459 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4460 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4461 PetscFunctionReturn(0); 4462 } 4463 4464 #undef __FUNCT__ 4465 #define __FUNCT__ "DMPlexCreateFromCellList" 4466 /* 4467 This takes as input the common mesh generator output, a list of the vertices for each cell 4468 */ 4469 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], PetscInt spaceDim, const double vertexCoords[], DM *dm) 4470 { 4471 PetscErrorCode ierr; 4472 4473 PetscFunctionBegin; 4474 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4475 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4476 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4477 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4478 if (interpolate) { 4479 DM idm; 4480 4481 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 4482 ierr = DMDestroy(dm);CHKERRQ(ierr); 4483 *dm = idm; 4484 } 4485 ierr = DMPlexBuildCoordinates_Private(*dm, spaceDim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4486 PetscFunctionReturn(0); 4487 } 4488 4489 #undef __FUNCT__ 4490 #define __FUNCT__ "DMPlexCreateFromDAG" 4491 /* 4492 This takes as input the raw Hasse Diagram data 4493 */ 4494 PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 4495 { 4496 Vec coordinates; 4497 PetscSection coordSection; 4498 PetscScalar *coords; 4499 PetscInt coordSize, firstVertex = numPoints[depth], pStart = 0, pEnd = 0, p, v, dim, d, off; 4500 PetscErrorCode ierr; 4501 4502 PetscFunctionBegin; 4503 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4504 for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 4505 ierr = DMPlexSetChart(dm, pStart, pEnd);CHKERRQ(ierr); 4506 for (p = pStart; p < pEnd; ++p) { 4507 ierr = DMPlexSetConeSize(dm, p, coneSize[p-pStart]);CHKERRQ(ierr); 4508 } 4509 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 4510 for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) { 4511 ierr = DMPlexSetCone(dm, p, &cones[off]);CHKERRQ(ierr); 4512 ierr = DMPlexSetConeOrientation(dm, p, &coneOrientations[off]);CHKERRQ(ierr); 4513 } 4514 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4515 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4516 /* Build coordinates */ 4517 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4518 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4519 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 4520 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);CHKERRQ(ierr); 4521 for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 4522 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 4523 } 4524 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4525 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4526 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4527 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4528 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4529 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4530 for (v = 0; v < numPoints[0]; ++v) { 4531 PetscInt off; 4532 4533 ierr = PetscSectionGetOffset(coordSection, v+firstVertex, &off);CHKERRQ(ierr); 4534 for (d = 0; d < dim; ++d) { 4535 coords[off+d] = vertexCoords[v*dim+d]; 4536 } 4537 } 4538 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4539 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4540 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4541 PetscFunctionReturn(0); 4542 } 4543 4544 #if defined(PETSC_HAVE_TRIANGLE) 4545 #include <triangle.h> 4546 4547 #undef __FUNCT__ 4548 #define __FUNCT__ "InitInput_Triangle" 4549 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4550 { 4551 PetscFunctionBegin; 4552 inputCtx->numberofpoints = 0; 4553 inputCtx->numberofpointattributes = 0; 4554 inputCtx->pointlist = NULL; 4555 inputCtx->pointattributelist = NULL; 4556 inputCtx->pointmarkerlist = NULL; 4557 inputCtx->numberofsegments = 0; 4558 inputCtx->segmentlist = NULL; 4559 inputCtx->segmentmarkerlist = NULL; 4560 inputCtx->numberoftriangleattributes = 0; 4561 inputCtx->trianglelist = NULL; 4562 inputCtx->numberofholes = 0; 4563 inputCtx->holelist = NULL; 4564 inputCtx->numberofregions = 0; 4565 inputCtx->regionlist = NULL; 4566 PetscFunctionReturn(0); 4567 } 4568 4569 #undef __FUNCT__ 4570 #define __FUNCT__ "InitOutput_Triangle" 4571 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4572 { 4573 PetscFunctionBegin; 4574 outputCtx->numberofpoints = 0; 4575 outputCtx->pointlist = NULL; 4576 outputCtx->pointattributelist = NULL; 4577 outputCtx->pointmarkerlist = NULL; 4578 outputCtx->numberoftriangles = 0; 4579 outputCtx->trianglelist = NULL; 4580 outputCtx->triangleattributelist = NULL; 4581 outputCtx->neighborlist = NULL; 4582 outputCtx->segmentlist = NULL; 4583 outputCtx->segmentmarkerlist = NULL; 4584 outputCtx->numberofedges = 0; 4585 outputCtx->edgelist = NULL; 4586 outputCtx->edgemarkerlist = NULL; 4587 PetscFunctionReturn(0); 4588 } 4589 4590 #undef __FUNCT__ 4591 #define __FUNCT__ "FiniOutput_Triangle" 4592 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4593 { 4594 PetscFunctionBegin; 4595 free(outputCtx->pointmarkerlist); 4596 free(outputCtx->edgelist); 4597 free(outputCtx->edgemarkerlist); 4598 free(outputCtx->trianglelist); 4599 free(outputCtx->neighborlist); 4600 PetscFunctionReturn(0); 4601 } 4602 4603 #undef __FUNCT__ 4604 #define __FUNCT__ "DMPlexGenerate_Triangle" 4605 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4606 { 4607 MPI_Comm comm; 4608 PetscInt dim = 2; 4609 const PetscBool createConvexHull = PETSC_FALSE; 4610 const PetscBool constrained = PETSC_FALSE; 4611 struct triangulateio in; 4612 struct triangulateio out; 4613 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4614 PetscMPIInt rank; 4615 PetscErrorCode ierr; 4616 4617 PetscFunctionBegin; 4618 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4619 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4620 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4621 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4622 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4623 4624 in.numberofpoints = vEnd - vStart; 4625 if (in.numberofpoints > 0) { 4626 PetscSection coordSection; 4627 Vec coordinates; 4628 PetscScalar *array; 4629 4630 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4631 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4632 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4633 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4634 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4635 for (v = vStart; v < vEnd; ++v) { 4636 const PetscInt idx = v - vStart; 4637 PetscInt off, d; 4638 4639 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4640 for (d = 0; d < dim; ++d) { 4641 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4642 } 4643 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4644 } 4645 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4646 } 4647 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4648 in.numberofsegments = eEnd - eStart; 4649 if (in.numberofsegments > 0) { 4650 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4651 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4652 for (e = eStart; e < eEnd; ++e) { 4653 const PetscInt idx = e - eStart; 4654 const PetscInt *cone; 4655 4656 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4657 4658 in.segmentlist[idx*2+0] = cone[0] - vStart; 4659 in.segmentlist[idx*2+1] = cone[1] - vStart; 4660 4661 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4662 } 4663 } 4664 #if 0 /* Do not currently support holes */ 4665 PetscReal *holeCoords; 4666 PetscInt h, d; 4667 4668 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4669 if (in.numberofholes > 0) { 4670 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4671 for (h = 0; h < in.numberofholes; ++h) { 4672 for (d = 0; d < dim; ++d) { 4673 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4674 } 4675 } 4676 } 4677 #endif 4678 if (!rank) { 4679 char args[32]; 4680 4681 /* Take away 'Q' for verbose output */ 4682 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4683 if (createConvexHull) { 4684 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4685 } 4686 if (constrained) { 4687 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4688 } 4689 triangulate(args, &in, &out, NULL); 4690 } 4691 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4692 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4693 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4694 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4695 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4696 4697 { 4698 const PetscInt numCorners = 3; 4699 const PetscInt numCells = out.numberoftriangles; 4700 const PetscInt numVertices = out.numberofpoints; 4701 const int *cells = out.trianglelist; 4702 const double *meshCoords = out.pointlist; 4703 4704 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4705 /* Set labels */ 4706 for (v = 0; v < numVertices; ++v) { 4707 if (out.pointmarkerlist[v]) { 4708 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4709 } 4710 } 4711 if (interpolate) { 4712 for (e = 0; e < out.numberofedges; e++) { 4713 if (out.edgemarkerlist[e]) { 4714 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4715 const PetscInt *edges; 4716 PetscInt numEdges; 4717 4718 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4719 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4720 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4721 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4722 } 4723 } 4724 } 4725 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4726 } 4727 #if 0 /* Do not currently support holes */ 4728 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4729 #endif 4730 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4731 PetscFunctionReturn(0); 4732 } 4733 4734 #undef __FUNCT__ 4735 #define __FUNCT__ "DMPlexRefine_Triangle" 4736 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4737 { 4738 MPI_Comm comm; 4739 PetscInt dim = 2; 4740 struct triangulateio in; 4741 struct triangulateio out; 4742 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4743 PetscMPIInt rank; 4744 PetscErrorCode ierr; 4745 4746 PetscFunctionBegin; 4747 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4748 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4749 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4750 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4751 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4752 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4753 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4754 4755 in.numberofpoints = vEnd - vStart; 4756 if (in.numberofpoints > 0) { 4757 PetscSection coordSection; 4758 Vec coordinates; 4759 PetscScalar *array; 4760 4761 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4762 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4763 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4764 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4765 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4766 for (v = vStart; v < vEnd; ++v) { 4767 const PetscInt idx = v - vStart; 4768 PetscInt off, d; 4769 4770 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4771 for (d = 0; d < dim; ++d) { 4772 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4773 } 4774 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4775 } 4776 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4777 } 4778 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4779 4780 in.numberofcorners = 3; 4781 in.numberoftriangles = cEnd - cStart; 4782 4783 in.trianglearealist = (double*) maxVolumes; 4784 if (in.numberoftriangles > 0) { 4785 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4786 for (c = cStart; c < cEnd; ++c) { 4787 const PetscInt idx = c - cStart; 4788 PetscInt *closure = NULL; 4789 PetscInt closureSize; 4790 4791 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4792 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4793 for (v = 0; v < 3; ++v) { 4794 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4795 } 4796 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4797 } 4798 } 4799 /* TODO: Segment markers are missing on input */ 4800 #if 0 /* Do not currently support holes */ 4801 PetscReal *holeCoords; 4802 PetscInt h, d; 4803 4804 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4805 if (in.numberofholes > 0) { 4806 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4807 for (h = 0; h < in.numberofholes; ++h) { 4808 for (d = 0; d < dim; ++d) { 4809 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4810 } 4811 } 4812 } 4813 #endif 4814 if (!rank) { 4815 char args[32]; 4816 4817 /* Take away 'Q' for verbose output */ 4818 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4819 triangulate(args, &in, &out, NULL); 4820 } 4821 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4822 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4823 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4824 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4825 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4826 4827 { 4828 const PetscInt numCorners = 3; 4829 const PetscInt numCells = out.numberoftriangles; 4830 const PetscInt numVertices = out.numberofpoints; 4831 const int *cells = out.trianglelist; 4832 const double *meshCoords = out.pointlist; 4833 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4834 4835 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4836 /* Set labels */ 4837 for (v = 0; v < numVertices; ++v) { 4838 if (out.pointmarkerlist[v]) { 4839 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4840 } 4841 } 4842 if (interpolate) { 4843 PetscInt e; 4844 4845 for (e = 0; e < out.numberofedges; e++) { 4846 if (out.edgemarkerlist[e]) { 4847 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4848 const PetscInt *edges; 4849 PetscInt numEdges; 4850 4851 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4852 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4853 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4854 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4855 } 4856 } 4857 } 4858 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4859 } 4860 #if 0 /* Do not currently support holes */ 4861 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4862 #endif 4863 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4864 PetscFunctionReturn(0); 4865 } 4866 #endif 4867 4868 #if defined(PETSC_HAVE_TETGEN) 4869 #include <tetgen.h> 4870 #undef __FUNCT__ 4871 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4872 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4873 { 4874 MPI_Comm comm; 4875 const PetscInt dim = 3; 4876 ::tetgenio in; 4877 ::tetgenio out; 4878 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4879 PetscMPIInt rank; 4880 PetscErrorCode ierr; 4881 4882 PetscFunctionBegin; 4883 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4884 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4885 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4886 in.numberofpoints = vEnd - vStart; 4887 if (in.numberofpoints > 0) { 4888 PetscSection coordSection; 4889 Vec coordinates; 4890 PetscScalar *array; 4891 4892 in.pointlist = new double[in.numberofpoints*dim]; 4893 in.pointmarkerlist = new int[in.numberofpoints]; 4894 4895 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4896 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4897 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4898 for (v = vStart; v < vEnd; ++v) { 4899 const PetscInt idx = v - vStart; 4900 PetscInt off, d; 4901 4902 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4903 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4904 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4905 } 4906 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4907 } 4908 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4909 4910 in.numberoffacets = fEnd - fStart; 4911 if (in.numberoffacets > 0) { 4912 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4913 in.facetmarkerlist = new int[in.numberoffacets]; 4914 for (f = fStart; f < fEnd; ++f) { 4915 const PetscInt idx = f - fStart; 4916 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 4917 4918 in.facetlist[idx].numberofpolygons = 1; 4919 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4920 in.facetlist[idx].numberofholes = 0; 4921 in.facetlist[idx].holelist = NULL; 4922 4923 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4924 for (p = 0; p < numPoints*2; p += 2) { 4925 const PetscInt point = points[p]; 4926 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 4927 } 4928 4929 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4930 poly->numberofvertices = numVertices; 4931 poly->vertexlist = new int[poly->numberofvertices]; 4932 for (v = 0; v < numVertices; ++v) { 4933 const PetscInt vIdx = points[v] - vStart; 4934 poly->vertexlist[v] = vIdx; 4935 } 4936 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4937 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4938 } 4939 } 4940 if (!rank) { 4941 char args[32]; 4942 4943 /* Take away 'Q' for verbose output */ 4944 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4945 ::tetrahedralize(args, &in, &out); 4946 } 4947 { 4948 const PetscInt numCorners = 4; 4949 const PetscInt numCells = out.numberoftetrahedra; 4950 const PetscInt numVertices = out.numberofpoints; 4951 const int *cells = out.tetrahedronlist; 4952 const double *meshCoords = out.pointlist; 4953 4954 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4955 /* Set labels */ 4956 for (v = 0; v < numVertices; ++v) { 4957 if (out.pointmarkerlist[v]) { 4958 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4959 } 4960 } 4961 if (interpolate) { 4962 PetscInt e; 4963 4964 for (e = 0; e < out.numberofedges; e++) { 4965 if (out.edgemarkerlist[e]) { 4966 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4967 const PetscInt *edges; 4968 PetscInt numEdges; 4969 4970 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4971 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4972 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4973 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4974 } 4975 } 4976 for (f = 0; f < out.numberoftrifaces; f++) { 4977 if (out.trifacemarkerlist[f]) { 4978 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4979 const PetscInt *faces; 4980 PetscInt numFaces; 4981 4982 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4983 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4984 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4985 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4986 } 4987 } 4988 } 4989 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4990 } 4991 PetscFunctionReturn(0); 4992 } 4993 4994 #undef __FUNCT__ 4995 #define __FUNCT__ "DMPlexRefine_Tetgen" 4996 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4997 { 4998 MPI_Comm comm; 4999 const PetscInt dim = 3; 5000 ::tetgenio in; 5001 ::tetgenio out; 5002 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5003 PetscMPIInt rank; 5004 PetscErrorCode ierr; 5005 5006 PetscFunctionBegin; 5007 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5008 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5009 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5010 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5011 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5012 5013 in.numberofpoints = vEnd - vStart; 5014 if (in.numberofpoints > 0) { 5015 PetscSection coordSection; 5016 Vec coordinates; 5017 PetscScalar *array; 5018 5019 in.pointlist = new double[in.numberofpoints*dim]; 5020 in.pointmarkerlist = new int[in.numberofpoints]; 5021 5022 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5023 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5024 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5025 for (v = vStart; v < vEnd; ++v) { 5026 const PetscInt idx = v - vStart; 5027 PetscInt off, d; 5028 5029 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5030 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5031 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5032 } 5033 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5034 } 5035 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5036 5037 in.numberofcorners = 4; 5038 in.numberoftetrahedra = cEnd - cStart; 5039 in.tetrahedronvolumelist = (double*) maxVolumes; 5040 if (in.numberoftetrahedra > 0) { 5041 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5042 for (c = cStart; c < cEnd; ++c) { 5043 const PetscInt idx = c - cStart; 5044 PetscInt *closure = NULL; 5045 PetscInt closureSize; 5046 5047 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5048 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5049 for (v = 0; v < 4; ++v) { 5050 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5051 } 5052 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5053 } 5054 } 5055 /* TODO: Put in boundary faces with markers */ 5056 if (!rank) { 5057 char args[32]; 5058 5059 /* Take away 'Q' for verbose output */ 5060 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5061 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5062 ::tetrahedralize(args, &in, &out); 5063 } 5064 in.tetrahedronvolumelist = NULL; 5065 5066 { 5067 const PetscInt numCorners = 4; 5068 const PetscInt numCells = out.numberoftetrahedra; 5069 const PetscInt numVertices = out.numberofpoints; 5070 const int *cells = out.tetrahedronlist; 5071 const double *meshCoords = out.pointlist; 5072 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5073 5074 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 5075 /* Set labels */ 5076 for (v = 0; v < numVertices; ++v) { 5077 if (out.pointmarkerlist[v]) { 5078 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5079 } 5080 } 5081 if (interpolate) { 5082 PetscInt e, f; 5083 5084 for (e = 0; e < out.numberofedges; e++) { 5085 if (out.edgemarkerlist[e]) { 5086 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5087 const PetscInt *edges; 5088 PetscInt numEdges; 5089 5090 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5091 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5092 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5093 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5094 } 5095 } 5096 for (f = 0; f < out.numberoftrifaces; f++) { 5097 if (out.trifacemarkerlist[f]) { 5098 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5099 const PetscInt *faces; 5100 PetscInt numFaces; 5101 5102 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5103 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5104 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5105 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5106 } 5107 } 5108 } 5109 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5110 } 5111 PetscFunctionReturn(0); 5112 } 5113 #endif 5114 5115 #if defined(PETSC_HAVE_CTETGEN) 5116 #include "ctetgen.h" 5117 5118 #undef __FUNCT__ 5119 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5120 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5121 { 5122 MPI_Comm comm; 5123 const PetscInt dim = 3; 5124 PLC *in, *out; 5125 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5126 PetscMPIInt rank; 5127 PetscErrorCode ierr; 5128 5129 PetscFunctionBegin; 5130 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5131 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5132 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5133 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5134 ierr = PLCCreate(&in);CHKERRQ(ierr); 5135 ierr = PLCCreate(&out);CHKERRQ(ierr); 5136 5137 in->numberofpoints = vEnd - vStart; 5138 if (in->numberofpoints > 0) { 5139 PetscSection coordSection; 5140 Vec coordinates; 5141 PetscScalar *array; 5142 5143 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5144 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5145 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5146 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5147 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5148 for (v = vStart; v < vEnd; ++v) { 5149 const PetscInt idx = v - vStart; 5150 PetscInt off, d, m; 5151 5152 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5153 for (d = 0; d < dim; ++d) { 5154 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5155 } 5156 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5157 5158 in->pointmarkerlist[idx] = (int) m; 5159 } 5160 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5161 } 5162 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5163 5164 in->numberoffacets = fEnd - fStart; 5165 if (in->numberoffacets > 0) { 5166 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5167 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5168 for (f = fStart; f < fEnd; ++f) { 5169 const PetscInt idx = f - fStart; 5170 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5171 polygon *poly; 5172 5173 in->facetlist[idx].numberofpolygons = 1; 5174 5175 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5176 5177 in->facetlist[idx].numberofholes = 0; 5178 in->facetlist[idx].holelist = NULL; 5179 5180 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5181 for (p = 0; p < numPoints*2; p += 2) { 5182 const PetscInt point = points[p]; 5183 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5184 } 5185 5186 poly = in->facetlist[idx].polygonlist; 5187 poly->numberofvertices = numVertices; 5188 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5189 for (v = 0; v < numVertices; ++v) { 5190 const PetscInt vIdx = points[v] - vStart; 5191 poly->vertexlist[v] = vIdx; 5192 } 5193 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5194 in->facetmarkerlist[idx] = (int) m; 5195 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5196 } 5197 } 5198 if (!rank) { 5199 TetGenOpts t; 5200 5201 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5202 t.in = boundary; /* Should go away */ 5203 t.plc = 1; 5204 t.quality = 1; 5205 t.edgesout = 1; 5206 t.zeroindex = 1; 5207 t.quiet = 1; 5208 t.verbose = verbose; 5209 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5210 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5211 } 5212 { 5213 const PetscInt numCorners = 4; 5214 const PetscInt numCells = out->numberoftetrahedra; 5215 const PetscInt numVertices = out->numberofpoints; 5216 const int *cells = out->tetrahedronlist; 5217 const double *meshCoords = out->pointlist; 5218 5219 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 5220 /* Set labels */ 5221 for (v = 0; v < numVertices; ++v) { 5222 if (out->pointmarkerlist[v]) { 5223 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5224 } 5225 } 5226 if (interpolate) { 5227 PetscInt e; 5228 5229 for (e = 0; e < out->numberofedges; e++) { 5230 if (out->edgemarkerlist[e]) { 5231 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5232 const PetscInt *edges; 5233 PetscInt numEdges; 5234 5235 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5236 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5237 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5238 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5239 } 5240 } 5241 for (f = 0; f < out->numberoftrifaces; f++) { 5242 if (out->trifacemarkerlist[f]) { 5243 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5244 const PetscInt *faces; 5245 PetscInt numFaces; 5246 5247 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5248 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5249 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5250 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5251 } 5252 } 5253 } 5254 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5255 } 5256 5257 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5258 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5259 PetscFunctionReturn(0); 5260 } 5261 5262 #undef __FUNCT__ 5263 #define __FUNCT__ "DMPlexRefine_CTetgen" 5264 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5265 { 5266 MPI_Comm comm; 5267 const PetscInt dim = 3; 5268 PLC *in, *out; 5269 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5270 PetscMPIInt rank; 5271 PetscErrorCode ierr; 5272 5273 PetscFunctionBegin; 5274 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5275 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5276 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5277 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5278 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5279 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5280 ierr = PLCCreate(&in);CHKERRQ(ierr); 5281 ierr = PLCCreate(&out);CHKERRQ(ierr); 5282 5283 in->numberofpoints = vEnd - vStart; 5284 if (in->numberofpoints > 0) { 5285 PetscSection coordSection; 5286 Vec coordinates; 5287 PetscScalar *array; 5288 5289 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5290 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5291 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5292 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5293 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5294 for (v = vStart; v < vEnd; ++v) { 5295 const PetscInt idx = v - vStart; 5296 PetscInt off, d, m; 5297 5298 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5299 for (d = 0; d < dim; ++d) { 5300 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5301 } 5302 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5303 5304 in->pointmarkerlist[idx] = (int) m; 5305 } 5306 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5307 } 5308 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5309 5310 in->numberofcorners = 4; 5311 in->numberoftetrahedra = cEnd - cStart; 5312 in->tetrahedronvolumelist = maxVolumes; 5313 if (in->numberoftetrahedra > 0) { 5314 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5315 for (c = cStart; c < cEnd; ++c) { 5316 const PetscInt idx = c - cStart; 5317 PetscInt *closure = NULL; 5318 PetscInt closureSize; 5319 5320 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5321 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5322 for (v = 0; v < 4; ++v) { 5323 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5324 } 5325 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5326 } 5327 } 5328 if (!rank) { 5329 TetGenOpts t; 5330 5331 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5332 5333 t.in = dm; /* Should go away */ 5334 t.refine = 1; 5335 t.varvolume = 1; 5336 t.quality = 1; 5337 t.edgesout = 1; 5338 t.zeroindex = 1; 5339 t.quiet = 1; 5340 t.verbose = verbose; /* Change this */ 5341 5342 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5343 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5344 } 5345 { 5346 const PetscInt numCorners = 4; 5347 const PetscInt numCells = out->numberoftetrahedra; 5348 const PetscInt numVertices = out->numberofpoints; 5349 const int *cells = out->tetrahedronlist; 5350 const double *meshCoords = out->pointlist; 5351 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5352 5353 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 5354 /* Set labels */ 5355 for (v = 0; v < numVertices; ++v) { 5356 if (out->pointmarkerlist[v]) { 5357 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5358 } 5359 } 5360 if (interpolate) { 5361 PetscInt e, f; 5362 5363 for (e = 0; e < out->numberofedges; e++) { 5364 if (out->edgemarkerlist[e]) { 5365 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5366 const PetscInt *edges; 5367 PetscInt numEdges; 5368 5369 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5370 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5371 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5372 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5373 } 5374 } 5375 for (f = 0; f < out->numberoftrifaces; f++) { 5376 if (out->trifacemarkerlist[f]) { 5377 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5378 const PetscInt *faces; 5379 PetscInt numFaces; 5380 5381 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5382 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5383 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5384 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5385 } 5386 } 5387 } 5388 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5389 } 5390 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5391 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5392 PetscFunctionReturn(0); 5393 } 5394 #endif 5395 5396 #undef __FUNCT__ 5397 #define __FUNCT__ "DMPlexGenerate" 5398 /*@C 5399 DMPlexGenerate - Generates a mesh. 5400 5401 Not Collective 5402 5403 Input Parameters: 5404 + boundary - The DMPlex boundary object 5405 . name - The mesh generation package name 5406 - interpolate - Flag to create intermediate mesh elements 5407 5408 Output Parameter: 5409 . mesh - The DMPlex object 5410 5411 Level: intermediate 5412 5413 .keywords: mesh, elements 5414 .seealso: DMPlexCreate(), DMRefine() 5415 @*/ 5416 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5417 { 5418 PetscInt dim; 5419 char genname[1024]; 5420 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5421 PetscErrorCode ierr; 5422 5423 PetscFunctionBegin; 5424 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5425 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5426 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5427 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5428 if (flg) name = genname; 5429 if (name) { 5430 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5431 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5432 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5433 } 5434 switch (dim) { 5435 case 1: 5436 if (!name || isTriangle) { 5437 #if defined(PETSC_HAVE_TRIANGLE) 5438 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5439 #else 5440 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5441 #endif 5442 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5443 break; 5444 case 2: 5445 if (!name || isCTetgen) { 5446 #if defined(PETSC_HAVE_CTETGEN) 5447 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5448 #else 5449 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5450 #endif 5451 } else if (isTetgen) { 5452 #if defined(PETSC_HAVE_TETGEN) 5453 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5454 #else 5455 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5456 #endif 5457 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5458 break; 5459 default: 5460 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5461 } 5462 PetscFunctionReturn(0); 5463 } 5464 5465 typedef PetscInt CellRefiner; 5466 5467 #undef __FUNCT__ 5468 #define __FUNCT__ "GetDepthStart_Private" 5469 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5470 { 5471 PetscFunctionBegin; 5472 if (cStart) *cStart = 0; 5473 if (vStart) *vStart = depthSize[depth]; 5474 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5475 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5476 PetscFunctionReturn(0); 5477 } 5478 5479 #undef __FUNCT__ 5480 #define __FUNCT__ "GetDepthEnd_Private" 5481 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5482 { 5483 PetscFunctionBegin; 5484 if (cEnd) *cEnd = depthSize[depth]; 5485 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5486 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5487 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5488 PetscFunctionReturn(0); 5489 } 5490 5491 #undef __FUNCT__ 5492 #define __FUNCT__ "CellRefinerGetSizes" 5493 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5494 { 5495 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5496 PetscErrorCode ierr; 5497 5498 PetscFunctionBegin; 5499 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5500 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5501 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5502 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5503 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5504 switch (refiner) { 5505 case 1: 5506 /* Simplicial 2D */ 5507 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5508 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5509 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5510 break; 5511 case 3: 5512 /* Hybrid 2D */ 5513 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5514 cMax = PetscMin(cEnd, cMax); 5515 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5516 fMax = PetscMin(fEnd, fMax); 5517 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5518 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 */ 5519 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5520 break; 5521 case 2: 5522 /* Hex 2D */ 5523 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5524 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5525 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5526 break; 5527 default: 5528 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5529 } 5530 PetscFunctionReturn(0); 5531 } 5532 5533 #undef __FUNCT__ 5534 #define __FUNCT__ "CellRefinerSetConeSizes" 5535 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5536 { 5537 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5538 PetscErrorCode ierr; 5539 5540 PetscFunctionBegin; 5541 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5542 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5543 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5544 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5545 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5546 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5547 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5548 switch (refiner) { 5549 case 1: 5550 /* Simplicial 2D */ 5551 /* All cells have 3 faces */ 5552 for (c = cStart; c < cEnd; ++c) { 5553 for (r = 0; r < 4; ++r) { 5554 const PetscInt newp = (c - cStart)*4 + r; 5555 5556 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5557 } 5558 } 5559 /* Split faces have 2 vertices and the same cells as the parent */ 5560 for (f = fStart; f < fEnd; ++f) { 5561 for (r = 0; r < 2; ++r) { 5562 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5563 PetscInt size; 5564 5565 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5566 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5567 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5568 } 5569 } 5570 /* Interior faces have 2 vertices and 2 cells */ 5571 for (c = cStart; c < cEnd; ++c) { 5572 for (r = 0; r < 3; ++r) { 5573 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5574 5575 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5576 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5577 } 5578 } 5579 /* Old vertices have identical supports */ 5580 for (v = vStart; v < vEnd; ++v) { 5581 const PetscInt newp = vStartNew + (v - vStart); 5582 PetscInt size; 5583 5584 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5585 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5586 } 5587 /* Face vertices have 2 + cells*2 supports */ 5588 for (f = fStart; f < fEnd; ++f) { 5589 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5590 PetscInt size; 5591 5592 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5593 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5594 } 5595 break; 5596 case 2: 5597 /* Hex 2D */ 5598 /* All cells have 4 faces */ 5599 for (c = cStart; c < cEnd; ++c) { 5600 for (r = 0; r < 4; ++r) { 5601 const PetscInt newp = (c - cStart)*4 + r; 5602 5603 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5604 } 5605 } 5606 /* Split faces have 2 vertices and the same cells as the parent */ 5607 for (f = fStart; f < fEnd; ++f) { 5608 for (r = 0; r < 2; ++r) { 5609 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5610 PetscInt size; 5611 5612 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5613 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5614 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5615 } 5616 } 5617 /* Interior faces have 2 vertices and 2 cells */ 5618 for (c = cStart; c < cEnd; ++c) { 5619 for (r = 0; r < 4; ++r) { 5620 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5621 5622 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5623 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5624 } 5625 } 5626 /* Old vertices have identical supports */ 5627 for (v = vStart; v < vEnd; ++v) { 5628 const PetscInt newp = vStartNew + (v - vStart); 5629 PetscInt size; 5630 5631 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5632 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5633 } 5634 /* Face vertices have 2 + cells supports */ 5635 for (f = fStart; f < fEnd; ++f) { 5636 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5637 PetscInt size; 5638 5639 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5640 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5641 } 5642 /* Cell vertices have 4 supports */ 5643 for (c = cStart; c < cEnd; ++c) { 5644 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5645 5646 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5647 } 5648 break; 5649 case 3: 5650 /* Hybrid 2D */ 5651 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5652 cMax = PetscMin(cEnd, cMax); 5653 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5654 fMax = PetscMin(fEnd, fMax); 5655 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5656 /* Interior cells have 3 faces */ 5657 for (c = cStart; c < cMax; ++c) { 5658 for (r = 0; r < 4; ++r) { 5659 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5660 5661 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5662 } 5663 } 5664 /* Hybrid cells have 4 faces */ 5665 for (c = cMax; c < cEnd; ++c) { 5666 for (r = 0; r < 2; ++r) { 5667 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5668 5669 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5670 } 5671 } 5672 /* Interior split faces have 2 vertices and the same cells as the parent */ 5673 for (f = fStart; f < fMax; ++f) { 5674 for (r = 0; r < 2; ++r) { 5675 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5676 PetscInt size; 5677 5678 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5679 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5680 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5681 } 5682 } 5683 /* Interior cell faces have 2 vertices and 2 cells */ 5684 for (c = cStart; c < cMax; ++c) { 5685 for (r = 0; r < 3; ++r) { 5686 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5687 5688 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5689 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5690 } 5691 } 5692 /* Hybrid faces have 2 vertices and the same cells */ 5693 for (f = fMax; f < fEnd; ++f) { 5694 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5695 PetscInt size; 5696 5697 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5698 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5699 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5700 } 5701 /* Hybrid cell faces have 2 vertices and 2 cells */ 5702 for (c = cMax; c < cEnd; ++c) { 5703 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5704 5705 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5706 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5707 } 5708 /* Old vertices have identical supports */ 5709 for (v = vStart; v < vEnd; ++v) { 5710 const PetscInt newp = vStartNew + (v - vStart); 5711 PetscInt size; 5712 5713 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5714 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5715 } 5716 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5717 for (f = fStart; f < fMax; ++f) { 5718 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5719 const PetscInt *support; 5720 PetscInt size, newSize = 2, s; 5721 5722 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5723 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5724 for (s = 0; s < size; ++s) { 5725 if (support[s] >= cMax) newSize += 1; 5726 else newSize += 2; 5727 } 5728 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5729 } 5730 break; 5731 default: 5732 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5733 } 5734 PetscFunctionReturn(0); 5735 } 5736 5737 #undef __FUNCT__ 5738 #define __FUNCT__ "CellRefinerSetCones" 5739 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5740 { 5741 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; 5742 PetscInt maxSupportSize, *supportRef; 5743 PetscErrorCode ierr; 5744 5745 PetscFunctionBegin; 5746 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5747 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5748 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5749 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5750 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5751 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5752 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5753 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5754 switch (refiner) { 5755 case 1: 5756 /* Simplicial 2D */ 5757 /* 5758 2 5759 |\ 5760 | \ 5761 | \ 5762 | \ 5763 | C \ 5764 | \ 5765 | \ 5766 2---1---1 5767 |\ D / \ 5768 | 2 0 \ 5769 |A \ / B \ 5770 0---0-------1 5771 */ 5772 /* All cells have 3 faces */ 5773 for (c = cStart; c < cEnd; ++c) { 5774 const PetscInt newp = cStartNew + (c - cStart)*4; 5775 const PetscInt *cone, *ornt; 5776 PetscInt coneNew[3], orntNew[3]; 5777 5778 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5779 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5780 /* A triangle */ 5781 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5782 orntNew[0] = ornt[0]; 5783 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5784 orntNew[1] = -2; 5785 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5786 orntNew[2] = ornt[2]; 5787 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5788 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5789 #if 1 5790 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5791 for (p = 0; p < 3; ++p) { 5792 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5793 } 5794 #endif 5795 /* B triangle */ 5796 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5797 orntNew[0] = ornt[0]; 5798 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5799 orntNew[1] = ornt[1]; 5800 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5801 orntNew[2] = -2; 5802 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5803 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5804 #if 1 5805 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 5806 for (p = 0; p < 3; ++p) { 5807 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5808 } 5809 #endif 5810 /* C triangle */ 5811 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5812 orntNew[0] = -2; 5813 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5814 orntNew[1] = ornt[1]; 5815 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5816 orntNew[2] = ornt[2]; 5817 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5818 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5819 #if 1 5820 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 5821 for (p = 0; p < 3; ++p) { 5822 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5823 } 5824 #endif 5825 /* D triangle */ 5826 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5827 orntNew[0] = 0; 5828 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5829 orntNew[1] = 0; 5830 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5831 orntNew[2] = 0; 5832 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5833 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5834 #if 1 5835 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 5836 for (p = 0; p < 3; ++p) { 5837 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5838 } 5839 #endif 5840 } 5841 /* Split faces have 2 vertices and the same cells as the parent */ 5842 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5843 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5844 for (f = fStart; f < fEnd; ++f) { 5845 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5846 5847 for (r = 0; r < 2; ++r) { 5848 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5849 const PetscInt *cone, *support; 5850 PetscInt coneNew[2], coneSize, c, supportSize, s; 5851 5852 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5853 coneNew[0] = vStartNew + (cone[0] - vStart); 5854 coneNew[1] = vStartNew + (cone[1] - vStart); 5855 coneNew[(r+1)%2] = newv; 5856 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5857 #if 1 5858 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5859 for (p = 0; p < 2; ++p) { 5860 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5861 } 5862 #endif 5863 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5864 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5865 for (s = 0; s < supportSize; ++s) { 5866 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5867 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5868 for (c = 0; c < coneSize; ++c) { 5869 if (cone[c] == f) break; 5870 } 5871 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5872 } 5873 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5874 #if 1 5875 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5876 for (p = 0; p < supportSize; ++p) { 5877 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 5878 } 5879 #endif 5880 } 5881 } 5882 /* Interior faces have 2 vertices and 2 cells */ 5883 for (c = cStart; c < cEnd; ++c) { 5884 const PetscInt *cone; 5885 5886 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5887 for (r = 0; r < 3; ++r) { 5888 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5889 PetscInt coneNew[2]; 5890 PetscInt supportNew[2]; 5891 5892 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5893 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5894 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5895 #if 1 5896 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5897 for (p = 0; p < 2; ++p) { 5898 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5899 } 5900 #endif 5901 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5902 supportNew[1] = (c - cStart)*4 + 3; 5903 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5904 #if 1 5905 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5906 for (p = 0; p < 2; ++p) { 5907 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5908 } 5909 #endif 5910 } 5911 } 5912 /* Old vertices have identical supports */ 5913 for (v = vStart; v < vEnd; ++v) { 5914 const PetscInt newp = vStartNew + (v - vStart); 5915 const PetscInt *support, *cone; 5916 PetscInt size, s; 5917 5918 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5919 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5920 for (s = 0; s < size; ++s) { 5921 PetscInt r = 0; 5922 5923 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5924 if (cone[1] == v) r = 1; 5925 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5926 } 5927 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5928 #if 1 5929 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5930 for (p = 0; p < size; ++p) { 5931 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5932 } 5933 #endif 5934 } 5935 /* Face vertices have 2 + cells*2 supports */ 5936 for (f = fStart; f < fEnd; ++f) { 5937 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5938 const PetscInt *cone, *support; 5939 PetscInt size, s; 5940 5941 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5942 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5943 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5944 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5945 for (s = 0; s < size; ++s) { 5946 PetscInt r = 0; 5947 5948 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5949 if (cone[1] == f) r = 1; 5950 else if (cone[2] == f) r = 2; 5951 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5952 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5953 } 5954 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5955 #if 1 5956 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5957 for (p = 0; p < 2+size*2; ++p) { 5958 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5959 } 5960 #endif 5961 } 5962 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5963 break; 5964 case 2: 5965 /* Hex 2D */ 5966 /* 5967 3---------2---------2 5968 | | | 5969 | D 2 C | 5970 | | | 5971 3----3----0----1----1 5972 | | | 5973 | A 0 B | 5974 | | | 5975 0---------0---------1 5976 */ 5977 /* All cells have 4 faces */ 5978 for (c = cStart; c < cEnd; ++c) { 5979 const PetscInt newp = (c - cStart)*4; 5980 const PetscInt *cone, *ornt; 5981 PetscInt coneNew[4], orntNew[4]; 5982 5983 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5984 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5985 /* A quad */ 5986 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5987 orntNew[0] = ornt[0]; 5988 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5989 orntNew[1] = 0; 5990 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5991 orntNew[2] = -2; 5992 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5993 orntNew[3] = ornt[3]; 5994 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5995 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5996 #if 1 5997 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5998 for (p = 0; p < 4; ++p) { 5999 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6000 } 6001 #endif 6002 /* B quad */ 6003 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6004 orntNew[0] = ornt[0]; 6005 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6006 orntNew[1] = ornt[1]; 6007 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6008 orntNew[2] = 0; 6009 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6010 orntNew[3] = -2; 6011 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6012 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6013 #if 1 6014 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6015 for (p = 0; p < 4; ++p) { 6016 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6017 } 6018 #endif 6019 /* C quad */ 6020 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6021 orntNew[0] = -2; 6022 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6023 orntNew[1] = ornt[1]; 6024 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6025 orntNew[2] = ornt[2]; 6026 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6027 orntNew[3] = 0; 6028 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6029 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6030 #if 1 6031 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6032 for (p = 0; p < 4; ++p) { 6033 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6034 } 6035 #endif 6036 /* D quad */ 6037 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6038 orntNew[0] = 0; 6039 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6040 orntNew[1] = -2; 6041 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6042 orntNew[2] = ornt[2]; 6043 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6044 orntNew[3] = ornt[3]; 6045 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6046 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6047 #if 1 6048 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6049 for (p = 0; p < 4; ++p) { 6050 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6051 } 6052 #endif 6053 } 6054 /* Split faces have 2 vertices and the same cells as the parent */ 6055 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6056 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6057 for (f = fStart; f < fEnd; ++f) { 6058 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6059 6060 for (r = 0; r < 2; ++r) { 6061 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6062 const PetscInt *cone, *support; 6063 PetscInt coneNew[2], coneSize, c, supportSize, s; 6064 6065 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6066 coneNew[0] = vStartNew + (cone[0] - vStart); 6067 coneNew[1] = vStartNew + (cone[1] - vStart); 6068 coneNew[(r+1)%2] = newv; 6069 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6070 #if 1 6071 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6072 for (p = 0; p < 2; ++p) { 6073 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6074 } 6075 #endif 6076 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6077 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6078 for (s = 0; s < supportSize; ++s) { 6079 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6080 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6081 for (c = 0; c < coneSize; ++c) { 6082 if (cone[c] == f) break; 6083 } 6084 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6085 } 6086 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6087 #if 1 6088 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6089 for (p = 0; p < supportSize; ++p) { 6090 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6091 } 6092 #endif 6093 } 6094 } 6095 /* Interior faces have 2 vertices and 2 cells */ 6096 for (c = cStart; c < cEnd; ++c) { 6097 const PetscInt *cone; 6098 PetscInt coneNew[2], supportNew[2]; 6099 6100 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6101 for (r = 0; r < 4; ++r) { 6102 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6103 6104 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6105 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6106 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6107 #if 1 6108 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6109 for (p = 0; p < 2; ++p) { 6110 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6111 } 6112 #endif 6113 supportNew[0] = (c - cStart)*4 + r; 6114 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6115 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6116 #if 1 6117 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6118 for (p = 0; p < 2; ++p) { 6119 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6120 } 6121 #endif 6122 } 6123 } 6124 /* Old vertices have identical supports */ 6125 for (v = vStart; v < vEnd; ++v) { 6126 const PetscInt newp = vStartNew + (v - vStart); 6127 const PetscInt *support, *cone; 6128 PetscInt size, s; 6129 6130 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6131 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6132 for (s = 0; s < size; ++s) { 6133 PetscInt r = 0; 6134 6135 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6136 if (cone[1] == v) r = 1; 6137 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6138 } 6139 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6140 #if 1 6141 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6142 for (p = 0; p < size; ++p) { 6143 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6144 } 6145 #endif 6146 } 6147 /* Face vertices have 2 + cells supports */ 6148 for (f = fStart; f < fEnd; ++f) { 6149 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6150 const PetscInt *cone, *support; 6151 PetscInt size, s; 6152 6153 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6154 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6155 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6156 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6157 for (s = 0; s < size; ++s) { 6158 PetscInt r = 0; 6159 6160 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6161 if (cone[1] == f) r = 1; 6162 else if (cone[2] == f) r = 2; 6163 else if (cone[3] == f) r = 3; 6164 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6165 } 6166 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6167 #if 1 6168 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6169 for (p = 0; p < 2+size; ++p) { 6170 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6171 } 6172 #endif 6173 } 6174 /* Cell vertices have 4 supports */ 6175 for (c = cStart; c < cEnd; ++c) { 6176 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6177 PetscInt supportNew[4]; 6178 6179 for (r = 0; r < 4; ++r) { 6180 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6181 } 6182 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6183 } 6184 break; 6185 case 3: 6186 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6187 cMax = PetscMin(cEnd, cMax); 6188 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6189 fMax = PetscMin(fEnd, fMax); 6190 /* Interior cells have 3 faces */ 6191 for (c = cStart; c < cMax; ++c) { 6192 const PetscInt newp = cStartNew + (c - cStart)*4; 6193 const PetscInt *cone, *ornt; 6194 PetscInt coneNew[3], orntNew[3]; 6195 6196 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6197 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6198 /* A triangle */ 6199 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6200 orntNew[0] = ornt[0]; 6201 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6202 orntNew[1] = -2; 6203 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6204 orntNew[2] = ornt[2]; 6205 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6206 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6207 #if 1 6208 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6209 for (p = 0; p < 3; ++p) { 6210 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6211 } 6212 #endif 6213 /* B triangle */ 6214 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6215 orntNew[0] = ornt[0]; 6216 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6217 orntNew[1] = ornt[1]; 6218 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6219 orntNew[2] = -2; 6220 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6221 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6222 #if 1 6223 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6224 for (p = 0; p < 3; ++p) { 6225 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6226 } 6227 #endif 6228 /* C triangle */ 6229 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6230 orntNew[0] = -2; 6231 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6232 orntNew[1] = ornt[1]; 6233 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6234 orntNew[2] = ornt[2]; 6235 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6236 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6237 #if 1 6238 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6239 for (p = 0; p < 3; ++p) { 6240 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6241 } 6242 #endif 6243 /* D triangle */ 6244 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6245 orntNew[0] = 0; 6246 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6247 orntNew[1] = 0; 6248 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6249 orntNew[2] = 0; 6250 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6251 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6252 #if 1 6253 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6254 for (p = 0; p < 3; ++p) { 6255 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6256 } 6257 #endif 6258 } 6259 /* 6260 2----3----3 6261 | | 6262 | B | 6263 | | 6264 0----4--- 1 6265 | | 6266 | A | 6267 | | 6268 0----2----1 6269 */ 6270 /* Hybrid cells have 4 faces */ 6271 for (c = cMax; c < cEnd; ++c) { 6272 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6273 const PetscInt *cone, *ornt; 6274 PetscInt coneNew[4], orntNew[4]; 6275 6276 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6277 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6278 /* A quad */ 6279 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6280 orntNew[0] = ornt[0]; 6281 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6282 orntNew[1] = ornt[1]; 6283 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6284 orntNew[2] = 0; 6285 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6286 orntNew[3] = 0; 6287 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6288 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6289 #if 1 6290 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6291 for (p = 0; p < 4; ++p) { 6292 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6293 } 6294 #endif 6295 /* B quad */ 6296 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6297 orntNew[0] = ornt[0]; 6298 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6299 orntNew[1] = ornt[1]; 6300 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6301 orntNew[2] = 0; 6302 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6303 orntNew[3] = 0; 6304 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6305 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6306 #if 1 6307 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6308 for (p = 0; p < 4; ++p) { 6309 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6310 } 6311 #endif 6312 } 6313 /* Interior split faces have 2 vertices and the same cells as the parent */ 6314 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6315 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6316 for (f = fStart; f < fMax; ++f) { 6317 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6318 6319 for (r = 0; r < 2; ++r) { 6320 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6321 const PetscInt *cone, *support; 6322 PetscInt coneNew[2], coneSize, c, supportSize, s; 6323 6324 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6325 coneNew[0] = vStartNew + (cone[0] - vStart); 6326 coneNew[1] = vStartNew + (cone[1] - vStart); 6327 coneNew[(r+1)%2] = newv; 6328 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6329 #if 1 6330 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6331 for (p = 0; p < 2; ++p) { 6332 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6333 } 6334 #endif 6335 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6336 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6337 for (s = 0; s < supportSize; ++s) { 6338 if (support[s] >= cMax) { 6339 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6340 } else { 6341 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6342 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6343 for (c = 0; c < coneSize; ++c) { 6344 if (cone[c] == f) break; 6345 } 6346 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6347 } 6348 } 6349 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6350 #if 1 6351 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6352 for (p = 0; p < supportSize; ++p) { 6353 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6354 } 6355 #endif 6356 } 6357 } 6358 /* Interior cell faces have 2 vertices and 2 cells */ 6359 for (c = cStart; c < cMax; ++c) { 6360 const PetscInt *cone; 6361 6362 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6363 for (r = 0; r < 3; ++r) { 6364 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6365 PetscInt coneNew[2]; 6366 PetscInt supportNew[2]; 6367 6368 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6369 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6370 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6371 #if 1 6372 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6373 for (p = 0; p < 2; ++p) { 6374 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6375 } 6376 #endif 6377 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6378 supportNew[1] = (c - cStart)*4 + 3; 6379 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6380 #if 1 6381 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6382 for (p = 0; p < 2; ++p) { 6383 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6384 } 6385 #endif 6386 } 6387 } 6388 /* Interior hybrid faces have 2 vertices and the same cells */ 6389 for (f = fMax; f < fEnd; ++f) { 6390 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6391 const PetscInt *cone; 6392 const PetscInt *support; 6393 PetscInt coneNew[2]; 6394 PetscInt supportNew[2]; 6395 PetscInt size, s, r; 6396 6397 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6398 coneNew[0] = vStartNew + (cone[0] - vStart); 6399 coneNew[1] = vStartNew + (cone[1] - vStart); 6400 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6401 #if 1 6402 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6403 for (p = 0; p < 2; ++p) { 6404 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6405 } 6406 #endif 6407 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6408 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6409 for (s = 0; s < size; ++s) { 6410 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6411 for (r = 0; r < 2; ++r) { 6412 if (cone[r+2] == f) break; 6413 } 6414 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6415 } 6416 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6417 #if 1 6418 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6419 for (p = 0; p < size; ++p) { 6420 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6421 } 6422 #endif 6423 } 6424 /* Cell hybrid faces have 2 vertices and 2 cells */ 6425 for (c = cMax; c < cEnd; ++c) { 6426 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6427 const PetscInt *cone; 6428 PetscInt coneNew[2]; 6429 PetscInt supportNew[2]; 6430 6431 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6432 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6433 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6434 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6435 #if 1 6436 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6437 for (p = 0; p < 2; ++p) { 6438 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6439 } 6440 #endif 6441 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6442 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6443 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6444 #if 1 6445 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6446 for (p = 0; p < 2; ++p) { 6447 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6448 } 6449 #endif 6450 } 6451 /* Old vertices have identical supports */ 6452 for (v = vStart; v < vEnd; ++v) { 6453 const PetscInt newp = vStartNew + (v - vStart); 6454 const PetscInt *support, *cone; 6455 PetscInt size, s; 6456 6457 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6458 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6459 for (s = 0; s < size; ++s) { 6460 if (support[s] >= fMax) { 6461 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6462 } else { 6463 PetscInt r = 0; 6464 6465 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6466 if (cone[1] == v) r = 1; 6467 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6468 } 6469 } 6470 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6471 #if 1 6472 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6473 for (p = 0; p < size; ++p) { 6474 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6475 } 6476 #endif 6477 } 6478 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6479 for (f = fStart; f < fMax; ++f) { 6480 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6481 const PetscInt *cone, *support; 6482 PetscInt size, newSize = 2, s; 6483 6484 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6485 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6486 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6487 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6488 for (s = 0; s < size; ++s) { 6489 PetscInt r = 0; 6490 6491 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6492 if (support[s] >= cMax) { 6493 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6494 6495 newSize += 1; 6496 } else { 6497 if (cone[1] == f) r = 1; 6498 else if (cone[2] == f) r = 2; 6499 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6500 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6501 6502 newSize += 2; 6503 } 6504 } 6505 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6506 #if 1 6507 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6508 for (p = 0; p < newSize; ++p) { 6509 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6510 } 6511 #endif 6512 } 6513 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6514 break; 6515 default: 6516 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6517 } 6518 PetscFunctionReturn(0); 6519 } 6520 6521 #undef __FUNCT__ 6522 #define __FUNCT__ "CellRefinerSetCoordinates" 6523 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6524 { 6525 PetscSection coordSection, coordSectionNew; 6526 Vec coordinates, coordinatesNew; 6527 PetscScalar *coords, *coordsNew; 6528 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6529 PetscErrorCode ierr; 6530 6531 PetscFunctionBegin; 6532 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6533 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6534 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6535 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6536 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6537 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6538 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6539 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6540 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6541 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6542 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6543 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6544 if (fMax < 0) fMax = fEnd; 6545 switch (refiner) { 6546 case 1: 6547 case 2: 6548 case 3: 6549 /* Simplicial and Hex 2D */ 6550 /* All vertices have the dim coordinates */ 6551 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6552 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6553 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6554 } 6555 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6556 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6557 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6558 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6559 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6560 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6561 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6562 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6563 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6564 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6565 /* Old vertices have the same coordinates */ 6566 for (v = vStart; v < vEnd; ++v) { 6567 const PetscInt newv = vStartNew + (v - vStart); 6568 PetscInt off, offnew, d; 6569 6570 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6571 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6572 for (d = 0; d < dim; ++d) { 6573 coordsNew[offnew+d] = coords[off+d]; 6574 } 6575 } 6576 /* Face vertices have the average of endpoint coordinates */ 6577 for (f = fStart; f < fMax; ++f) { 6578 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6579 const PetscInt *cone; 6580 PetscInt coneSize, offA, offB, offnew, d; 6581 6582 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6583 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6584 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6585 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6586 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6587 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6588 for (d = 0; d < dim; ++d) { 6589 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6590 } 6591 } 6592 /* Just Hex 2D */ 6593 if (refiner == 2) { 6594 /* Cell vertices have the average of corner coordinates */ 6595 for (c = cStart; c < cEnd; ++c) { 6596 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6597 PetscInt *cone = NULL; 6598 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6599 6600 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6601 for (p = 0; p < closureSize*2; p += 2) { 6602 const PetscInt point = cone[p]; 6603 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6604 } 6605 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6606 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6607 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6608 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6609 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6610 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6611 for (d = 0; d < dim; ++d) { 6612 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6613 } 6614 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6615 } 6616 } 6617 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6618 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6619 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6620 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6621 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 6622 break; 6623 default: 6624 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6625 } 6626 PetscFunctionReturn(0); 6627 } 6628 6629 #undef __FUNCT__ 6630 #define __FUNCT__ "DMPlexCreateProcessSF" 6631 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6632 { 6633 PetscInt numRoots, numLeaves, l; 6634 const PetscInt *localPoints; 6635 const PetscSFNode *remotePoints; 6636 PetscInt *localPointsNew; 6637 PetscSFNode *remotePointsNew; 6638 PetscInt *ranks, *ranksNew; 6639 PetscErrorCode ierr; 6640 6641 PetscFunctionBegin; 6642 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6643 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6644 for (l = 0; l < numLeaves; ++l) { 6645 ranks[l] = remotePoints[l].rank; 6646 } 6647 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6648 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6649 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6650 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6651 for (l = 0; l < numLeaves; ++l) { 6652 ranksNew[l] = ranks[l]; 6653 localPointsNew[l] = l; 6654 remotePointsNew[l].index = 0; 6655 remotePointsNew[l].rank = ranksNew[l]; 6656 } 6657 ierr = PetscFree(ranks);CHKERRQ(ierr); 6658 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6659 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 6660 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6661 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6662 PetscFunctionReturn(0); 6663 } 6664 6665 #undef __FUNCT__ 6666 #define __FUNCT__ "CellRefinerCreateSF" 6667 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6668 { 6669 PetscSF sf, sfNew, sfProcess; 6670 IS processRanks; 6671 MPI_Datatype depthType; 6672 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6673 const PetscInt *localPoints, *neighbors; 6674 const PetscSFNode *remotePoints; 6675 PetscInt *localPointsNew; 6676 PetscSFNode *remotePointsNew; 6677 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6678 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6679 PetscErrorCode ierr; 6680 6681 PetscFunctionBegin; 6682 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6683 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6684 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6685 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6686 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6687 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6688 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6689 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6690 switch (refiner) { 6691 case 3: 6692 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6693 cMax = PetscMin(cEnd, cMax); 6694 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6695 fMax = PetscMin(fEnd, fMax); 6696 } 6697 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6698 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6699 /* Caculate size of new SF */ 6700 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6701 if (numRoots < 0) PetscFunctionReturn(0); 6702 for (l = 0; l < numLeaves; ++l) { 6703 const PetscInt p = localPoints[l]; 6704 6705 switch (refiner) { 6706 case 1: 6707 /* Simplicial 2D */ 6708 if ((p >= vStart) && (p < vEnd)) { 6709 /* Old vertices stay the same */ 6710 ++numLeavesNew; 6711 } else if ((p >= fStart) && (p < fEnd)) { 6712 /* Old faces add new faces and vertex */ 6713 numLeavesNew += 1 + 2; 6714 } else if ((p >= cStart) && (p < cEnd)) { 6715 /* Old cells add new cells and interior faces */ 6716 numLeavesNew += 4 + 3; 6717 } 6718 break; 6719 case 2: 6720 /* Hex 2D */ 6721 if ((p >= vStart) && (p < vEnd)) { 6722 /* Old vertices stay the same */ 6723 ++numLeavesNew; 6724 } else if ((p >= fStart) && (p < fEnd)) { 6725 /* Old faces add new faces and vertex */ 6726 numLeavesNew += 1 + 2; 6727 } else if ((p >= cStart) && (p < cEnd)) { 6728 /* Old cells add new cells and interior faces */ 6729 numLeavesNew += 4 + 4; 6730 } 6731 break; 6732 default: 6733 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6734 } 6735 } 6736 /* Communicate depthSizes for each remote rank */ 6737 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6738 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6739 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6740 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); 6741 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6742 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6743 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6744 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6745 for (n = 0; n < numNeighbors; ++n) { 6746 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6747 } 6748 depthSizeOld[depth] = cMax; 6749 depthSizeOld[0] = vMax; 6750 depthSizeOld[depth-1] = fMax; 6751 depthSizeOld[1] = eMax; 6752 6753 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6754 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6755 6756 depthSizeOld[depth] = cEnd - cStart; 6757 depthSizeOld[0] = vEnd - vStart; 6758 depthSizeOld[depth-1] = fEnd - fStart; 6759 depthSizeOld[1] = eEnd - eStart; 6760 6761 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6762 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6763 for (n = 0; n < numNeighbors; ++n) { 6764 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6765 } 6766 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6767 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6768 /* Calculate new point SF */ 6769 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6770 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6771 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6772 for (l = 0, m = 0; l < numLeaves; ++l) { 6773 PetscInt p = localPoints[l]; 6774 PetscInt rp = remotePoints[l].index, n; 6775 PetscMPIInt rrank = remotePoints[l].rank; 6776 6777 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6778 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6779 switch (refiner) { 6780 case 1: 6781 /* Simplicial 2D */ 6782 if ((p >= vStart) && (p < vEnd)) { 6783 /* Old vertices stay the same */ 6784 localPointsNew[m] = vStartNew + (p - vStart); 6785 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6786 remotePointsNew[m].rank = rrank; 6787 ++m; 6788 } else if ((p >= fStart) && (p < fEnd)) { 6789 /* Old faces add new faces and vertex */ 6790 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6791 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6792 remotePointsNew[m].rank = rrank; 6793 ++m; 6794 for (r = 0; r < 2; ++r, ++m) { 6795 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6796 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6797 remotePointsNew[m].rank = rrank; 6798 } 6799 } else if ((p >= cStart) && (p < cEnd)) { 6800 /* Old cells add new cells and interior faces */ 6801 for (r = 0; r < 4; ++r, ++m) { 6802 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6803 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6804 remotePointsNew[m].rank = rrank; 6805 } 6806 for (r = 0; r < 3; ++r, ++m) { 6807 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6808 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6809 remotePointsNew[m].rank = rrank; 6810 } 6811 } 6812 break; 6813 case 2: 6814 /* Hex 2D */ 6815 if ((p >= vStart) && (p < vEnd)) { 6816 /* Old vertices stay the same */ 6817 localPointsNew[m] = vStartNew + (p - vStart); 6818 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6819 remotePointsNew[m].rank = rrank; 6820 ++m; 6821 } else if ((p >= fStart) && (p < fEnd)) { 6822 /* Old faces add new faces and vertex */ 6823 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6824 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6825 remotePointsNew[m].rank = rrank; 6826 ++m; 6827 for (r = 0; r < 2; ++r, ++m) { 6828 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6829 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6830 remotePointsNew[m].rank = rrank; 6831 } 6832 } else if ((p >= cStart) && (p < cEnd)) { 6833 /* Old cells add new cells and interior faces */ 6834 for (r = 0; r < 4; ++r, ++m) { 6835 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6836 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6837 remotePointsNew[m].rank = rrank; 6838 } 6839 for (r = 0; r < 4; ++r, ++m) { 6840 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6841 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6842 remotePointsNew[m].rank = rrank; 6843 } 6844 } 6845 break; 6846 case 3: 6847 /* Hybrid simplicial 2D */ 6848 if ((p >= vStart) && (p < vEnd)) { 6849 /* Old vertices stay the same */ 6850 localPointsNew[m] = vStartNew + (p - vStart); 6851 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6852 remotePointsNew[m].rank = rrank; 6853 ++m; 6854 } else if ((p >= fStart) && (p < fMax)) { 6855 /* Old interior faces add new faces and vertex */ 6856 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6857 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6858 remotePointsNew[m].rank = rrank; 6859 ++m; 6860 for (r = 0; r < 2; ++r, ++m) { 6861 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6862 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6863 remotePointsNew[m].rank = rrank; 6864 } 6865 } else if ((p >= fMax) && (p < fEnd)) { 6866 /* Old hybrid faces stay the same */ 6867 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6868 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6869 remotePointsNew[m].rank = rrank; 6870 ++m; 6871 } else if ((p >= cStart) && (p < cMax)) { 6872 /* Old interior cells add new cells and interior faces */ 6873 for (r = 0; r < 4; ++r, ++m) { 6874 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6875 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6876 remotePointsNew[m].rank = rrank; 6877 } 6878 for (r = 0; r < 3; ++r, ++m) { 6879 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6880 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6881 remotePointsNew[m].rank = rrank; 6882 } 6883 } else if ((p >= cStart) && (p < cMax)) { 6884 /* Old hybrid cells add new cells and hybrid face */ 6885 for (r = 0; r < 2; ++r, ++m) { 6886 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6887 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6888 remotePointsNew[m].rank = rrank; 6889 } 6890 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6891 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]); 6892 remotePointsNew[m].rank = rrank; 6893 ++m; 6894 } 6895 break; 6896 default: 6897 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6898 } 6899 } 6900 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6901 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6902 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6903 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6904 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6905 PetscFunctionReturn(0); 6906 } 6907 6908 #undef __FUNCT__ 6909 #define __FUNCT__ "CellRefinerCreateLabels" 6910 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6911 { 6912 PetscInt numLabels, l; 6913 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6914 PetscErrorCode ierr; 6915 6916 PetscFunctionBegin; 6917 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6918 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6919 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6920 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6921 6922 cStartNew = 0; 6923 vStartNew = depthSize[2]; 6924 fStartNew = depthSize[2] + depthSize[0]; 6925 6926 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6927 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6928 switch (refiner) { 6929 case 3: 6930 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6931 cMax = PetscMin(cEnd, cMax); 6932 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6933 fMax = PetscMin(fEnd, fMax); 6934 } 6935 for (l = 0; l < numLabels; ++l) { 6936 DMLabel label, labelNew; 6937 const char *lname; 6938 PetscBool isDepth; 6939 IS valueIS; 6940 const PetscInt *values; 6941 PetscInt numValues, val; 6942 6943 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6944 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6945 if (isDepth) continue; 6946 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6947 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6948 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6949 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6950 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6951 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6952 for (val = 0; val < numValues; ++val) { 6953 IS pointIS; 6954 const PetscInt *points; 6955 PetscInt numPoints, n; 6956 6957 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6958 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6959 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6960 for (n = 0; n < numPoints; ++n) { 6961 const PetscInt p = points[n]; 6962 switch (refiner) { 6963 case 1: 6964 /* Simplicial 2D */ 6965 if ((p >= vStart) && (p < vEnd)) { 6966 /* Old vertices stay the same */ 6967 newp = vStartNew + (p - vStart); 6968 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6969 } else if ((p >= fStart) && (p < fEnd)) { 6970 /* Old faces add new faces and vertex */ 6971 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6972 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6973 for (r = 0; r < 2; ++r) { 6974 newp = fStartNew + (p - fStart)*2 + r; 6975 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6976 } 6977 } else if ((p >= cStart) && (p < cEnd)) { 6978 /* Old cells add new cells and interior faces */ 6979 for (r = 0; r < 4; ++r) { 6980 newp = cStartNew + (p - cStart)*4 + r; 6981 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6982 } 6983 for (r = 0; r < 3; ++r) { 6984 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6985 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6986 } 6987 } 6988 break; 6989 case 2: 6990 /* Hex 2D */ 6991 if ((p >= vStart) && (p < vEnd)) { 6992 /* Old vertices stay the same */ 6993 newp = vStartNew + (p - vStart); 6994 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6995 } else if ((p >= fStart) && (p < fEnd)) { 6996 /* Old faces add new faces and vertex */ 6997 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6998 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6999 for (r = 0; r < 2; ++r) { 7000 newp = fStartNew + (p - fStart)*2 + r; 7001 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7002 } 7003 } else if ((p >= cStart) && (p < cEnd)) { 7004 /* Old cells add new cells and interior faces and vertex */ 7005 for (r = 0; r < 4; ++r) { 7006 newp = cStartNew + (p - cStart)*4 + r; 7007 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7008 } 7009 for (r = 0; r < 4; ++r) { 7010 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7011 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7012 } 7013 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7014 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7015 } 7016 break; 7017 case 3: 7018 /* Hybrid simplicial 2D */ 7019 if ((p >= vStart) && (p < vEnd)) { 7020 /* Old vertices stay the same */ 7021 newp = vStartNew + (p - vStart); 7022 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7023 } else if ((p >= fStart) && (p < fMax)) { 7024 /* Old interior faces add new faces and vertex */ 7025 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7026 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7027 for (r = 0; r < 2; ++r) { 7028 newp = fStartNew + (p - fStart)*2 + r; 7029 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7030 } 7031 } else if ((p >= fMax) && (p < fEnd)) { 7032 /* Old hybrid faces stay the same */ 7033 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7034 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7035 } else if ((p >= cStart) && (p < cMax)) { 7036 /* Old interior cells add new cells and interior faces */ 7037 for (r = 0; r < 4; ++r) { 7038 newp = cStartNew + (p - cStart)*4 + r; 7039 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7040 } 7041 for (r = 0; r < 3; ++r) { 7042 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7043 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7044 } 7045 } else if ((p >= cMax) && (p < cEnd)) { 7046 /* Old hybrid cells add new cells and hybrid face */ 7047 for (r = 0; r < 2; ++r) { 7048 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7049 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7050 } 7051 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7052 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7053 } 7054 break; 7055 default: 7056 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7057 } 7058 } 7059 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7060 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7061 } 7062 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7063 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7064 if (0) { 7065 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7066 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7067 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7068 } 7069 } 7070 PetscFunctionReturn(0); 7071 } 7072 7073 #undef __FUNCT__ 7074 #define __FUNCT__ "DMPlexRefine_Uniform" 7075 /* This will only work for interpolated meshes */ 7076 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7077 { 7078 DM rdm; 7079 PetscInt *depthSize; 7080 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7081 PetscErrorCode ierr; 7082 7083 PetscFunctionBegin; 7084 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 7085 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7086 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7087 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7088 /* Calculate number of new points of each depth */ 7089 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7090 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7091 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7092 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7093 /* Step 1: Set chart */ 7094 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7095 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7096 /* Step 2: Set cone/support sizes */ 7097 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7098 /* Step 3: Setup refined DM */ 7099 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7100 /* Step 4: Set cones and supports */ 7101 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7102 /* Step 5: Stratify */ 7103 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7104 /* Step 6: Set coordinates for vertices */ 7105 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7106 /* Step 7: Create pointSF */ 7107 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7108 /* Step 8: Create labels */ 7109 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7110 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7111 7112 *dmRefined = rdm; 7113 PetscFunctionReturn(0); 7114 } 7115 7116 #undef __FUNCT__ 7117 #define __FUNCT__ "DMPlexSetRefinementUniform" 7118 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7119 { 7120 DM_Plex *mesh = (DM_Plex*) dm->data; 7121 7122 PetscFunctionBegin; 7123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7124 mesh->refinementUniform = refinementUniform; 7125 PetscFunctionReturn(0); 7126 } 7127 7128 #undef __FUNCT__ 7129 #define __FUNCT__ "DMPlexGetRefinementUniform" 7130 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7131 { 7132 DM_Plex *mesh = (DM_Plex*) dm->data; 7133 7134 PetscFunctionBegin; 7135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7136 PetscValidPointer(refinementUniform, 2); 7137 *refinementUniform = mesh->refinementUniform; 7138 PetscFunctionReturn(0); 7139 } 7140 7141 #undef __FUNCT__ 7142 #define __FUNCT__ "DMPlexSetRefinementLimit" 7143 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7144 { 7145 DM_Plex *mesh = (DM_Plex*) dm->data; 7146 7147 PetscFunctionBegin; 7148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7149 mesh->refinementLimit = refinementLimit; 7150 PetscFunctionReturn(0); 7151 } 7152 7153 #undef __FUNCT__ 7154 #define __FUNCT__ "DMPlexGetRefinementLimit" 7155 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7156 { 7157 DM_Plex *mesh = (DM_Plex*) dm->data; 7158 7159 PetscFunctionBegin; 7160 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7161 PetscValidPointer(refinementLimit, 2); 7162 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7163 *refinementLimit = mesh->refinementLimit; 7164 PetscFunctionReturn(0); 7165 } 7166 7167 #undef __FUNCT__ 7168 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7169 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7170 { 7171 PetscInt dim, cStart, coneSize, cMax; 7172 PetscErrorCode ierr; 7173 7174 PetscFunctionBegin; 7175 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7176 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7177 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7178 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7179 switch (dim) { 7180 case 2: 7181 switch (coneSize) { 7182 case 3: 7183 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7184 else *cellRefiner = 1; /* Triangular */ 7185 break; 7186 case 4: 7187 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7188 else *cellRefiner = 2; /* Quadrilateral */ 7189 break; 7190 default: 7191 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7192 } 7193 break; 7194 default: 7195 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7196 } 7197 PetscFunctionReturn(0); 7198 } 7199 7200 #undef __FUNCT__ 7201 #define __FUNCT__ "DMRefine_Plex" 7202 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7203 { 7204 PetscReal refinementLimit; 7205 PetscInt dim, cStart, cEnd; 7206 char genname[1024], *name = NULL; 7207 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7208 PetscErrorCode ierr; 7209 7210 PetscFunctionBegin; 7211 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7212 if (isUniform) { 7213 CellRefiner cellRefiner; 7214 7215 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7216 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7217 PetscFunctionReturn(0); 7218 } 7219 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7220 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7221 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7222 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7223 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7224 if (flg) name = genname; 7225 if (name) { 7226 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7227 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7228 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7229 } 7230 switch (dim) { 7231 case 2: 7232 if (!name || isTriangle) { 7233 #if defined(PETSC_HAVE_TRIANGLE) 7234 double *maxVolumes; 7235 PetscInt c; 7236 7237 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7238 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7239 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7240 #else 7241 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7242 #endif 7243 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7244 break; 7245 case 3: 7246 if (!name || isCTetgen) { 7247 #if defined(PETSC_HAVE_CTETGEN) 7248 PetscReal *maxVolumes; 7249 PetscInt c; 7250 7251 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7252 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7253 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7254 #else 7255 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7256 #endif 7257 } else if (isTetgen) { 7258 #if defined(PETSC_HAVE_TETGEN) 7259 double *maxVolumes; 7260 PetscInt c; 7261 7262 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7263 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7264 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7265 #else 7266 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7267 #endif 7268 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7269 break; 7270 default: 7271 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7272 } 7273 PetscFunctionReturn(0); 7274 } 7275 7276 #undef __FUNCT__ 7277 #define __FUNCT__ "DMPlexGetDepth" 7278 /*@ 7279 DMPlexGetDepth - get the number of strata 7280 7281 Not Collective 7282 7283 Input Parameters: 7284 . dm - The DMPlex object 7285 7286 Output Parameters: 7287 . depth - number of strata 7288 7289 Level: developer 7290 7291 Notes: 7292 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7293 7294 .keywords: mesh, points 7295 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7296 @*/ 7297 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7298 { 7299 PetscInt d; 7300 PetscErrorCode ierr; 7301 7302 PetscFunctionBegin; 7303 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7304 PetscValidPointer(depth, 2); 7305 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7306 *depth = d-1; 7307 PetscFunctionReturn(0); 7308 } 7309 7310 #undef __FUNCT__ 7311 #define __FUNCT__ "DMPlexGetDepthStratum" 7312 /*@ 7313 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7314 7315 Not Collective 7316 7317 Input Parameters: 7318 + dm - The DMPlex object 7319 - stratumValue - The requested depth 7320 7321 Output Parameters: 7322 + start - The first point at this depth 7323 - end - One beyond the last point at this depth 7324 7325 Level: developer 7326 7327 .keywords: mesh, points 7328 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7329 @*/ 7330 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7331 { 7332 DM_Plex *mesh = (DM_Plex*) dm->data; 7333 DMLabel next = mesh->labels; 7334 PetscBool flg = PETSC_FALSE; 7335 PetscInt depth; 7336 PetscErrorCode ierr; 7337 7338 PetscFunctionBegin; 7339 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7340 if (stratumValue < 0) { 7341 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7342 PetscFunctionReturn(0); 7343 } else { 7344 PetscInt pStart, pEnd; 7345 7346 if (start) *start = 0; 7347 if (end) *end = 0; 7348 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7349 if (pStart == pEnd) PetscFunctionReturn(0); 7350 } 7351 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7352 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7353 /* We should have a generic GetLabel() and a Label class */ 7354 while (next) { 7355 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7356 if (flg) break; 7357 next = next->next; 7358 } 7359 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7360 depth = stratumValue; 7361 if ((depth < 0) || (depth >= next->numStrata)) { 7362 if (start) *start = 0; 7363 if (end) *end = 0; 7364 } else { 7365 if (start) *start = next->points[next->stratumOffsets[depth]]; 7366 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7367 } 7368 PetscFunctionReturn(0); 7369 } 7370 7371 #undef __FUNCT__ 7372 #define __FUNCT__ "DMPlexGetHeightStratum" 7373 /*@ 7374 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7375 7376 Not Collective 7377 7378 Input Parameters: 7379 + dm - The DMPlex object 7380 - stratumValue - The requested height 7381 7382 Output Parameters: 7383 + start - The first point at this height 7384 - end - One beyond the last point at this height 7385 7386 Level: developer 7387 7388 .keywords: mesh, points 7389 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7390 @*/ 7391 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7392 { 7393 DM_Plex *mesh = (DM_Plex*) dm->data; 7394 DMLabel next = mesh->labels; 7395 PetscBool flg = PETSC_FALSE; 7396 PetscInt depth; 7397 PetscErrorCode ierr; 7398 7399 PetscFunctionBegin; 7400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7401 if (stratumValue < 0) { 7402 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7403 } else { 7404 PetscInt pStart, pEnd; 7405 7406 if (start) *start = 0; 7407 if (end) *end = 0; 7408 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7409 if (pStart == pEnd) PetscFunctionReturn(0); 7410 } 7411 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7412 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7413 /* We should have a generic GetLabel() and a Label class */ 7414 while (next) { 7415 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7416 if (flg) break; 7417 next = next->next; 7418 } 7419 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7420 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7421 if ((depth < 0) || (depth >= next->numStrata)) { 7422 if (start) *start = 0; 7423 if (end) *end = 0; 7424 } else { 7425 if (start) *start = next->points[next->stratumOffsets[depth]]; 7426 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7427 } 7428 PetscFunctionReturn(0); 7429 } 7430 7431 #undef __FUNCT__ 7432 #define __FUNCT__ "DMPlexCreateSectionInitial" 7433 /* Set the number of dof on each point and separate by fields */ 7434 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7435 { 7436 PetscInt *numDofTot; 7437 PetscInt pStart = 0, pEnd = 0; 7438 PetscInt p, d, f; 7439 PetscErrorCode ierr; 7440 7441 PetscFunctionBegin; 7442 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7443 for (d = 0; d <= dim; ++d) { 7444 numDofTot[d] = 0; 7445 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7446 } 7447 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7448 if (numFields > 0) { 7449 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7450 if (numComp) { 7451 for (f = 0; f < numFields; ++f) { 7452 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7453 } 7454 } 7455 } 7456 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7457 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7458 for (d = 0; d <= dim; ++d) { 7459 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7460 for (p = pStart; p < pEnd; ++p) { 7461 for (f = 0; f < numFields; ++f) { 7462 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7463 } 7464 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7465 } 7466 } 7467 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7468 PetscFunctionReturn(0); 7469 } 7470 7471 #undef __FUNCT__ 7472 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7473 /* Set the number of dof on each point and separate by fields 7474 If constDof is PETSC_DETERMINE, constrain every dof on the point 7475 */ 7476 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7477 { 7478 PetscInt numFields; 7479 PetscInt bc; 7480 PetscErrorCode ierr; 7481 7482 PetscFunctionBegin; 7483 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7484 for (bc = 0; bc < numBC; ++bc) { 7485 PetscInt field = 0; 7486 const PetscInt *idx; 7487 PetscInt n, i; 7488 7489 if (numFields) field = bcField[bc]; 7490 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7491 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7492 for (i = 0; i < n; ++i) { 7493 const PetscInt p = idx[i]; 7494 PetscInt numConst = constDof; 7495 7496 /* Constrain every dof on the point */ 7497 if (numConst < 0) { 7498 if (numFields) { 7499 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7500 } else { 7501 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7502 } 7503 } 7504 if (numFields) { 7505 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7506 } 7507 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7508 } 7509 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7510 } 7511 PetscFunctionReturn(0); 7512 } 7513 7514 #undef __FUNCT__ 7515 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7516 /* Set the constrained indices on each point and separate by fields */ 7517 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7518 { 7519 PetscInt *maxConstraints; 7520 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7521 PetscErrorCode ierr; 7522 7523 PetscFunctionBegin; 7524 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7525 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7526 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7527 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7528 for (p = pStart; p < pEnd; ++p) { 7529 PetscInt cdof; 7530 7531 if (numFields) { 7532 for (f = 0; f < numFields; ++f) { 7533 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7534 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7535 } 7536 } else { 7537 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7538 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7539 } 7540 } 7541 for (f = 0; f < numFields; ++f) { 7542 maxConstraints[numFields] += maxConstraints[f]; 7543 } 7544 if (maxConstraints[numFields]) { 7545 PetscInt *indices; 7546 7547 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7548 for (p = pStart; p < pEnd; ++p) { 7549 PetscInt cdof, d; 7550 7551 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7552 if (cdof) { 7553 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7554 if (numFields) { 7555 PetscInt numConst = 0, foff = 0; 7556 7557 for (f = 0; f < numFields; ++f) { 7558 PetscInt cfdof, fdof; 7559 7560 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7561 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7562 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7563 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7564 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7565 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7566 numConst += cfdof; 7567 foff += fdof; 7568 } 7569 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7570 } else { 7571 for (d = 0; d < cdof; ++d) indices[d] = d; 7572 } 7573 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7574 } 7575 } 7576 ierr = PetscFree(indices);CHKERRQ(ierr); 7577 } 7578 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7579 PetscFunctionReturn(0); 7580 } 7581 7582 #undef __FUNCT__ 7583 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7584 /* Set the constrained field indices on each point */ 7585 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7586 { 7587 const PetscInt *points, *indices; 7588 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7589 PetscErrorCode ierr; 7590 7591 PetscFunctionBegin; 7592 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7593 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7594 7595 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7596 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7597 if (!constraintIndices) { 7598 PetscInt *idx, i; 7599 7600 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7601 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7602 for (i = 0; i < maxDof; ++i) idx[i] = i; 7603 for (p = 0; p < numPoints; ++p) { 7604 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7605 } 7606 ierr = PetscFree(idx);CHKERRQ(ierr); 7607 } else { 7608 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7609 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7610 for (p = 0; p < numPoints; ++p) { 7611 PetscInt fcdof; 7612 7613 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7614 if (fcdof != numConstraints) SETERRQ4(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 7615 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7616 } 7617 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7618 } 7619 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7620 PetscFunctionReturn(0); 7621 } 7622 7623 #undef __FUNCT__ 7624 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7625 /* Set the constrained indices on each point and separate by fields */ 7626 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7627 { 7628 PetscInt *indices; 7629 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7630 PetscErrorCode ierr; 7631 7632 PetscFunctionBegin; 7633 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7634 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7635 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7636 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7637 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7638 for (p = pStart; p < pEnd; ++p) { 7639 PetscInt cdof, d; 7640 7641 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7642 if (cdof) { 7643 PetscInt numConst = 0, foff = 0; 7644 7645 for (f = 0; f < numFields; ++f) { 7646 const PetscInt *fcind; 7647 PetscInt fdof, fcdof; 7648 7649 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7650 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7651 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7652 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7653 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7654 foff += fdof; 7655 numConst += fcdof; 7656 } 7657 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7658 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7659 } 7660 } 7661 ierr = PetscFree(indices);CHKERRQ(ierr); 7662 PetscFunctionReturn(0); 7663 } 7664 7665 #undef __FUNCT__ 7666 #define __FUNCT__ "DMPlexCreateSection" 7667 /*@C 7668 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7669 7670 Not Collective 7671 7672 Input Parameters: 7673 + dm - The DMPlex object 7674 . dim - The spatial dimension of the problem 7675 . numFields - The number of fields in the problem 7676 . numComp - An array of size numFields that holds the number of components for each field 7677 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7678 . numBC - The number of boundary conditions 7679 . bcField - An array of size numBC giving the field number for each boundry condition 7680 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7681 7682 Output Parameter: 7683 . section - The PetscSection object 7684 7685 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 7686 nubmer of dof for field 0 on each edge. 7687 7688 Level: developer 7689 7690 .keywords: mesh, elements 7691 .seealso: DMPlexCreate(), PetscSectionCreate() 7692 @*/ 7693 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 7694 { 7695 PetscErrorCode ierr; 7696 7697 PetscFunctionBegin; 7698 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7699 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7700 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7701 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7702 { 7703 PetscBool view = PETSC_FALSE; 7704 7705 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7706 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7707 } 7708 PetscFunctionReturn(0); 7709 } 7710 7711 #undef __FUNCT__ 7712 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7713 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7714 { 7715 PetscSection section; 7716 PetscErrorCode ierr; 7717 7718 PetscFunctionBegin; 7719 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7720 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7721 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7722 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7723 PetscFunctionReturn(0); 7724 } 7725 7726 #undef __FUNCT__ 7727 #define __FUNCT__ "DMPlexGetCoordinateSection" 7728 /*@ 7729 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7730 7731 Not Collective 7732 7733 Input Parameter: 7734 . dm - The DMPlex object 7735 7736 Output Parameter: 7737 . section - The PetscSection object 7738 7739 Level: intermediate 7740 7741 .keywords: mesh, coordinates 7742 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7743 @*/ 7744 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7745 { 7746 DM cdm; 7747 PetscErrorCode ierr; 7748 7749 PetscFunctionBegin; 7750 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7751 PetscValidPointer(section, 2); 7752 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7753 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7754 PetscFunctionReturn(0); 7755 } 7756 7757 #undef __FUNCT__ 7758 #define __FUNCT__ "DMPlexSetCoordinateSection" 7759 /*@ 7760 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7761 7762 Not Collective 7763 7764 Input Parameters: 7765 + dm - The DMPlex object 7766 - section - The PetscSection object 7767 7768 Level: intermediate 7769 7770 .keywords: mesh, coordinates 7771 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7772 @*/ 7773 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7774 { 7775 DM cdm; 7776 PetscErrorCode ierr; 7777 7778 PetscFunctionBegin; 7779 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7780 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 7781 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7782 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7783 PetscFunctionReturn(0); 7784 } 7785 7786 #undef __FUNCT__ 7787 #define __FUNCT__ "DMPlexGetConeSection" 7788 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7789 { 7790 DM_Plex *mesh = (DM_Plex*) dm->data; 7791 7792 PetscFunctionBegin; 7793 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7794 if (section) *section = mesh->coneSection; 7795 PetscFunctionReturn(0); 7796 } 7797 7798 #undef __FUNCT__ 7799 #define __FUNCT__ "DMPlexGetCones" 7800 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 7801 { 7802 DM_Plex *mesh = (DM_Plex*) dm->data; 7803 7804 PetscFunctionBegin; 7805 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7806 if (cones) *cones = mesh->cones; 7807 PetscFunctionReturn(0); 7808 } 7809 7810 #undef __FUNCT__ 7811 #define __FUNCT__ "DMPlexGetConeOrientations" 7812 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 7813 { 7814 DM_Plex *mesh = (DM_Plex*) dm->data; 7815 7816 PetscFunctionBegin; 7817 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7818 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7819 PetscFunctionReturn(0); 7820 } 7821 7822 #undef __FUNCT__ 7823 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7824 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7825 { 7826 const PetscInt embedDim = 2; 7827 PetscReal x = PetscRealPart(point[0]); 7828 PetscReal y = PetscRealPart(point[1]); 7829 PetscReal v0[2], J[4], invJ[4], detJ; 7830 PetscReal xi, eta; 7831 PetscErrorCode ierr; 7832 7833 PetscFunctionBegin; 7834 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7835 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7836 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7837 7838 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 7839 else *cell = -1; 7840 PetscFunctionReturn(0); 7841 } 7842 7843 #undef __FUNCT__ 7844 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7845 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7846 { 7847 PetscSection coordSection; 7848 Vec coordsLocal; 7849 const PetscScalar *coords; 7850 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7851 PetscReal x = PetscRealPart(point[0]); 7852 PetscReal y = PetscRealPart(point[1]); 7853 PetscInt crossings = 0, f; 7854 PetscErrorCode ierr; 7855 7856 PetscFunctionBegin; 7857 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7858 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7859 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7860 for (f = 0; f < 4; ++f) { 7861 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7862 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7863 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7864 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7865 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7866 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7867 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7868 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7869 if ((cond1 || cond2) && above) ++crossings; 7870 } 7871 if (crossings % 2) *cell = c; 7872 else *cell = -1; 7873 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7874 PetscFunctionReturn(0); 7875 } 7876 7877 #undef __FUNCT__ 7878 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7879 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7880 { 7881 const PetscInt embedDim = 3; 7882 PetscReal v0[3], J[9], invJ[9], detJ; 7883 PetscReal x = PetscRealPart(point[0]); 7884 PetscReal y = PetscRealPart(point[1]); 7885 PetscReal z = PetscRealPart(point[2]); 7886 PetscReal xi, eta, zeta; 7887 PetscErrorCode ierr; 7888 7889 PetscFunctionBegin; 7890 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7891 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7892 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7893 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7894 7895 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 7896 else *cell = -1; 7897 PetscFunctionReturn(0); 7898 } 7899 7900 #undef __FUNCT__ 7901 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7902 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7903 { 7904 PetscSection coordSection; 7905 Vec coordsLocal; 7906 const PetscScalar *coords; 7907 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7908 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7909 PetscBool found = PETSC_TRUE; 7910 PetscInt f; 7911 PetscErrorCode ierr; 7912 7913 PetscFunctionBegin; 7914 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7915 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7916 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7917 for (f = 0; f < 6; ++f) { 7918 /* Check the point is under plane */ 7919 /* Get face normal */ 7920 PetscReal v_i[3]; 7921 PetscReal v_j[3]; 7922 PetscReal normal[3]; 7923 PetscReal pp[3]; 7924 PetscReal dot; 7925 7926 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 7927 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 7928 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 7929 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 7930 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 7931 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 7932 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 7933 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 7934 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 7935 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 7936 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 7937 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 7938 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7939 7940 /* Check that projected point is in face (2D location problem) */ 7941 if (dot < 0.0) { 7942 found = PETSC_FALSE; 7943 break; 7944 } 7945 } 7946 if (found) *cell = c; 7947 else *cell = -1; 7948 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7949 PetscFunctionReturn(0); 7950 } 7951 7952 #undef __FUNCT__ 7953 #define __FUNCT__ "DMLocatePoints_Plex" 7954 /* 7955 Need to implement using the guess 7956 */ 7957 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7958 { 7959 PetscInt cell = -1 /*, guess = -1*/; 7960 PetscInt bs, numPoints, p; 7961 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7962 PetscInt *cells; 7963 PetscScalar *a; 7964 PetscErrorCode ierr; 7965 7966 PetscFunctionBegin; 7967 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7968 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7969 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7970 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7971 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7972 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7973 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7974 if (bs != dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 7975 numPoints /= bs; 7976 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7977 for (p = 0; p < numPoints; ++p) { 7978 const PetscScalar *point = &a[p*bs]; 7979 7980 switch (dim) { 7981 case 2: 7982 for (c = cStart; c < cEnd; ++c) { 7983 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7984 switch (coneSize) { 7985 case 3: 7986 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7987 break; 7988 case 4: 7989 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7990 break; 7991 default: 7992 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7993 } 7994 if (cell >= 0) break; 7995 } 7996 break; 7997 case 3: 7998 for (c = cStart; c < cEnd; ++c) { 7999 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8000 switch (coneSize) { 8001 case 4: 8002 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8003 break; 8004 case 8: 8005 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8006 break; 8007 default: 8008 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8009 } 8010 if (cell >= 0) break; 8011 } 8012 break; 8013 default: 8014 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8015 } 8016 cells[p] = cell; 8017 } 8018 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8019 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8020 PetscFunctionReturn(0); 8021 } 8022 8023 /******************************** FEM Support **********************************/ 8024 8025 #undef __FUNCT__ 8026 #define __FUNCT__ "DMPlexVecGetClosure" 8027 /*@C 8028 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8029 8030 Not collective 8031 8032 Input Parameters: 8033 + dm - The DM 8034 . section - The section describing the layout in v, or NULL to use the default section 8035 . v - The local vector 8036 - point - The sieve point in the DM 8037 8038 Output Parameters: 8039 + csize - The number of values in the closure, or NULL 8040 - values - The array of values, which is a borrowed array and should not be freed 8041 8042 Level: intermediate 8043 8044 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8045 @*/ 8046 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8047 { 8048 PetscScalar *array, *vArray; 8049 PetscInt *points = NULL; 8050 PetscInt offsets[32]; 8051 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8052 PetscErrorCode ierr; 8053 8054 PetscFunctionBegin; 8055 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8056 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8057 if (!section) { 8058 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8059 } 8060 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8061 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8062 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8063 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8064 /* Compress out points not in the section */ 8065 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8066 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8067 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8068 points[q*2] = points[p]; 8069 points[q*2+1] = points[p+1]; 8070 ++q; 8071 } 8072 } 8073 numPoints = q; 8074 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8075 PetscInt dof, fdof; 8076 8077 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8078 for (f = 0; f < numFields; ++f) { 8079 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8080 offsets[f+1] += fdof; 8081 } 8082 size += dof; 8083 } 8084 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8085 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8086 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8087 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8088 for (p = 0; p < numPoints*2; p += 2) { 8089 PetscInt o = points[p+1]; 8090 PetscInt dof, off, d; 8091 PetscScalar *varr; 8092 8093 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8094 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8095 varr = &vArray[off]; 8096 if (numFields) { 8097 PetscInt fdof, foff, fcomp, f, c; 8098 8099 for (f = 0, foff = 0; f < numFields; ++f) { 8100 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8101 if (o >= 0) { 8102 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8103 array[offsets[f]] = varr[foff+d]; 8104 } 8105 } else { 8106 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8107 for (d = fdof/fcomp-1; d >= 0; --d) { 8108 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8109 array[offsets[f]] = varr[foff+d*fcomp+c]; 8110 } 8111 } 8112 } 8113 foff += fdof; 8114 } 8115 } else { 8116 if (o >= 0) { 8117 for (d = 0; d < dof; ++d, ++offsets[0]) { 8118 array[offsets[0]] = varr[d]; 8119 } 8120 } else { 8121 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8122 array[offsets[0]] = varr[d]; 8123 } 8124 } 8125 } 8126 } 8127 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8128 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8129 if (csize) *csize = size; 8130 *values = array; 8131 PetscFunctionReturn(0); 8132 } 8133 8134 #undef __FUNCT__ 8135 #define __FUNCT__ "DMPlexVecRestoreClosure" 8136 /*@C 8137 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8138 8139 Not collective 8140 8141 Input Parameters: 8142 + dm - The DM 8143 . section - The section describing the layout in v, or NULL to use the default section 8144 . v - The local vector 8145 . point - The sieve point in the DM 8146 . csize - The number of values in the closure, or NULL 8147 - values - The array of values, which is a borrowed array and should not be freed 8148 8149 Level: intermediate 8150 8151 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8152 @*/ 8153 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8154 { 8155 PetscInt size = 0; 8156 PetscErrorCode ierr; 8157 8158 PetscFunctionBegin; 8159 /* Should work without recalculating size */ 8160 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8161 PetscFunctionReturn(0); 8162 } 8163 8164 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8165 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8166 8167 #undef __FUNCT__ 8168 #define __FUNCT__ "updatePoint_private" 8169 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8170 { 8171 PetscInt cdof; /* The number of constraints on this point */ 8172 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8173 PetscScalar *a; 8174 PetscInt off, cind = 0, k; 8175 PetscErrorCode ierr; 8176 8177 PetscFunctionBegin; 8178 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8179 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8180 a = &array[off]; 8181 if (!cdof || setBC) { 8182 if (orientation >= 0) { 8183 for (k = 0; k < dof; ++k) { 8184 fuse(&a[k], values[k]); 8185 } 8186 } else { 8187 for (k = 0; k < dof; ++k) { 8188 fuse(&a[k], values[dof-k-1]); 8189 } 8190 } 8191 } else { 8192 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8193 if (orientation >= 0) { 8194 for (k = 0; k < dof; ++k) { 8195 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8196 fuse(&a[k], values[k]); 8197 } 8198 } else { 8199 for (k = 0; k < dof; ++k) { 8200 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8201 fuse(&a[k], values[dof-k-1]); 8202 } 8203 } 8204 } 8205 PetscFunctionReturn(0); 8206 } 8207 8208 #undef __FUNCT__ 8209 #define __FUNCT__ "updatePointFields_private" 8210 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8211 { 8212 PetscScalar *a; 8213 PetscInt numFields, off, foff, f; 8214 PetscErrorCode ierr; 8215 8216 PetscFunctionBegin; 8217 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8218 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8219 a = &array[off]; 8220 for (f = 0, foff = 0; f < numFields; ++f) { 8221 PetscInt fdof, fcomp, fcdof; 8222 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8223 PetscInt cind = 0, k, c; 8224 8225 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8226 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8227 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8228 if (!fcdof || setBC) { 8229 if (orientation >= 0) { 8230 for (k = 0; k < fdof; ++k) { 8231 fuse(&a[foff+k], values[foffs[f]+k]); 8232 } 8233 } else { 8234 for (k = fdof/fcomp-1; k >= 0; --k) { 8235 for (c = 0; c < fcomp; ++c) { 8236 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8237 } 8238 } 8239 } 8240 } else { 8241 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8242 if (orientation >= 0) { 8243 for (k = 0; k < fdof; ++k) { 8244 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8245 fuse(&a[foff+k], values[foffs[f]+k]); 8246 } 8247 } else { 8248 for (k = fdof/fcomp-1; k >= 0; --k) { 8249 for (c = 0; c < fcomp; ++c) { 8250 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8251 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8252 } 8253 } 8254 } 8255 } 8256 foff += fdof; 8257 foffs[f] += fdof; 8258 } 8259 PetscFunctionReturn(0); 8260 } 8261 8262 #undef __FUNCT__ 8263 #define __FUNCT__ "DMPlexVecSetClosure" 8264 /*@C 8265 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8266 8267 Not collective 8268 8269 Input Parameters: 8270 + dm - The DM 8271 . section - The section describing the layout in v, or NULL to use the default sectionw 8272 . v - The local vector 8273 . point - The sieve point in the DM 8274 . values - The array of values, which is a borrowed array and should not be freed 8275 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8276 8277 Level: intermediate 8278 8279 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8280 @*/ 8281 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8282 { 8283 PetscScalar *array; 8284 PetscInt *points = NULL; 8285 PetscInt offsets[32]; 8286 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8287 PetscErrorCode ierr; 8288 8289 PetscFunctionBegin; 8290 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8291 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8292 if (!section) { 8293 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8294 } 8295 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8296 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8297 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8298 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8299 /* Compress out points not in the section */ 8300 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8301 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8302 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8303 points[q*2] = points[p]; 8304 points[q*2+1] = points[p+1]; 8305 ++q; 8306 } 8307 } 8308 numPoints = q; 8309 for (p = 0; p < numPoints*2; p += 2) { 8310 PetscInt fdof; 8311 8312 for (f = 0; f < numFields; ++f) { 8313 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8314 offsets[f+1] += fdof; 8315 } 8316 } 8317 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8318 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8319 if (numFields) { 8320 switch (mode) { 8321 case INSERT_VALUES: 8322 for (p = 0; p < numPoints*2; p += 2) { 8323 PetscInt o = points[p+1]; 8324 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8325 } break; 8326 case INSERT_ALL_VALUES: 8327 for (p = 0; p < numPoints*2; p += 2) { 8328 PetscInt o = points[p+1]; 8329 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8330 } break; 8331 case ADD_VALUES: 8332 for (p = 0; p < numPoints*2; p += 2) { 8333 PetscInt o = points[p+1]; 8334 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8335 } break; 8336 case ADD_ALL_VALUES: 8337 for (p = 0; p < numPoints*2; p += 2) { 8338 PetscInt o = points[p+1]; 8339 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8340 } break; 8341 default: 8342 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8343 } 8344 } else { 8345 switch (mode) { 8346 case INSERT_VALUES: 8347 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8348 PetscInt o = points[p+1]; 8349 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8350 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8351 } break; 8352 case INSERT_ALL_VALUES: 8353 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8354 PetscInt o = points[p+1]; 8355 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8356 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8357 } break; 8358 case ADD_VALUES: 8359 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8360 PetscInt o = points[p+1]; 8361 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8362 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8363 } break; 8364 case ADD_ALL_VALUES: 8365 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8366 PetscInt o = points[p+1]; 8367 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8368 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8369 } break; 8370 default: 8371 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8372 } 8373 } 8374 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8375 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8376 PetscFunctionReturn(0); 8377 } 8378 8379 #undef __FUNCT__ 8380 #define __FUNCT__ "DMPlexPrintMatSetValues" 8381 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8382 { 8383 PetscMPIInt rank; 8384 PetscInt i, j; 8385 PetscErrorCode ierr; 8386 8387 PetscFunctionBegin; 8388 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8389 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8390 for (i = 0; i < numIndices; i++) { 8391 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8392 } 8393 for (i = 0; i < numIndices; i++) { 8394 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8395 for (j = 0; j < numIndices; j++) { 8396 #if defined(PETSC_USE_COMPLEX) 8397 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8398 #else 8399 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8400 #endif 8401 } 8402 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8403 } 8404 PetscFunctionReturn(0); 8405 } 8406 8407 #undef __FUNCT__ 8408 #define __FUNCT__ "indicesPoint_private" 8409 /* . off - The global offset of this point */ 8410 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8411 { 8412 PetscInt dof; /* The number of unknowns on this point */ 8413 PetscInt cdof; /* The number of constraints on this point */ 8414 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8415 PetscInt cind = 0, k; 8416 PetscErrorCode ierr; 8417 8418 PetscFunctionBegin; 8419 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8420 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8421 if (!cdof || setBC) { 8422 if (orientation >= 0) { 8423 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8424 } else { 8425 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8426 } 8427 } else { 8428 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8429 if (orientation >= 0) { 8430 for (k = 0; k < dof; ++k) { 8431 if ((cind < cdof) && (k == cdofs[cind])) { 8432 /* Insert check for returning constrained indices */ 8433 indices[*loff+k] = -(off+k+1); 8434 ++cind; 8435 } else { 8436 indices[*loff+k] = off+k-cind; 8437 } 8438 } 8439 } else { 8440 for (k = 0; k < dof; ++k) { 8441 if ((cind < cdof) && (k == cdofs[cind])) { 8442 /* Insert check for returning constrained indices */ 8443 indices[*loff+dof-k-1] = -(off+k+1); 8444 ++cind; 8445 } else { 8446 indices[*loff+dof-k-1] = off+k-cind; 8447 } 8448 } 8449 } 8450 } 8451 *loff += dof; 8452 PetscFunctionReturn(0); 8453 } 8454 8455 #undef __FUNCT__ 8456 #define __FUNCT__ "indicesPointFields_private" 8457 /* . off - The global offset of this point */ 8458 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8459 { 8460 PetscInt numFields, foff, f; 8461 PetscErrorCode ierr; 8462 8463 PetscFunctionBegin; 8464 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8465 for (f = 0, foff = 0; f < numFields; ++f) { 8466 PetscInt fdof, fcomp, cfdof; 8467 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8468 PetscInt cind = 0, k, c; 8469 8470 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8471 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8472 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8473 if (!cfdof || setBC) { 8474 if (orientation >= 0) { 8475 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8476 } else { 8477 for (k = fdof/fcomp-1; k >= 0; --k) { 8478 for (c = 0; c < fcomp; ++c) { 8479 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8480 } 8481 } 8482 } 8483 } else { 8484 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8485 if (orientation >= 0) { 8486 for (k = 0; k < fdof; ++k) { 8487 if ((cind < cfdof) && (k == fcdofs[cind])) { 8488 indices[foffs[f]+k] = -(off+foff+k+1); 8489 ++cind; 8490 } else { 8491 indices[foffs[f]+k] = off+foff+k-cind; 8492 } 8493 } 8494 } else { 8495 for (k = fdof/fcomp-1; k >= 0; --k) { 8496 for (c = 0; c < fcomp; ++c) { 8497 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8498 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8499 ++cind; 8500 } else { 8501 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8502 } 8503 } 8504 } 8505 } 8506 } 8507 foff += fdof - cfdof; 8508 foffs[f] += fdof; 8509 } 8510 PetscFunctionReturn(0); 8511 } 8512 8513 #undef __FUNCT__ 8514 #define __FUNCT__ "DMPlexMatSetClosure" 8515 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8516 { 8517 DM_Plex *mesh = (DM_Plex*) dm->data; 8518 PetscInt *points = NULL; 8519 PetscInt *indices; 8520 PetscInt offsets[32]; 8521 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8522 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8523 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8524 PetscErrorCode ierr; 8525 8526 PetscFunctionBegin; 8527 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8528 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8529 if (useDefault) { 8530 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8531 } 8532 if (useGlobalDefault) { 8533 if (useDefault) { 8534 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8535 } else { 8536 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8537 } 8538 } 8539 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8540 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8541 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8542 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8543 /* Compress out points not in the section */ 8544 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8545 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8546 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8547 points[q*2] = points[p]; 8548 points[q*2+1] = points[p+1]; 8549 ++q; 8550 } 8551 } 8552 numPoints = q; 8553 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8554 PetscInt fdof; 8555 8556 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8557 for (f = 0; f < numFields; ++f) { 8558 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8559 offsets[f+1] += fdof; 8560 } 8561 numIndices += dof; 8562 } 8563 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8564 8565 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8566 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8567 if (numFields) { 8568 for (p = 0; p < numPoints*2; p += 2) { 8569 PetscInt o = points[p+1]; 8570 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8571 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8572 } 8573 } else { 8574 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8575 PetscInt o = points[p+1]; 8576 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8577 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8578 } 8579 } 8580 if (useGlobalDefault && !useDefault) { 8581 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8582 } 8583 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8584 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8585 if (ierr) { 8586 PetscMPIInt rank; 8587 PetscErrorCode ierr2; 8588 8589 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8590 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8591 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8592 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8593 CHKERRQ(ierr); 8594 } 8595 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8596 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8597 PetscFunctionReturn(0); 8598 } 8599 8600 #undef __FUNCT__ 8601 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8602 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8603 { 8604 PetscSection coordSection; 8605 Vec coordinates; 8606 const PetscScalar *coords; 8607 const PetscInt dim = 2; 8608 PetscInt d, f; 8609 PetscErrorCode ierr; 8610 8611 PetscFunctionBegin; 8612 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8613 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8614 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8615 if (v0) { 8616 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8617 } 8618 if (J) { 8619 for (d = 0; d < dim; d++) { 8620 for (f = 0; f < dim; f++) { 8621 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8622 } 8623 } 8624 *detJ = J[0]*J[3] - J[1]*J[2]; 8625 #if 0 8626 if (detJ < 0.0) { 8627 const PetscReal xLength = mesh->periodicity[0]; 8628 8629 if (xLength != 0.0) { 8630 PetscReal v0x = coords[0*dim+0]; 8631 8632 if (v0x == 0.0) v0x = v0[0] = xLength; 8633 for (f = 0; f < dim; f++) { 8634 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8635 8636 J[0*dim+f] = 0.5*(px - v0x); 8637 } 8638 } 8639 detJ = J[0]*J[3] - J[1]*J[2]; 8640 } 8641 #endif 8642 PetscLogFlops(8.0 + 3.0); 8643 } 8644 if (invJ) { 8645 const PetscReal invDet = 1.0/(*detJ); 8646 8647 invJ[0] = invDet*J[3]; 8648 invJ[1] = -invDet*J[1]; 8649 invJ[2] = -invDet*J[2]; 8650 invJ[3] = invDet*J[0]; 8651 PetscLogFlops(5.0); 8652 } 8653 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8654 PetscFunctionReturn(0); 8655 } 8656 8657 #undef __FUNCT__ 8658 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8659 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8660 { 8661 PetscSection coordSection; 8662 Vec coordinates; 8663 const PetscScalar *coords; 8664 const PetscInt dim = 2; 8665 PetscInt d, f; 8666 PetscErrorCode ierr; 8667 8668 PetscFunctionBegin; 8669 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8670 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8671 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8672 if (v0) { 8673 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8674 } 8675 if (J) { 8676 for (d = 0; d < dim; d++) { 8677 for (f = 0; f < dim; f++) { 8678 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8679 } 8680 } 8681 *detJ = J[0]*J[3] - J[1]*J[2]; 8682 PetscLogFlops(8.0 + 3.0); 8683 } 8684 if (invJ) { 8685 const PetscReal invDet = 1.0/(*detJ); 8686 8687 invJ[0] = invDet*J[3]; 8688 invJ[1] = -invDet*J[1]; 8689 invJ[2] = -invDet*J[2]; 8690 invJ[3] = invDet*J[0]; 8691 PetscLogFlops(5.0); 8692 } 8693 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8694 PetscFunctionReturn(0); 8695 } 8696 8697 #undef __FUNCT__ 8698 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8699 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8700 { 8701 PetscSection coordSection; 8702 Vec coordinates; 8703 const PetscScalar *coords; 8704 const PetscInt dim = 3; 8705 PetscInt d, f; 8706 PetscErrorCode ierr; 8707 8708 PetscFunctionBegin; 8709 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8710 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8711 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8712 if (v0) { 8713 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8714 } 8715 if (J) { 8716 for (d = 0; d < dim; d++) { 8717 for (f = 0; f < dim; f++) { 8718 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8719 } 8720 } 8721 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8722 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8723 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8724 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8725 PetscLogFlops(18.0 + 12.0); 8726 } 8727 if (invJ) { 8728 const PetscReal invDet = 1.0/(*detJ); 8729 8730 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8731 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8732 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8733 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8734 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8735 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8736 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8737 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8738 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8739 PetscLogFlops(37.0); 8740 } 8741 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8742 PetscFunctionReturn(0); 8743 } 8744 8745 #undef __FUNCT__ 8746 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8747 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8748 { 8749 PetscSection coordSection; 8750 Vec coordinates; 8751 const PetscScalar *coords; 8752 const PetscInt dim = 3; 8753 PetscInt d; 8754 PetscErrorCode ierr; 8755 8756 PetscFunctionBegin; 8757 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8758 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8759 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8760 if (v0) { 8761 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8762 } 8763 if (J) { 8764 for (d = 0; d < dim; d++) { 8765 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8766 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8767 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8768 } 8769 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8770 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8771 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8772 PetscLogFlops(18.0 + 12.0); 8773 } 8774 if (invJ) { 8775 const PetscReal invDet = -1.0/(*detJ); 8776 8777 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8778 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8779 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8780 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8781 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8782 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8783 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8784 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8785 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8786 PetscLogFlops(37.0); 8787 } 8788 *detJ *= 8.0; 8789 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8790 PetscFunctionReturn(0); 8791 } 8792 8793 #undef __FUNCT__ 8794 #define __FUNCT__ "DMPlexComputeCellGeometry" 8795 /*@C 8796 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8797 8798 Collective on DM 8799 8800 Input Arguments: 8801 + dm - the DM 8802 - cell - the cell 8803 8804 Output Arguments: 8805 + v0 - the translation part of this affine transform 8806 . J - the Jacobian of the transform to the reference element 8807 . invJ - the inverse of the Jacobian 8808 - detJ - the Jacobian determinant 8809 8810 Level: advanced 8811 8812 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8813 @*/ 8814 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8815 { 8816 PetscInt dim, coneSize; 8817 PetscErrorCode ierr; 8818 8819 PetscFunctionBegin; 8820 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8821 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8822 switch (dim) { 8823 case 2: 8824 switch (coneSize) { 8825 case 3: 8826 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8827 break; 8828 case 4: 8829 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8830 break; 8831 default: 8832 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8833 } 8834 break; 8835 case 3: 8836 switch (coneSize) { 8837 case 4: 8838 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8839 break; 8840 case 8: 8841 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8842 break; 8843 default: 8844 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8845 } 8846 break; 8847 default: 8848 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8849 } 8850 PetscFunctionReturn(0); 8851 } 8852 8853 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8854 { 8855 switch (i) { 8856 case 0: 8857 switch (j) { 8858 case 0: return 0; 8859 case 1: 8860 switch (k) { 8861 case 0: return 0; 8862 case 1: return 0; 8863 case 2: return 1; 8864 } 8865 case 2: 8866 switch (k) { 8867 case 0: return 0; 8868 case 1: return -1; 8869 case 2: return 0; 8870 } 8871 } 8872 case 1: 8873 switch (j) { 8874 case 0: 8875 switch (k) { 8876 case 0: return 0; 8877 case 1: return 0; 8878 case 2: return -1; 8879 } 8880 case 1: return 0; 8881 case 2: 8882 switch (k) { 8883 case 0: return 1; 8884 case 1: return 0; 8885 case 2: return 0; 8886 } 8887 } 8888 case 2: 8889 switch (j) { 8890 case 0: 8891 switch (k) { 8892 case 0: return 0; 8893 case 1: return 1; 8894 case 2: return 0; 8895 } 8896 case 1: 8897 switch (k) { 8898 case 0: return -1; 8899 case 1: return 0; 8900 case 2: return 0; 8901 } 8902 case 2: return 0; 8903 } 8904 } 8905 return 0; 8906 } 8907 8908 #undef __FUNCT__ 8909 #define __FUNCT__ "DMPlexCreateRigidBody" 8910 /*@C 8911 DMPlexCreateRigidBody - create rigid body modes from coordinates 8912 8913 Collective on DM 8914 8915 Input Arguments: 8916 + dm - the DM 8917 . section - the local section associated with the rigid field, or NULL for the default section 8918 - globalSection - the global section associated with the rigid field, or NULL for the default section 8919 8920 Output Argument: 8921 . sp - the null space 8922 8923 Note: This is necessary to take account of Dirichlet conditions on the displacements 8924 8925 Level: advanced 8926 8927 .seealso: MatNullSpaceCreate() 8928 @*/ 8929 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8930 { 8931 MPI_Comm comm; 8932 Vec coordinates, localMode, mode[6]; 8933 PetscSection coordSection; 8934 PetscScalar *coords; 8935 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8936 PetscErrorCode ierr; 8937 8938 PetscFunctionBegin; 8939 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 8940 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8941 if (dim == 1) { 8942 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 8943 PetscFunctionReturn(0); 8944 } 8945 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8946 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8947 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8948 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8949 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8950 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8951 m = (dim*(dim+1))/2; 8952 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8953 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8954 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8955 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8956 /* Assume P1 */ 8957 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8958 for (d = 0; d < dim; ++d) { 8959 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8960 8961 values[d] = 1.0; 8962 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8963 for (v = vStart; v < vEnd; ++v) { 8964 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8965 } 8966 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8967 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8968 } 8969 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8970 for (d = dim; d < dim*(dim+1)/2; ++d) { 8971 PetscInt i, j, k = dim > 2 ? d - dim : d; 8972 8973 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8974 for (v = vStart; v < vEnd; ++v) { 8975 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8976 PetscInt off; 8977 8978 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8979 for (i = 0; i < dim; ++i) { 8980 for (j = 0; j < dim; ++j) { 8981 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8982 } 8983 } 8984 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8985 } 8986 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8987 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8988 } 8989 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8990 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8991 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 8992 /* Orthonormalize system */ 8993 for (i = dim; i < m; ++i) { 8994 PetscScalar dots[6]; 8995 8996 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8997 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8998 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8999 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 9000 } 9001 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9002 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9003 PetscFunctionReturn(0); 9004 } 9005 9006 #undef __FUNCT__ 9007 #define __FUNCT__ "DMPlexGetHybridBounds" 9008 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9009 { 9010 DM_Plex *mesh = (DM_Plex*) dm->data; 9011 PetscInt dim; 9012 PetscErrorCode ierr; 9013 9014 PetscFunctionBegin; 9015 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9016 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9017 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9018 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9019 if (eMax) *eMax = mesh->hybridPointMax[1]; 9020 if (vMax) *vMax = mesh->hybridPointMax[0]; 9021 PetscFunctionReturn(0); 9022 } 9023 9024 #undef __FUNCT__ 9025 #define __FUNCT__ "DMPlexSetHybridBounds" 9026 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9027 { 9028 DM_Plex *mesh = (DM_Plex*) dm->data; 9029 PetscInt dim; 9030 PetscErrorCode ierr; 9031 9032 PetscFunctionBegin; 9033 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9034 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9035 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9036 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9037 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9038 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9039 PetscFunctionReturn(0); 9040 } 9041 9042 #undef __FUNCT__ 9043 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9044 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9045 { 9046 DM_Plex *mesh = (DM_Plex*) dm->data; 9047 9048 PetscFunctionBegin; 9049 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9050 PetscValidPointer(cellHeight, 2); 9051 *cellHeight = mesh->vtkCellHeight; 9052 PetscFunctionReturn(0); 9053 } 9054 9055 #undef __FUNCT__ 9056 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9057 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9058 { 9059 DM_Plex *mesh = (DM_Plex*) dm->data; 9060 9061 PetscFunctionBegin; 9062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9063 mesh->vtkCellHeight = cellHeight; 9064 PetscFunctionReturn(0); 9065 } 9066 9067 #undef __FUNCT__ 9068 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9069 /* We can easily have a form that takes an IS instead */ 9070 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9071 { 9072 PetscSection section, globalSection; 9073 PetscInt *numbers, p; 9074 PetscErrorCode ierr; 9075 9076 PetscFunctionBegin; 9077 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 9078 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9079 for (p = pStart; p < pEnd; ++p) { 9080 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9081 } 9082 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9083 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9084 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9085 for (p = pStart; p < pEnd; ++p) { 9086 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9087 } 9088 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9089 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9090 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9091 PetscFunctionReturn(0); 9092 } 9093 9094 #undef __FUNCT__ 9095 #define __FUNCT__ "DMPlexGetCellNumbering" 9096 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9097 { 9098 DM_Plex *mesh = (DM_Plex*) dm->data; 9099 PetscInt cellHeight, cStart, cEnd, cMax; 9100 PetscErrorCode ierr; 9101 9102 PetscFunctionBegin; 9103 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9104 if (!mesh->globalCellNumbers) { 9105 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9106 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9107 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 9108 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9109 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9110 } 9111 *globalCellNumbers = mesh->globalCellNumbers; 9112 PetscFunctionReturn(0); 9113 } 9114 9115 #undef __FUNCT__ 9116 #define __FUNCT__ "DMPlexGetVertexNumbering" 9117 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9118 { 9119 DM_Plex *mesh = (DM_Plex*) dm->data; 9120 PetscInt vStart, vEnd, vMax; 9121 PetscErrorCode ierr; 9122 9123 PetscFunctionBegin; 9124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9125 if (!mesh->globalVertexNumbers) { 9126 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9127 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9128 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9129 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9130 } 9131 *globalVertexNumbers = mesh->globalVertexNumbers; 9132 PetscFunctionReturn(0); 9133 } 9134 9135 #undef __FUNCT__ 9136 #define __FUNCT__ "DMPlexGetScale" 9137 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9138 { 9139 DM_Plex *mesh = (DM_Plex*) dm->data; 9140 9141 PetscFunctionBegin; 9142 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9143 PetscValidPointer(scale, 3); 9144 *scale = mesh->scale[unit]; 9145 PetscFunctionReturn(0); 9146 } 9147 9148 #undef __FUNCT__ 9149 #define __FUNCT__ "DMPlexSetScale" 9150 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9151 { 9152 DM_Plex *mesh = (DM_Plex*) dm->data; 9153 9154 PetscFunctionBegin; 9155 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9156 mesh->scale[unit] = scale; 9157 PetscFunctionReturn(0); 9158 } 9159 9160 9161 /******************************************************************************* 9162 This should be in a separate Discretization object, but I am not sure how to lay 9163 it out yet, so I am stuffing things here while I experiment. 9164 *******************************************************************************/ 9165 #undef __FUNCT__ 9166 #define __FUNCT__ "DMPlexSetFEMIntegration" 9167 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9168 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9169 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9170 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9171 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9172 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9173 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9174 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9175 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9176 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9177 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9178 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9179 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9180 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9181 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9182 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9183 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9184 { 9185 DM_Plex *mesh = (DM_Plex*) dm->data; 9186 9187 PetscFunctionBegin; 9188 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9189 mesh->integrateResidualFEM = integrateResidualFEM; 9190 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9191 mesh->integrateJacobianFEM = integrateJacobianFEM; 9192 PetscFunctionReturn(0); 9193 } 9194 9195 #undef __FUNCT__ 9196 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9197 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9198 { 9199 Vec coordinates; 9200 PetscSection section, cSection; 9201 PetscInt dim, vStart, vEnd, v, c, d; 9202 PetscScalar *values, *cArray; 9203 PetscReal *coords; 9204 PetscErrorCode ierr; 9205 9206 PetscFunctionBegin; 9207 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9208 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9209 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9210 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9211 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9212 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9213 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9214 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9215 for (v = vStart; v < vEnd; ++v) { 9216 PetscInt dof, off; 9217 9218 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9219 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9220 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9221 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9222 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9223 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9224 } 9225 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9226 /* Temporary, must be replaced by a projection on the finite element basis */ 9227 { 9228 PetscInt eStart = 0, eEnd = 0, e, depth; 9229 9230 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9231 --depth; 9232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9233 for (e = eStart; e < eEnd; ++e) { 9234 const PetscInt *cone = NULL; 9235 PetscInt coneSize, d; 9236 PetscScalar *coordsA, *coordsB; 9237 9238 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9240 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9241 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9242 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9243 for (d = 0; d < dim; ++d) { 9244 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9245 } 9246 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9247 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9248 } 9249 } 9250 9251 ierr = PetscFree(coords);CHKERRQ(ierr); 9252 ierr = PetscFree(values);CHKERRQ(ierr); 9253 #if 0 9254 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9255 PetscReal detJ; 9256 9257 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9258 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9259 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9260 9261 for (PetscInt c = cStart; c < cEnd; ++c) { 9262 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9263 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9264 const int oSize = pV.getSize(); 9265 int v = 0; 9266 9267 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9268 for (PetscInt cl = 0; cl < oSize; ++cl) { 9269 const PetscInt fDim; 9270 9271 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9272 if (pointDim) { 9273 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9274 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9275 } 9276 } 9277 } 9278 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9279 pV.clear(); 9280 } 9281 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9282 ierr = PetscFree(values);CHKERRQ(ierr); 9283 #endif 9284 PetscFunctionReturn(0); 9285 } 9286 9287 #undef __FUNCT__ 9288 #define __FUNCT__ "DMPlexProjectFunction" 9289 /*@C 9290 DMPlexProjectFunction - This projects the given function into the function space provided. 9291 9292 Input Parameters: 9293 + dm - The DM 9294 . numComp - The number of components (functions) 9295 . funcs - The coordinate functions to evaluate 9296 - mode - The insertion mode for values 9297 9298 Output Parameter: 9299 . X - vector 9300 9301 Level: developer 9302 9303 Note: 9304 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9305 We will eventually fix it. 9306 9307 ,seealso: DMPlexComputeL2Diff() 9308 */ 9309 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9310 { 9311 Vec localX; 9312 PetscErrorCode ierr; 9313 9314 PetscFunctionBegin; 9315 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9316 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9317 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9318 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9319 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9320 PetscFunctionReturn(0); 9321 } 9322 9323 #undef __FUNCT__ 9324 #define __FUNCT__ "DMPlexComputeL2Diff" 9325 /*@C 9326 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9327 9328 Input Parameters: 9329 + dm - The DM 9330 . quad - The PetscQuadrature object for each field 9331 . funcs - The functions to evaluate for each field component 9332 - X - The coefficient vector u_h 9333 9334 Output Parameter: 9335 . diff - The diff ||u - u_h||_2 9336 9337 Level: developer 9338 9339 .seealso: DMPlexProjectFunction() 9340 */ 9341 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9342 { 9343 const PetscInt debug = 0; 9344 PetscSection section; 9345 Vec localX; 9346 PetscReal *coords, *v0, *J, *invJ, detJ; 9347 PetscReal localDiff = 0.0; 9348 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9349 PetscErrorCode ierr; 9350 9351 PetscFunctionBegin; 9352 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9353 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9354 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9355 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9356 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9357 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9358 for (field = 0; field < numFields; ++field) { 9359 numComponents += quad[field].numComponents; 9360 } 9361 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9362 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9363 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9364 for (c = cStart; c < cEnd; ++c) { 9365 const PetscScalar *x; 9366 PetscReal elemDiff = 0.0; 9367 9368 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9369 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9370 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9371 9372 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9373 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9374 const PetscReal *quadPoints = quad[field].quadPoints; 9375 const PetscReal *quadWeights = quad[field].quadWeights; 9376 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9377 const PetscInt numBasisComps = quad[field].numComponents; 9378 const PetscReal *basis = quad[field].basis; 9379 PetscInt q, d, e, fc, f; 9380 9381 if (debug) { 9382 char title[1024]; 9383 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9384 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9385 } 9386 for (q = 0; q < numQuadPoints; ++q) { 9387 for (d = 0; d < dim; d++) { 9388 coords[d] = v0[d]; 9389 for (e = 0; e < dim; e++) { 9390 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9391 } 9392 } 9393 for (fc = 0; fc < numBasisComps; ++fc) { 9394 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9395 PetscReal interpolant = 0.0; 9396 for (f = 0; f < numBasisFuncs; ++f) { 9397 const PetscInt fidx = f*numBasisComps+fc; 9398 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9399 } 9400 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9401 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9402 } 9403 } 9404 comp += numBasisComps; 9405 fieldOffset += numBasisFuncs*numBasisComps; 9406 } 9407 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9408 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9409 localDiff += elemDiff; 9410 } 9411 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9412 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9413 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9414 *diff = PetscSqrtReal(*diff); 9415 PetscFunctionReturn(0); 9416 } 9417 9418 #undef __FUNCT__ 9419 #define __FUNCT__ "DMPlexComputeResidualFEM" 9420 /*@ 9421 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9422 9423 Input Parameters: 9424 + dm - The mesh 9425 . X - Local input vector 9426 - user - The user context 9427 9428 Output Parameter: 9429 . F - Local output vector 9430 9431 Note: 9432 The second member of the user context must be an FEMContext. 9433 9434 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9435 like a GPU, or vectorize on a multicore machine. 9436 9437 .seealso: DMPlexComputeJacobianActionFEM() 9438 */ 9439 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9440 { 9441 DM_Plex *mesh = (DM_Plex*) dm->data; 9442 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9443 PetscQuadrature *quad = fem->quad; 9444 PetscSection section; 9445 PetscReal *v0, *J, *invJ, *detJ; 9446 PetscScalar *elemVec, *u; 9447 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9448 PetscInt cellDof = 0, numComponents = 0; 9449 PetscErrorCode ierr; 9450 9451 PetscFunctionBegin; 9452 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9453 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9454 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9455 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9456 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9457 numCells = cEnd - cStart; 9458 for (field = 0; field < numFields; ++field) { 9459 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9460 numComponents += quad[field].numComponents; 9461 } 9462 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9463 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9464 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); 9465 for (c = cStart; c < cEnd; ++c) { 9466 const PetscScalar *x; 9467 PetscInt i; 9468 9469 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9470 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9471 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9472 9473 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9474 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9475 } 9476 for (field = 0; field < numFields; ++field) { 9477 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9478 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9479 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9480 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9481 /* Conforming batches */ 9482 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9483 PetscInt numBlocks = 1; 9484 PetscInt batchSize = numBlocks * blockSize; 9485 PetscInt numBatches = numBatchesTmp; 9486 PetscInt numChunks = numCells / (numBatches*batchSize); 9487 /* Remainder */ 9488 PetscInt numRemainder = numCells % (numBatches * batchSize); 9489 PetscInt offset = numCells - numRemainder; 9490 9491 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9492 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9493 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9494 } 9495 for (c = cStart; c < cEnd; ++c) { 9496 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9497 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9498 } 9499 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9500 if (mesh->printFEM) { 9501 PetscMPIInt rank, numProcs; 9502 PetscInt p; 9503 9504 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9505 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9506 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9507 for (p = 0; p < numProcs; ++p) { 9508 if (p == rank) { 9509 Vec f; 9510 9511 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9512 ierr = VecCopy(F, f);CHKERRQ(ierr); 9513 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9514 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9515 ierr = VecDestroy(&f);CHKERRQ(ierr); 9516 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9517 } 9518 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9519 } 9520 } 9521 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9522 PetscFunctionReturn(0); 9523 } 9524 9525 #undef __FUNCT__ 9526 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9527 /*@C 9528 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9529 9530 Input Parameters: 9531 + dm - The mesh 9532 . J - The Jacobian shell matrix 9533 . X - Local input vector 9534 - user - The user context 9535 9536 Output Parameter: 9537 . F - Local output vector 9538 9539 Note: 9540 The second member of the user context must be an FEMContext. 9541 9542 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9543 like a GPU, or vectorize on a multicore machine. 9544 9545 .seealso: DMPlexComputeResidualFEM() 9546 */ 9547 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9548 { 9549 DM_Plex *mesh = (DM_Plex*) dm->data; 9550 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9551 PetscQuadrature *quad = fem->quad; 9552 PetscSection section; 9553 JacActionCtx *jctx; 9554 PetscReal *v0, *J, *invJ, *detJ; 9555 PetscScalar *elemVec, *u, *a; 9556 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9557 PetscInt cellDof = 0; 9558 PetscErrorCode ierr; 9559 9560 PetscFunctionBegin; 9561 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9562 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9563 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9564 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9565 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9566 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9567 numCells = cEnd - cStart; 9568 for (field = 0; field < numFields; ++field) { 9569 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9570 } 9571 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9572 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); 9573 for (c = cStart; c < cEnd; ++c) { 9574 const PetscScalar *x; 9575 PetscInt i; 9576 9577 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9578 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9579 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9580 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9581 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9582 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9583 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9584 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9585 } 9586 for (field = 0; field < numFields; ++field) { 9587 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9588 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9589 /* Conforming batches */ 9590 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9591 PetscInt numBlocks = 1; 9592 PetscInt batchSize = numBlocks * blockSize; 9593 PetscInt numBatches = numBatchesTmp; 9594 PetscInt numChunks = numCells / (numBatches*batchSize); 9595 /* Remainder */ 9596 PetscInt numRemainder = numCells % (numBatches * batchSize); 9597 PetscInt offset = numCells - numRemainder; 9598 9599 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); 9600 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], 9601 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9602 } 9603 for (c = cStart; c < cEnd; ++c) { 9604 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9605 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9606 } 9607 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9608 if (mesh->printFEM) { 9609 PetscMPIInt rank, numProcs; 9610 PetscInt p; 9611 9612 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9613 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9614 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9615 for (p = 0; p < numProcs; ++p) { 9616 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9617 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9618 } 9619 } 9620 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9621 PetscFunctionReturn(0); 9622 } 9623 9624 #undef __FUNCT__ 9625 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9626 /*@ 9627 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9628 9629 Input Parameters: 9630 + dm - The mesh 9631 . X - Local input vector 9632 - user - The user context 9633 9634 Output Parameter: 9635 . Jac - Jacobian matrix 9636 9637 Note: 9638 The second member of the user context must be an FEMContext. 9639 9640 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9641 like a GPU, or vectorize on a multicore machine. 9642 9643 .seealso: FormFunctionLocal() 9644 */ 9645 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9646 { 9647 DM_Plex *mesh = (DM_Plex*) dm->data; 9648 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9649 PetscQuadrature *quad = fem->quad; 9650 PetscSection section; 9651 PetscReal *v0, *J, *invJ, *detJ; 9652 PetscScalar *elemMat, *u; 9653 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9654 PetscInt cellDof = 0, numComponents = 0; 9655 PetscBool isShell; 9656 PetscErrorCode ierr; 9657 9658 PetscFunctionBegin; 9659 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9660 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9661 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9662 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9663 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9664 numCells = cEnd - cStart; 9665 for (field = 0; field < numFields; ++field) { 9666 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9667 numComponents += quad[field].numComponents; 9668 } 9669 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9670 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9671 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); 9672 for (c = cStart; c < cEnd; ++c) { 9673 const PetscScalar *x; 9674 PetscInt i; 9675 9676 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9677 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9678 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9679 9680 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9681 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9682 } 9683 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9684 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9685 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9686 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9687 PetscInt fieldJ; 9688 9689 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9690 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9691 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9692 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9693 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9694 /* Conforming batches */ 9695 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9696 PetscInt numBlocks = 1; 9697 PetscInt batchSize = numBlocks * blockSize; 9698 PetscInt numBatches = numBatchesTmp; 9699 PetscInt numChunks = numCells / (numBatches*batchSize); 9700 /* Remainder */ 9701 PetscInt numRemainder = numCells % (numBatches * batchSize); 9702 PetscInt offset = numCells - numRemainder; 9703 9704 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9705 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9706 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9707 } 9708 } 9709 for (c = cStart; c < cEnd; ++c) { 9710 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9711 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9712 } 9713 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9714 9715 /* Assemble matrix, using the 2-step process: 9716 MatAssemblyBegin(), MatAssemblyEnd(). */ 9717 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9718 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9719 9720 if (mesh->printFEM) { 9721 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9722 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9723 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9724 } 9725 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9726 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9727 if (isShell) { 9728 JacActionCtx *jctx; 9729 9730 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9731 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9732 } 9733 *str = SAME_NONZERO_PATTERN; 9734 PetscFunctionReturn(0); 9735 } 9736 9737 9738 #undef __FUNCT__ 9739 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9740 /*@C 9741 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9742 the local section and an SF describing the section point overlap. 9743 9744 Input Parameters: 9745 + s - The PetscSection for the local field layout 9746 . sf - The SF describing parallel layout of the section points 9747 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9748 . label - The label specifying the points 9749 - labelValue - The label stratum specifying the points 9750 9751 Output Parameter: 9752 . gsection - The PetscSection for the global field layout 9753 9754 Note: This gives negative sizes and offsets to points not owned by this process 9755 9756 Level: developer 9757 9758 .seealso: PetscSectionCreate() 9759 @*/ 9760 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9761 { 9762 PetscInt *neg; 9763 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9764 PetscErrorCode ierr; 9765 9766 PetscFunctionBegin; 9767 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9768 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9769 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9770 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9771 /* Mark ghost points with negative dof */ 9772 for (p = pStart; p < pEnd; ++p) { 9773 PetscInt value; 9774 9775 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9776 if (value != labelValue) continue; 9777 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9778 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9779 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9780 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9781 neg[p-pStart] = -(dof+1); 9782 } 9783 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9784 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 9785 if (nroots >= 0) { 9786 if (nroots > pEnd - pStart) { 9787 PetscInt *tmpDof; 9788 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9789 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9790 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9791 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9792 for (p = pStart; p < pEnd; ++p) { 9793 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 9794 } 9795 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9796 } else { 9797 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9798 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9799 } 9800 } 9801 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9802 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9803 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9804 9805 (*gsection)->atlasOff[p] = off; 9806 9807 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9808 } 9809 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9810 globalOff -= off; 9811 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9812 (*gsection)->atlasOff[p] += globalOff; 9813 9814 neg[p] = -((*gsection)->atlasOff[p]+1); 9815 } 9816 /* Put in negative offsets for ghost points */ 9817 if (nroots >= 0) { 9818 if (nroots > pEnd - pStart) { 9819 PetscInt *tmpOff; 9820 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9821 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9822 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9823 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9824 for (p = pStart; p < pEnd; ++p) { 9825 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 9826 } 9827 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9828 } else { 9829 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9830 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9831 } 9832 } 9833 ierr = PetscFree(neg);CHKERRQ(ierr); 9834 PetscFunctionReturn(0); 9835 } 9836