1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/vecimpl.h> 4 #include <petsc-private/isimpl.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 8 9 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "VecView_Plex_Local" 14 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 15 { 16 DM dm; 17 PetscBool isvtk; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 22 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 23 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 24 if (isvtk) { 25 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 26 PetscSection section; 27 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 28 29 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 30 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 33 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 34 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 35 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 36 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 37 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 38 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 39 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 40 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 41 } else if (cdof && vdof) { 42 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 43 } else if (cdof) { 44 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 45 * vector or just happens to have the same number of dofs as the dimension. */ 46 if (cdof == dim) { 47 ft = PETSC_VTK_CELL_VECTOR_FIELD; 48 } else { 49 ft = PETSC_VTK_CELL_FIELD; 50 } 51 } else if (vdof) { 52 if (vdof == dim) { 53 ft = PETSC_VTK_POINT_VECTOR_FIELD; 54 } else { 55 ft = PETSC_VTK_POINT_FIELD; 56 } 57 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 58 59 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 61 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 62 } else { 63 PetscBool isseq; 64 65 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 66 if (isseq) { 67 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 68 } else { 69 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "VecView_Plex" 77 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 78 { 79 DM dm; 80 PetscBool isvtk; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 85 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 86 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 87 if (isvtk) { 88 Vec locv; 89 const char *name; 90 91 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 92 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 93 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 96 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 97 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 98 } else { 99 PetscBool isseq; 100 101 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 102 if (isseq) { 103 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 104 } else { 105 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexView_Ascii" 113 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 114 { 115 DM_Plex *mesh = (DM_Plex*) dm->data; 116 DM cdm; 117 DMLabel markers; 118 PetscSection coordSection; 119 Vec coordinates; 120 PetscViewerFormat format; 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 125 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 126 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 127 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 128 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 129 const char *name; 130 PetscInt maxConeSize, maxSupportSize; 131 PetscInt pStart, pEnd, p; 132 PetscMPIInt rank, size; 133 134 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 135 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 136 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 137 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 138 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 143 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 144 for (p = pStart; p < pEnd; ++p) { 145 PetscInt dof, off, s; 146 147 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 148 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 149 for (s = off; s < off+dof; ++s) { 150 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 151 } 152 } 153 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 154 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 155 for (p = pStart; p < pEnd; ++p) { 156 PetscInt dof, off, c; 157 158 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 159 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 160 for (c = off; c < off+dof; ++c) { 161 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 162 } 163 } 164 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 165 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 166 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 167 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 168 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for (c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 284 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 285 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 286 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 287 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 288 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 289 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 290 if (depth == 1) { 291 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 292 pEnd = pEnd - pStart; 293 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 294 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 295 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 296 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 297 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 298 pEnd = pEnd - pStart; 299 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 300 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 301 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 302 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 303 } else { 304 for (d = 0; d <= dim; d++) { 305 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 306 pEnd = pEnd - pStart; 307 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 308 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 309 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 310 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 311 } 312 } 313 ierr = PetscFree(sizes);CHKERRQ(ierr); 314 } 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "DMView_Plex" 320 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 321 { 322 PetscBool iascii, isbinary; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 327 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 330 if (iascii) { 331 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 332 #if 0 333 } else if (isbinary) { 334 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 335 #endif 336 } 337 PetscFunctionReturn(0); 338 } 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "DMDestroy_Plex" 342 PetscErrorCode DMDestroy_Plex(DM dm) 343 { 344 DM_Plex *mesh = (DM_Plex*) dm->data; 345 DMLabel next = mesh->labels; 346 PetscErrorCode ierr; 347 348 PetscFunctionBegin; 349 if (--mesh->refct > 0) PetscFunctionReturn(0); 350 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 353 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 355 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 356 while (next) { 357 DMLabel tmp = next->next; 358 359 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 360 next = tmp; 361 } 362 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 364 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 365 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 366 ierr = PetscFree(mesh);CHKERRQ(ierr); 367 PetscFunctionReturn(0); 368 } 369 370 #undef __FUNCT__ 371 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 372 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 373 { 374 const PetscInt *support = NULL; 375 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 376 PetscErrorCode ierr; 377 378 PetscFunctionBegin; 379 if (useClosure) { 380 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 381 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 382 for (s = 0; s < supportSize; ++s) { 383 const PetscInt *cone = NULL; 384 PetscInt coneSize, c, q; 385 386 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 387 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 388 for (c = 0; c < coneSize; ++c) { 389 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 390 if (cone[c] == adj[q]) break; 391 } 392 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 393 } 394 } 395 } else { 396 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 397 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 398 for (s = 0; s < supportSize; ++s) { 399 const PetscInt *cone = NULL; 400 PetscInt coneSize, c, q; 401 402 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 403 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 404 for (c = 0; c < coneSize; ++c) { 405 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 406 if (cone[c] == adj[q]) break; 407 } 408 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 409 } 410 } 411 } 412 *adjSize = numAdj; 413 PetscFunctionReturn(0); 414 } 415 416 #undef __FUNCT__ 417 #define __FUNCT__ "DMPlexGetAdjacency_Private" 418 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 419 { 420 const PetscInt *star = tmpClosure; 421 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 422 PetscErrorCode ierr; 423 424 PetscFunctionBegin; 425 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 426 for (s = 2; s < starSize*2; s += 2) { 427 const PetscInt *closure = NULL; 428 PetscInt closureSize, c, q; 429 430 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 431 for (c = 0; c < closureSize*2; c += 2) { 432 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 433 if (closure[c] == adj[q]) break; 434 } 435 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 436 } 437 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 438 } 439 *adjSize = numAdj; 440 PetscFunctionReturn(0); 441 } 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 445 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 446 { 447 DM_Plex *mesh = (DM_Plex*) dm->data; 448 449 PetscFunctionBegin; 450 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 451 mesh->preallocCenterDim = preallocCenterDim; 452 PetscFunctionReturn(0); 453 } 454 455 #undef __FUNCT__ 456 #define __FUNCT__ "DMPlexPreallocateOperator" 457 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 458 { 459 DM_Plex *mesh = (DM_Plex*) dm->data; 460 MPI_Comm comm; 461 PetscSF sf, sfDof, sfAdj; 462 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 463 PetscInt nleaves, l, p; 464 const PetscInt *leaves; 465 const PetscSFNode *remotes; 466 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 467 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 468 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 469 PetscLayout rLayout; 470 PetscInt locRows, rStart, rEnd, r; 471 PetscMPIInt size; 472 PetscBool useClosure, debug = PETSC_FALSE; 473 PetscErrorCode ierr; 474 475 PetscFunctionBegin; 476 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 477 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 478 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 479 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 480 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 481 /* Create dof SF based on point SF */ 482 if (debug) { 483 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 487 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 488 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 489 } 490 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 491 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 492 if (debug) { 493 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 494 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 495 } 496 /* Create section for dof adjacency (dof ==> # adj dof) */ 497 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 498 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 499 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 500 if (mesh->preallocCenterDim == dim) { 501 useClosure = PETSC_FALSE; 502 } else if (mesh->preallocCenterDim == 0) { 503 useClosure = PETSC_TRUE; 504 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 505 506 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 507 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 510 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 511 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 512 /* Fill in the ghost dofs on the interface */ 513 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 514 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 515 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 516 517 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 518 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 519 520 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 521 522 /* 523 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 524 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 525 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 526 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 527 Create sfAdj connecting rootSectionAdj and leafSectionAdj 528 3. Visit unowned points on interface, write adjacencies to adj 529 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 530 4. Visit owned points on interface, write adjacencies to rootAdj 531 Remove redundancy in rootAdj 532 ** The last two traversals use transitive closure 533 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 534 Allocate memory addressed by sectionAdj (cols) 535 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 536 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 537 */ 538 539 for (l = 0; l < nleaves; ++l) { 540 PetscInt dof, off, d, q; 541 PetscInt p = leaves[l], numAdj = maxAdjSize; 542 543 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 544 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 545 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 546 for (q = 0; q < numAdj; ++q) { 547 PetscInt ndof, ncdof; 548 549 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 550 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 551 for (d = off; d < off+dof; ++d) { 552 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 553 } 554 } 555 } 556 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 557 if (debug) { 558 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 559 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 560 } 561 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 562 if (size > 1) { 563 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 564 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 565 } 566 if (debug) { 567 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 568 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 569 } 570 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 571 for (p = pStart; p < pEnd; ++p) { 572 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 573 574 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 575 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 576 if (!dof) continue; 577 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 578 if (adof <= 0) continue; 579 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 580 for (q = 0; q < numAdj; ++q) { 581 PetscInt ndof, ncdof; 582 583 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 584 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 585 for (d = off; d < off+dof; ++d) { 586 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 587 } 588 } 589 } 590 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 591 if (debug) { 592 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 593 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 594 } 595 /* Create adj SF based on dof SF */ 596 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 597 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 598 if (debug) { 599 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 600 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 601 } 602 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 603 /* Create leaf adjacency */ 604 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 605 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 606 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 607 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 608 for (l = 0; l < nleaves; ++l) { 609 PetscInt dof, off, d, q; 610 PetscInt p = leaves[l], numAdj = maxAdjSize; 611 612 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 613 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 614 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 615 for (d = off; d < off+dof; ++d) { 616 PetscInt aoff, i = 0; 617 618 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 619 for (q = 0; q < numAdj; ++q) { 620 PetscInt ndof, ncdof, ngoff, nd; 621 622 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 623 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 624 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 625 for (nd = 0; nd < ndof-ncdof; ++nd) { 626 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 627 ++i; 628 } 629 } 630 } 631 } 632 /* Debugging */ 633 if (debug) { 634 IS tmp; 635 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 636 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 637 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 638 } 639 /* Gather adjacenct indices to root */ 640 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 641 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 642 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 643 if (size > 1) { 644 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 645 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 646 } 647 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 648 ierr = PetscFree(adj);CHKERRQ(ierr); 649 /* Debugging */ 650 if (debug) { 651 IS tmp; 652 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 653 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 654 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 655 } 656 /* Add in local adjacency indices for owned dofs on interface (roots) */ 657 for (p = pStart; p < pEnd; ++p) { 658 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 659 660 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 661 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 662 if (!dof) continue; 663 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 664 if (adof <= 0) continue; 665 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 666 for (d = off; d < off+dof; ++d) { 667 PetscInt adof, aoff, i; 668 669 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 670 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 671 i = adof-1; 672 for (q = 0; q < numAdj; ++q) { 673 PetscInt ndof, ncdof, ngoff, nd; 674 675 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 676 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 677 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 678 for (nd = 0; nd < ndof-ncdof; ++nd) { 679 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 680 --i; 681 } 682 } 683 } 684 } 685 /* Debugging */ 686 if (debug) { 687 IS tmp; 688 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 689 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 690 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 691 } 692 /* Compress indices */ 693 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 694 for (p = pStart; p < pEnd; ++p) { 695 PetscInt dof, cdof, off, d; 696 PetscInt adof, aoff; 697 698 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 699 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 700 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 701 if (!dof) continue; 702 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 703 if (adof <= 0) continue; 704 for (d = off; d < off+dof-cdof; ++d) { 705 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 706 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 707 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 708 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 709 } 710 } 711 /* Debugging */ 712 if (debug) { 713 IS tmp; 714 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 715 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 716 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 717 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 718 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 719 } 720 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 721 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 722 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 723 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 724 for (p = pStart; p < pEnd; ++p) { 725 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 726 PetscBool found = PETSC_TRUE; 727 728 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 729 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 730 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 731 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 732 for (d = 0; d < dof-cdof; ++d) { 733 PetscInt ldof, rdof; 734 735 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 736 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 737 if (ldof > 0) { 738 /* We do not own this point */ 739 } else if (rdof > 0) { 740 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 741 } else { 742 found = PETSC_FALSE; 743 } 744 } 745 if (found) continue; 746 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 747 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 748 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 749 for (q = 0; q < numAdj; ++q) { 750 PetscInt ndof, ncdof, noff; 751 752 /* Adjacent points may not be in the section chart */ 753 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 754 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 755 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 756 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 757 for (d = goff; d < goff+dof-cdof; ++d) { 758 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 759 } 760 } 761 } 762 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 763 if (debug) { 764 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 765 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 766 } 767 /* Get adjacent indices */ 768 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 769 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 770 for (p = pStart; p < pEnd; ++p) { 771 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 772 PetscBool found = PETSC_TRUE; 773 774 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 775 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 776 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 777 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 778 for (d = 0; d < dof-cdof; ++d) { 779 PetscInt ldof, rdof; 780 781 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 782 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 783 if (ldof > 0) { 784 /* We do not own this point */ 785 } else if (rdof > 0) { 786 PetscInt aoff, roff; 787 788 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 789 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 790 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 791 } else { 792 found = PETSC_FALSE; 793 } 794 } 795 if (found) continue; 796 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 797 for (d = goff; d < goff+dof-cdof; ++d) { 798 PetscInt adof, aoff, i = 0; 799 800 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 801 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 802 for (q = 0; q < numAdj; ++q) { 803 PetscInt ndof, ncdof, ngoff, nd; 804 const PetscInt *ncind; 805 806 /* Adjacent points may not be in the section chart */ 807 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 808 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 809 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 810 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 811 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 812 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 813 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 814 } 815 } 816 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 817 } 818 } 819 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 820 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 821 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 822 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 823 /* Debugging */ 824 if (debug) { 825 IS tmp; 826 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 827 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 828 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 829 } 830 /* Create allocation vectors from adjacency graph */ 831 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 832 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr); 833 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 834 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 835 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 836 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 837 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 838 /* Only loop over blocks of rows */ 839 if (rStart%bs || rEnd%bs) SETERRQ3(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 840 for (r = rStart/bs; r < rEnd/bs; ++r) { 841 const PetscInt row = r*bs; 842 PetscInt numCols, cStart, c; 843 844 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 845 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 846 for (c = cStart; c < cStart+numCols; ++c) { 847 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 848 ++dnz[r-rStart]; 849 if (cols[c] >= row) ++dnzu[r-rStart]; 850 } else { 851 ++onz[r-rStart]; 852 if (cols[c] >= row) ++onzu[r-rStart]; 853 } 854 } 855 } 856 if (bs > 1) { 857 for (r = 0; r < locRows/bs; ++r) { 858 dnz[r] /= bs; 859 onz[r] /= bs; 860 dnzu[r] /= bs; 861 onzu[r] /= bs; 862 } 863 } 864 /* Set matrix pattern */ 865 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 866 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 867 /* Fill matrix with zeros */ 868 if (fillMatrix) { 869 PetscScalar *values; 870 PetscInt maxRowLen = 0; 871 872 for (r = rStart; r < rEnd; ++r) { 873 PetscInt len; 874 875 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 876 maxRowLen = PetscMax(maxRowLen, len); 877 } 878 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 879 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 880 for (r = rStart; r < rEnd; ++r) { 881 PetscInt numCols, cStart; 882 883 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 884 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 885 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 886 } 887 ierr = PetscFree(values);CHKERRQ(ierr); 888 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 889 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 890 } 891 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 892 ierr = PetscFree(cols);CHKERRQ(ierr); 893 PetscFunctionReturn(0); 894 } 895 896 #if 0 897 #undef __FUNCT__ 898 #define __FUNCT__ "DMPlexPreallocateOperator_2" 899 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 900 { 901 PetscInt *tmpClosure,*tmpAdj,*visits; 902 PetscInt c,cStart,cEnd,pStart,pEnd; 903 PetscErrorCode ierr; 904 905 PetscFunctionBegin; 906 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 907 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 908 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 909 910 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 911 912 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 913 npoints = pEnd - pStart; 914 915 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 916 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 917 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 918 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 919 for (c=cStart; c<cEnd; c++) { 920 PetscInt *support = tmpClosure; 921 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 922 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 923 } 924 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 925 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 926 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 927 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 928 929 ierr = PetscSFGetRanks();CHKERRQ(ierr); 930 931 932 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 933 for (c=cStart; c<cEnd; c++) { 934 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 935 /* 936 Depth-first walk of transitive closure. 937 At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 938 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 939 */ 940 } 941 942 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 943 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 944 PetscFunctionReturn(0); 945 } 946 #endif 947 948 #undef __FUNCT__ 949 #define __FUNCT__ "DMCreateMatrix_Plex" 950 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 951 { 952 PetscSection section, sectionGlobal; 953 PetscInt bs = -1; 954 PetscInt localSize; 955 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 956 PetscErrorCode ierr; 957 958 PetscFunctionBegin; 959 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 960 ierr = MatInitializePackage(NULL);CHKERRQ(ierr); 961 #endif 962 if (!mtype) mtype = MATAIJ; 963 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 964 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 965 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 966 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 967 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 968 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 969 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 970 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 974 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 975 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 976 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 977 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 978 /* Check for symmetric storage */ 979 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 980 if (isSymmetric) { 981 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 982 } 983 if (!isShell) { 984 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 985 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 986 987 if (bs < 0) { 988 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 989 PetscInt pStart, pEnd, p, dof, cdof; 990 991 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 992 for (p = pStart; p < pEnd; ++p) { 993 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 994 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 995 if (dof-cdof) { 996 if (bs < 0) { 997 bs = dof-cdof; 998 } else if (bs != dof-cdof) { 999 /* Layout does not admit a pointwise block size */ 1000 bs = 1; 1001 break; 1002 } 1003 } 1004 } 1005 /* Must have same blocksize on all procs (some might have no points) */ 1006 bsLocal = bs; 1007 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1008 bsLocal = bs < 0 ? bsMax : bs; 1009 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1010 if (bsMin != bsMax) { 1011 bs = 1; 1012 } else { 1013 bs = bsMax; 1014 } 1015 } else { 1016 bs = 1; 1017 } 1018 } 1019 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1020 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1021 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1022 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1023 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1024 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1025 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1026 } 1027 PetscFunctionReturn(0); 1028 } 1029 1030 #undef __FUNCT__ 1031 #define __FUNCT__ "DMPlexGetDimension" 1032 /*@ 1033 DMPlexGetDimension - Return the topological mesh dimension 1034 1035 Not collective 1036 1037 Input Parameter: 1038 . mesh - The DMPlex 1039 1040 Output Parameter: 1041 . dim - The topological mesh dimension 1042 1043 Level: beginner 1044 1045 .seealso: DMPlexCreate() 1046 @*/ 1047 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1048 { 1049 DM_Plex *mesh = (DM_Plex*) dm->data; 1050 1051 PetscFunctionBegin; 1052 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1053 PetscValidPointer(dim, 2); 1054 *dim = mesh->dim; 1055 PetscFunctionReturn(0); 1056 } 1057 1058 #undef __FUNCT__ 1059 #define __FUNCT__ "DMPlexSetDimension" 1060 /*@ 1061 DMPlexSetDimension - Set the topological mesh dimension 1062 1063 Collective on mesh 1064 1065 Input Parameters: 1066 + mesh - The DMPlex 1067 - dim - The topological mesh dimension 1068 1069 Level: beginner 1070 1071 .seealso: DMPlexCreate() 1072 @*/ 1073 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1074 { 1075 DM_Plex *mesh = (DM_Plex*) dm->data; 1076 1077 PetscFunctionBegin; 1078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1079 PetscValidLogicalCollectiveInt(dm, dim, 2); 1080 mesh->dim = dim; 1081 mesh->preallocCenterDim = dim; 1082 PetscFunctionReturn(0); 1083 } 1084 1085 #undef __FUNCT__ 1086 #define __FUNCT__ "DMPlexGetChart" 1087 /*@ 1088 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1089 1090 Not collective 1091 1092 Input Parameter: 1093 . mesh - The DMPlex 1094 1095 Output Parameters: 1096 + pStart - The first mesh point 1097 - pEnd - The upper bound for mesh points 1098 1099 Level: beginner 1100 1101 .seealso: DMPlexCreate(), DMPlexSetChart() 1102 @*/ 1103 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1104 { 1105 DM_Plex *mesh = (DM_Plex*) dm->data; 1106 PetscErrorCode ierr; 1107 1108 PetscFunctionBegin; 1109 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1110 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1111 PetscFunctionReturn(0); 1112 } 1113 1114 #undef __FUNCT__ 1115 #define __FUNCT__ "DMPlexSetChart" 1116 /*@ 1117 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1118 1119 Not collective 1120 1121 Input Parameters: 1122 + mesh - The DMPlex 1123 . pStart - The first mesh point 1124 - pEnd - The upper bound for mesh points 1125 1126 Output Parameters: 1127 1128 Level: beginner 1129 1130 .seealso: DMPlexCreate(), DMPlexGetChart() 1131 @*/ 1132 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1133 { 1134 DM_Plex *mesh = (DM_Plex*) dm->data; 1135 PetscErrorCode ierr; 1136 1137 PetscFunctionBegin; 1138 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1139 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1140 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1141 PetscFunctionReturn(0); 1142 } 1143 1144 #undef __FUNCT__ 1145 #define __FUNCT__ "DMPlexGetConeSize" 1146 /*@ 1147 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1148 1149 Not collective 1150 1151 Input Parameters: 1152 + mesh - The DMPlex 1153 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1154 1155 Output Parameter: 1156 . size - The cone size for point p 1157 1158 Level: beginner 1159 1160 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1161 @*/ 1162 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1163 { 1164 DM_Plex *mesh = (DM_Plex*) dm->data; 1165 PetscErrorCode ierr; 1166 1167 PetscFunctionBegin; 1168 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1169 PetscValidPointer(size, 3); 1170 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1171 PetscFunctionReturn(0); 1172 } 1173 1174 #undef __FUNCT__ 1175 #define __FUNCT__ "DMPlexSetConeSize" 1176 /*@ 1177 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1178 1179 Not collective 1180 1181 Input Parameters: 1182 + mesh - The DMPlex 1183 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1184 - size - The cone size for point p 1185 1186 Output Parameter: 1187 1188 Note: 1189 This should be called after DMPlexSetChart(). 1190 1191 Level: beginner 1192 1193 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1194 @*/ 1195 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1196 { 1197 DM_Plex *mesh = (DM_Plex*) dm->data; 1198 PetscErrorCode ierr; 1199 1200 PetscFunctionBegin; 1201 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1202 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1203 1204 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1205 PetscFunctionReturn(0); 1206 } 1207 1208 #undef __FUNCT__ 1209 #define __FUNCT__ "DMPlexGetCone" 1210 /*@C 1211 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1212 1213 Not collective 1214 1215 Input Parameters: 1216 + mesh - The DMPlex 1217 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1218 1219 Output Parameter: 1220 . cone - An array of points which are on the in-edges for point p 1221 1222 Level: beginner 1223 1224 Note: 1225 This routine is not available in Fortran. 1226 1227 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1228 @*/ 1229 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1230 { 1231 DM_Plex *mesh = (DM_Plex*) dm->data; 1232 PetscInt off; 1233 PetscErrorCode ierr; 1234 1235 PetscFunctionBegin; 1236 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1237 PetscValidPointer(cone, 3); 1238 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1239 *cone = &mesh->cones[off]; 1240 PetscFunctionReturn(0); 1241 } 1242 1243 #undef __FUNCT__ 1244 #define __FUNCT__ "DMPlexSetCone" 1245 /*@ 1246 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1247 1248 Not collective 1249 1250 Input Parameters: 1251 + mesh - The DMPlex 1252 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1253 - cone - An array of points which are on the in-edges for point p 1254 1255 Output Parameter: 1256 1257 Note: 1258 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1259 1260 Level: beginner 1261 1262 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1263 @*/ 1264 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1265 { 1266 DM_Plex *mesh = (DM_Plex*) dm->data; 1267 PetscInt pStart, pEnd; 1268 PetscInt dof, off, c; 1269 PetscErrorCode ierr; 1270 1271 PetscFunctionBegin; 1272 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1273 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1274 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1275 if (dof) PetscValidPointer(cone, 3); 1276 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1277 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1278 for (c = 0; c < dof; ++c) { 1279 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1280 mesh->cones[off+c] = cone[c]; 1281 } 1282 PetscFunctionReturn(0); 1283 } 1284 1285 #undef __FUNCT__ 1286 #define __FUNCT__ "DMPlexGetConeOrientation" 1287 /*@C 1288 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1289 1290 Not collective 1291 1292 Input Parameters: 1293 + mesh - The DMPlex 1294 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1295 1296 Output Parameter: 1297 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1298 integer giving the prescription for cone traversal. If it is negative, the cone is 1299 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1300 the index of the cone point on which to start. 1301 1302 Level: beginner 1303 1304 Note: 1305 This routine is not available in Fortran. 1306 1307 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1308 @*/ 1309 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1310 { 1311 DM_Plex *mesh = (DM_Plex*) dm->data; 1312 PetscInt off; 1313 PetscErrorCode ierr; 1314 1315 PetscFunctionBegin; 1316 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1317 #if defined(PETSC_USE_DEBUG) 1318 { 1319 PetscInt dof; 1320 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1321 if (dof) PetscValidPointer(coneOrientation, 3); 1322 } 1323 #endif 1324 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1325 1326 *coneOrientation = &mesh->coneOrientations[off]; 1327 PetscFunctionReturn(0); 1328 } 1329 1330 #undef __FUNCT__ 1331 #define __FUNCT__ "DMPlexSetConeOrientation" 1332 /*@ 1333 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1334 1335 Not collective 1336 1337 Input Parameters: 1338 + mesh - The DMPlex 1339 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1340 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1341 integer giving the prescription for cone traversal. If it is negative, the cone is 1342 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1343 the index of the cone point on which to start. 1344 1345 Output Parameter: 1346 1347 Note: 1348 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1349 1350 Level: beginner 1351 1352 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1353 @*/ 1354 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1355 { 1356 DM_Plex *mesh = (DM_Plex*) dm->data; 1357 PetscInt pStart, pEnd; 1358 PetscInt dof, off, c; 1359 PetscErrorCode ierr; 1360 1361 PetscFunctionBegin; 1362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1363 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1364 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1365 if (dof) PetscValidPointer(coneOrientation, 3); 1366 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1367 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1368 for (c = 0; c < dof; ++c) { 1369 PetscInt cdof, o = coneOrientation[c]; 1370 1371 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1372 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1373 mesh->coneOrientations[off+c] = o; 1374 } 1375 PetscFunctionReturn(0); 1376 } 1377 1378 #undef __FUNCT__ 1379 #define __FUNCT__ "DMPlexInsertCone" 1380 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1381 { 1382 DM_Plex *mesh = (DM_Plex*) dm->data; 1383 PetscInt pStart, pEnd; 1384 PetscInt dof, off; 1385 PetscErrorCode ierr; 1386 1387 PetscFunctionBegin; 1388 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1389 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1390 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1391 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1392 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1393 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1394 if (conePos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1395 mesh->cones[off+conePos] = conePoint; 1396 PetscFunctionReturn(0); 1397 } 1398 1399 #undef __FUNCT__ 1400 #define __FUNCT__ "DMPlexGetSupportSize" 1401 /*@ 1402 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1403 1404 Not collective 1405 1406 Input Parameters: 1407 + mesh - The DMPlex 1408 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1409 1410 Output Parameter: 1411 . size - The support size for point p 1412 1413 Level: beginner 1414 1415 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1416 @*/ 1417 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1418 { 1419 DM_Plex *mesh = (DM_Plex*) dm->data; 1420 PetscErrorCode ierr; 1421 1422 PetscFunctionBegin; 1423 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1424 PetscValidPointer(size, 3); 1425 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1426 PetscFunctionReturn(0); 1427 } 1428 1429 #undef __FUNCT__ 1430 #define __FUNCT__ "DMPlexSetSupportSize" 1431 /*@ 1432 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1433 1434 Not collective 1435 1436 Input Parameters: 1437 + mesh - The DMPlex 1438 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1439 - size - The support size for point p 1440 1441 Output Parameter: 1442 1443 Note: 1444 This should be called after DMPlexSetChart(). 1445 1446 Level: beginner 1447 1448 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1449 @*/ 1450 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1451 { 1452 DM_Plex *mesh = (DM_Plex*) dm->data; 1453 PetscErrorCode ierr; 1454 1455 PetscFunctionBegin; 1456 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1457 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1458 1459 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1460 PetscFunctionReturn(0); 1461 } 1462 1463 #undef __FUNCT__ 1464 #define __FUNCT__ "DMPlexGetSupport" 1465 /*@C 1466 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1467 1468 Not collective 1469 1470 Input Parameters: 1471 + mesh - The DMPlex 1472 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1473 1474 Output Parameter: 1475 . support - An array of points which are on the out-edges for point p 1476 1477 Level: beginner 1478 1479 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1480 @*/ 1481 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1482 { 1483 DM_Plex *mesh = (DM_Plex*) dm->data; 1484 PetscInt off; 1485 PetscErrorCode ierr; 1486 1487 PetscFunctionBegin; 1488 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1489 PetscValidPointer(support, 3); 1490 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1491 *support = &mesh->supports[off]; 1492 PetscFunctionReturn(0); 1493 } 1494 1495 #undef __FUNCT__ 1496 #define __FUNCT__ "DMPlexSetSupport" 1497 /*@ 1498 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1499 1500 Not collective 1501 1502 Input Parameters: 1503 + mesh - The DMPlex 1504 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1505 - support - An array of points which are on the in-edges for point p 1506 1507 Output Parameter: 1508 1509 Note: 1510 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1511 1512 Level: beginner 1513 1514 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1515 @*/ 1516 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1517 { 1518 DM_Plex *mesh = (DM_Plex*) dm->data; 1519 PetscInt pStart, pEnd; 1520 PetscInt dof, off, c; 1521 PetscErrorCode ierr; 1522 1523 PetscFunctionBegin; 1524 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1525 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1526 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1527 if (dof) PetscValidPointer(support, 3); 1528 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1529 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1530 for (c = 0; c < dof; ++c) { 1531 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1532 mesh->supports[off+c] = support[c]; 1533 } 1534 PetscFunctionReturn(0); 1535 } 1536 1537 #undef __FUNCT__ 1538 #define __FUNCT__ "DMPlexInsertSupport" 1539 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1540 { 1541 DM_Plex *mesh = (DM_Plex*) dm->data; 1542 PetscInt pStart, pEnd; 1543 PetscInt dof, off; 1544 PetscErrorCode ierr; 1545 1546 PetscFunctionBegin; 1547 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1548 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1549 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1550 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1551 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1552 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1553 if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1554 mesh->supports[off+supportPos] = supportPoint; 1555 PetscFunctionReturn(0); 1556 } 1557 1558 #undef __FUNCT__ 1559 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1560 /*@C 1561 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1562 1563 Not collective 1564 1565 Input Parameters: 1566 + mesh - The DMPlex 1567 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1568 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1569 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1570 1571 Output Parameters: 1572 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1573 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1574 1575 Note: 1576 If using internal storage (points is NULL on input), each call overwrites the last output. 1577 1578 Level: beginner 1579 1580 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1581 @*/ 1582 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1583 { 1584 DM_Plex *mesh = (DM_Plex*) dm->data; 1585 PetscInt *closure, *fifo; 1586 const PetscInt *tmp = NULL, *tmpO = NULL; 1587 PetscInt tmpSize, t; 1588 PetscInt depth = 0, maxSize; 1589 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1590 PetscErrorCode ierr; 1591 1592 PetscFunctionBegin; 1593 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1594 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1595 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1596 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1597 if (*points) { 1598 closure = *points; 1599 } else { 1600 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1601 } 1602 closure[0] = p; closure[1] = 0; 1603 /* This is only 1-level */ 1604 if (useCone) { 1605 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1606 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1607 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1608 } else { 1609 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1610 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1611 } 1612 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1613 const PetscInt cp = tmp[t]; 1614 const PetscInt co = tmpO ? tmpO[t] : 0; 1615 1616 closure[closureSize] = cp; 1617 closure[closureSize+1] = co; 1618 fifo[fifoSize] = cp; 1619 fifo[fifoSize+1] = co; 1620 } 1621 while (fifoSize - fifoStart) { 1622 const PetscInt q = fifo[fifoStart]; 1623 const PetscInt o = fifo[fifoStart+1]; 1624 const PetscInt rev = o >= 0 ? 0 : 1; 1625 const PetscInt off = rev ? -(o+1) : o; 1626 1627 if (useCone) { 1628 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1629 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1630 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1631 } else { 1632 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1633 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1634 tmpO = NULL; 1635 } 1636 for (t = 0; t < tmpSize; ++t) { 1637 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1638 const PetscInt cp = tmp[i]; 1639 /* Must propogate orientation */ 1640 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1641 PetscInt c; 1642 1643 /* Check for duplicate */ 1644 for (c = 0; c < closureSize; c += 2) { 1645 if (closure[c] == cp) break; 1646 } 1647 if (c == closureSize) { 1648 closure[closureSize] = cp; 1649 closure[closureSize+1] = co; 1650 fifo[fifoSize] = cp; 1651 fifo[fifoSize+1] = co; 1652 closureSize += 2; 1653 fifoSize += 2; 1654 } 1655 } 1656 fifoStart += 2; 1657 } 1658 if (numPoints) *numPoints = closureSize/2; 1659 if (points) *points = closure; 1660 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1661 PetscFunctionReturn(0); 1662 } 1663 1664 #undef __FUNCT__ 1665 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1666 /*@C 1667 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1668 1669 Not collective 1670 1671 Input Parameters: 1672 + mesh - The DMPlex 1673 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1674 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1675 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1676 1677 Output Parameters: 1678 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1679 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1680 1681 Note: 1682 If not using internal storage (points is not NULL on input), this call is unnecessary 1683 1684 Level: beginner 1685 1686 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1687 @*/ 1688 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1689 { 1690 PetscErrorCode ierr; 1691 1692 PetscFunctionBegin; 1693 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1694 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1695 PetscFunctionReturn(0); 1696 } 1697 1698 #undef __FUNCT__ 1699 #define __FUNCT__ "DMPlexGetFaces" 1700 /* 1701 DMPlexGetFaces - 1702 1703 Note: This will only work for cell-vertex meshes. 1704 */ 1705 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1706 { 1707 DM_Plex *mesh = (DM_Plex*) dm->data; 1708 const PetscInt *cone = NULL; 1709 PetscInt depth = 0, dim, coneSize; 1710 PetscErrorCode ierr; 1711 1712 PetscFunctionBegin; 1713 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1714 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1715 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1716 if (depth > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1717 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1718 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1719 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1720 switch (dim) { 1721 case 2: 1722 switch (coneSize) { 1723 case 3: 1724 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1725 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1726 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1727 *numFaces = 3; 1728 *faceSize = 2; 1729 *faces = mesh->facesTmp; 1730 break; 1731 case 4: 1732 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1733 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1734 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1735 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1736 *numFaces = 4; 1737 *faceSize = 2; 1738 *faces = mesh->facesTmp; 1739 break; 1740 default: 1741 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1742 } 1743 break; 1744 case 3: 1745 switch (coneSize) { 1746 case 3: 1747 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1748 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1749 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1750 *numFaces = 3; 1751 *faceSize = 2; 1752 *faces = mesh->facesTmp; 1753 break; 1754 case 4: 1755 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1756 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1757 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1758 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1759 *numFaces = 4; 1760 *faceSize = 3; 1761 *faces = mesh->facesTmp; 1762 break; 1763 default: 1764 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1765 } 1766 break; 1767 default: 1768 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1769 } 1770 PetscFunctionReturn(0); 1771 } 1772 1773 #undef __FUNCT__ 1774 #define __FUNCT__ "DMPlexGetMaxSizes" 1775 /*@ 1776 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1777 1778 Not collective 1779 1780 Input Parameter: 1781 . mesh - The DMPlex 1782 1783 Output Parameters: 1784 + maxConeSize - The maximum number of in-edges 1785 - maxSupportSize - The maximum number of out-edges 1786 1787 Level: beginner 1788 1789 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1790 @*/ 1791 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1792 { 1793 DM_Plex *mesh = (DM_Plex*) dm->data; 1794 1795 PetscFunctionBegin; 1796 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1797 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1798 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1799 PetscFunctionReturn(0); 1800 } 1801 1802 #undef __FUNCT__ 1803 #define __FUNCT__ "DMSetUp_Plex" 1804 PetscErrorCode DMSetUp_Plex(DM dm) 1805 { 1806 DM_Plex *mesh = (DM_Plex*) dm->data; 1807 PetscInt size; 1808 PetscErrorCode ierr; 1809 1810 PetscFunctionBegin; 1811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1812 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1813 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1814 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1815 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1816 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1817 if (mesh->maxSupportSize) { 1818 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1819 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1820 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1821 } 1822 PetscFunctionReturn(0); 1823 } 1824 1825 #undef __FUNCT__ 1826 #define __FUNCT__ "DMCreateSubDM_Plex" 1827 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1828 { 1829 PetscSection section, sectionGlobal; 1830 PetscInt *subIndices; 1831 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1832 PetscErrorCode ierr; 1833 1834 PetscFunctionBegin; 1835 if (!numFields) PetscFunctionReturn(0); 1836 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1837 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1838 if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1839 if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1840 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1841 if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1842 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1843 for (p = pStart; p < pEnd; ++p) { 1844 PetscInt gdof; 1845 1846 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1847 if (gdof > 0) { 1848 for (f = 0; f < numFields; ++f) { 1849 PetscInt fdof, fcdof; 1850 1851 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1852 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1853 subSize += fdof-fcdof; 1854 } 1855 } 1856 } 1857 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1858 for (p = pStart; p < pEnd; ++p) { 1859 PetscInt gdof, goff; 1860 1861 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1862 if (gdof > 0) { 1863 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1864 for (f = 0; f < numFields; ++f) { 1865 PetscInt fdof, fcdof, fc, f2, poff = 0; 1866 1867 /* Can get rid of this loop by storing field information in the global section */ 1868 for (f2 = 0; f2 < fields[f]; ++f2) { 1869 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1870 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1871 poff += fdof-fcdof; 1872 } 1873 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1874 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1875 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1876 subIndices[subOff] = goff+poff+fc; 1877 } 1878 } 1879 } 1880 } 1881 if (is) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1882 if (subdm) { 1883 PetscSection subsection; 1884 PetscBool haveNull = PETSC_FALSE; 1885 PetscInt f, nf = 0; 1886 1887 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1888 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1889 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1890 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 1891 for (f = 0; f < numFields; ++f) { 1892 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1893 if ((*subdm)->nullspaceConstructors[f]) { 1894 haveNull = PETSC_TRUE; 1895 nf = f; 1896 } 1897 } 1898 if (haveNull) { 1899 MatNullSpace nullSpace; 1900 1901 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1902 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1903 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1904 } 1905 if (dm->fields) { 1906 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); 1907 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1908 for (f = 0; f < numFields; ++f) { 1909 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1910 } 1911 if (numFields == 1) { 1912 MatNullSpace space; 1913 Mat pmat; 1914 1915 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1916 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1917 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1918 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1919 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1920 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1921 } 1922 } 1923 } 1924 PetscFunctionReturn(0); 1925 } 1926 1927 #undef __FUNCT__ 1928 #define __FUNCT__ "DMPlexSymmetrize" 1929 /*@ 1930 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1931 1932 Not collective 1933 1934 Input Parameter: 1935 . mesh - The DMPlex 1936 1937 Output Parameter: 1938 1939 Note: 1940 This should be called after all calls to DMPlexSetCone() 1941 1942 Level: beginner 1943 1944 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1945 @*/ 1946 PetscErrorCode DMPlexSymmetrize(DM dm) 1947 { 1948 DM_Plex *mesh = (DM_Plex*) dm->data; 1949 PetscInt *offsets; 1950 PetscInt supportSize; 1951 PetscInt pStart, pEnd, p; 1952 PetscErrorCode ierr; 1953 1954 PetscFunctionBegin; 1955 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1956 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1957 /* Calculate support sizes */ 1958 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1959 for (p = pStart; p < pEnd; ++p) { 1960 PetscInt dof, off, c; 1961 1962 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1963 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1964 for (c = off; c < off+dof; ++c) { 1965 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1966 } 1967 } 1968 for (p = pStart; p < pEnd; ++p) { 1969 PetscInt dof; 1970 1971 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1972 1973 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1974 } 1975 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1976 /* Calculate supports */ 1977 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1978 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1979 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1980 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1981 for (p = pStart; p < pEnd; ++p) { 1982 PetscInt dof, off, c; 1983 1984 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1985 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1986 for (c = off; c < off+dof; ++c) { 1987 const PetscInt q = mesh->cones[c]; 1988 PetscInt offS; 1989 1990 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1991 1992 mesh->supports[offS+offsets[q]] = p; 1993 ++offsets[q]; 1994 } 1995 } 1996 ierr = PetscFree(offsets);CHKERRQ(ierr); 1997 PetscFunctionReturn(0); 1998 } 1999 2000 #undef __FUNCT__ 2001 #define __FUNCT__ "DMPlexSetDepth_Private" 2002 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 2003 { 2004 PetscInt d; 2005 PetscErrorCode ierr; 2006 2007 PetscFunctionBegin; 2008 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 2009 if (d < 0) { 2010 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2011 const PetscInt *cone = NULL; 2012 PetscInt dCone; 2013 2014 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2015 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2016 d = dCone+1; 2017 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2018 } 2019 *depth = d; 2020 PetscFunctionReturn(0); 2021 } 2022 2023 #undef __FUNCT__ 2024 #define __FUNCT__ "DMPlexStratify" 2025 /*@ 2026 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2027 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2028 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2029 the DAG. 2030 2031 Not collective 2032 2033 Input Parameter: 2034 . mesh - The DMPlex 2035 2036 Output Parameter: 2037 2038 Notes: 2039 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2040 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2041 2042 This should be called after all calls to DMPlexSymmetrize() 2043 2044 Level: beginner 2045 2046 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2047 @*/ 2048 PetscErrorCode DMPlexStratify(DM dm) 2049 { 2050 DM_Plex *mesh = (DM_Plex*) dm->data; 2051 PetscInt pStart, pEnd, p; 2052 PetscInt numRoots = 0, numLeaves = 0; 2053 PetscErrorCode ierr; 2054 2055 PetscFunctionBegin; 2056 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2057 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2058 /* Calculate depth */ 2059 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2060 /* Initialize roots and count leaves */ 2061 for (p = pStart; p < pEnd; ++p) { 2062 PetscInt coneSize, supportSize; 2063 2064 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2065 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2066 if (!coneSize && supportSize) { 2067 ++numRoots; 2068 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2069 } else if (!supportSize && coneSize) { 2070 ++numLeaves; 2071 } else if (!supportSize && !coneSize) { 2072 /* Isolated points */ 2073 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2074 } 2075 } 2076 if (numRoots + numLeaves == (pEnd - pStart)) { 2077 for (p = pStart; p < pEnd; ++p) { 2078 PetscInt coneSize, supportSize; 2079 2080 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2081 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2082 if (!supportSize && coneSize) { 2083 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2084 } 2085 } 2086 } else { 2087 /* This might be slow since lookup is not fast */ 2088 for (p = pStart; p < pEnd; ++p) { 2089 PetscInt depth; 2090 2091 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2092 } 2093 } 2094 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2095 PetscFunctionReturn(0); 2096 } 2097 2098 #undef __FUNCT__ 2099 #define __FUNCT__ "DMPlexGetJoin" 2100 /*@C 2101 DMPlexGetJoin - Get an array for the join of the set of points 2102 2103 Not Collective 2104 2105 Input Parameters: 2106 + dm - The DMPlex object 2107 . numPoints - The number of input points for the join 2108 - points - The input points 2109 2110 Output Parameters: 2111 + numCoveredPoints - The number of points in the join 2112 - coveredPoints - The points in the join 2113 2114 Level: intermediate 2115 2116 Note: Currently, this is restricted to a single level join 2117 2118 .keywords: mesh 2119 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2120 @*/ 2121 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2122 { 2123 DM_Plex *mesh = (DM_Plex*) dm->data; 2124 PetscInt *join[2]; 2125 PetscInt joinSize, i = 0; 2126 PetscInt dof, off, p, c, m; 2127 PetscErrorCode ierr; 2128 2129 PetscFunctionBegin; 2130 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2131 PetscValidPointer(points, 2); 2132 PetscValidPointer(numCoveredPoints, 3); 2133 PetscValidPointer(coveredPoints, 4); 2134 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2135 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2136 /* Copy in support of first point */ 2137 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2138 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2139 for (joinSize = 0; joinSize < dof; ++joinSize) { 2140 join[i][joinSize] = mesh->supports[off+joinSize]; 2141 } 2142 /* Check each successive support */ 2143 for (p = 1; p < numPoints; ++p) { 2144 PetscInt newJoinSize = 0; 2145 2146 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2147 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2148 for (c = 0; c < dof; ++c) { 2149 const PetscInt point = mesh->supports[off+c]; 2150 2151 for (m = 0; m < joinSize; ++m) { 2152 if (point == join[i][m]) { 2153 join[1-i][newJoinSize++] = point; 2154 break; 2155 } 2156 } 2157 } 2158 joinSize = newJoinSize; 2159 i = 1-i; 2160 } 2161 *numCoveredPoints = joinSize; 2162 *coveredPoints = join[i]; 2163 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2164 PetscFunctionReturn(0); 2165 } 2166 2167 #undef __FUNCT__ 2168 #define __FUNCT__ "DMPlexRestoreJoin" 2169 /*@C 2170 DMPlexRestoreJoin - Restore an array for the join of the set of points 2171 2172 Not Collective 2173 2174 Input Parameters: 2175 + dm - The DMPlex object 2176 . numPoints - The number of input points for the join 2177 - points - The input points 2178 2179 Output Parameters: 2180 + numCoveredPoints - The number of points in the join 2181 - coveredPoints - The points in the join 2182 2183 Level: intermediate 2184 2185 .keywords: mesh 2186 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2187 @*/ 2188 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2189 { 2190 PetscErrorCode ierr; 2191 2192 PetscFunctionBegin; 2193 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2194 PetscValidPointer(coveredPoints, 4); 2195 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2196 PetscFunctionReturn(0); 2197 } 2198 2199 #undef __FUNCT__ 2200 #define __FUNCT__ "DMPlexGetFullJoin" 2201 /*@C 2202 DMPlexGetFullJoin - Get an array for the join of the set of points 2203 2204 Not Collective 2205 2206 Input Parameters: 2207 + dm - The DMPlex object 2208 . numPoints - The number of input points for the join 2209 - points - The input points 2210 2211 Output Parameters: 2212 + numCoveredPoints - The number of points in the join 2213 - coveredPoints - The points in the join 2214 2215 Level: intermediate 2216 2217 .keywords: mesh 2218 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2219 @*/ 2220 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2221 { 2222 DM_Plex *mesh = (DM_Plex*) dm->data; 2223 PetscInt *offsets, **closures; 2224 PetscInt *join[2]; 2225 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2226 PetscInt p, d, c, m; 2227 PetscErrorCode ierr; 2228 2229 PetscFunctionBegin; 2230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2231 PetscValidPointer(points, 2); 2232 PetscValidPointer(numCoveredPoints, 3); 2233 PetscValidPointer(coveredPoints, 4); 2234 2235 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2236 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2237 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2238 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2239 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2240 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2241 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2242 2243 for (p = 0; p < numPoints; ++p) { 2244 PetscInt closureSize; 2245 2246 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2247 2248 offsets[p*(depth+2)+0] = 0; 2249 for (d = 0; d < depth+1; ++d) { 2250 PetscInt pStart, pEnd, i; 2251 2252 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2253 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2254 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2255 offsets[p*(depth+2)+d+1] = i; 2256 break; 2257 } 2258 } 2259 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2260 } 2261 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); 2262 } 2263 for (d = 0; d < depth+1; ++d) { 2264 PetscInt dof; 2265 2266 /* Copy in support of first point */ 2267 dof = offsets[d+1] - offsets[d]; 2268 for (joinSize = 0; joinSize < dof; ++joinSize) { 2269 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2270 } 2271 /* Check each successive cone */ 2272 for (p = 1; p < numPoints && joinSize; ++p) { 2273 PetscInt newJoinSize = 0; 2274 2275 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2276 for (c = 0; c < dof; ++c) { 2277 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2278 2279 for (m = 0; m < joinSize; ++m) { 2280 if (point == join[i][m]) { 2281 join[1-i][newJoinSize++] = point; 2282 break; 2283 } 2284 } 2285 } 2286 joinSize = newJoinSize; 2287 i = 1-i; 2288 } 2289 if (joinSize) break; 2290 } 2291 *numCoveredPoints = joinSize; 2292 *coveredPoints = join[i]; 2293 for (p = 0; p < numPoints; ++p) { 2294 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2295 } 2296 ierr = PetscFree(closures);CHKERRQ(ierr); 2297 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2298 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2299 PetscFunctionReturn(0); 2300 } 2301 2302 #undef __FUNCT__ 2303 #define __FUNCT__ "DMPlexGetMeet" 2304 /*@C 2305 DMPlexGetMeet - Get an array for the meet of the set of points 2306 2307 Not Collective 2308 2309 Input Parameters: 2310 + dm - The DMPlex object 2311 . numPoints - The number of input points for the meet 2312 - points - The input points 2313 2314 Output Parameters: 2315 + numCoveredPoints - The number of points in the meet 2316 - coveredPoints - The points in the meet 2317 2318 Level: intermediate 2319 2320 Note: Currently, this is restricted to a single level meet 2321 2322 .keywords: mesh 2323 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2324 @*/ 2325 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2326 { 2327 DM_Plex *mesh = (DM_Plex*) dm->data; 2328 PetscInt *meet[2]; 2329 PetscInt meetSize, i = 0; 2330 PetscInt dof, off, p, c, m; 2331 PetscErrorCode ierr; 2332 2333 PetscFunctionBegin; 2334 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2335 PetscValidPointer(points, 2); 2336 PetscValidPointer(numCoveringPoints, 3); 2337 PetscValidPointer(coveringPoints, 4); 2338 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2339 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2340 /* Copy in cone of first point */ 2341 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2342 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2343 for (meetSize = 0; meetSize < dof; ++meetSize) { 2344 meet[i][meetSize] = mesh->cones[off+meetSize]; 2345 } 2346 /* Check each successive cone */ 2347 for (p = 1; p < numPoints; ++p) { 2348 PetscInt newMeetSize = 0; 2349 2350 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2351 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2352 for (c = 0; c < dof; ++c) { 2353 const PetscInt point = mesh->cones[off+c]; 2354 2355 for (m = 0; m < meetSize; ++m) { 2356 if (point == meet[i][m]) { 2357 meet[1-i][newMeetSize++] = point; 2358 break; 2359 } 2360 } 2361 } 2362 meetSize = newMeetSize; 2363 i = 1-i; 2364 } 2365 *numCoveringPoints = meetSize; 2366 *coveringPoints = meet[i]; 2367 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2368 PetscFunctionReturn(0); 2369 } 2370 2371 #undef __FUNCT__ 2372 #define __FUNCT__ "DMPlexRestoreMeet" 2373 /*@C 2374 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2375 2376 Not Collective 2377 2378 Input Parameters: 2379 + dm - The DMPlex object 2380 . numPoints - The number of input points for the meet 2381 - points - The input points 2382 2383 Output Parameters: 2384 + numCoveredPoints - The number of points in the meet 2385 - coveredPoints - The points in the meet 2386 2387 Level: intermediate 2388 2389 .keywords: mesh 2390 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2391 @*/ 2392 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2393 { 2394 PetscErrorCode ierr; 2395 2396 PetscFunctionBegin; 2397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2398 PetscValidPointer(coveredPoints, 4); 2399 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2400 PetscFunctionReturn(0); 2401 } 2402 2403 #undef __FUNCT__ 2404 #define __FUNCT__ "DMPlexGetFullMeet" 2405 /*@C 2406 DMPlexGetFullMeet - Get an array for the meet of the set of points 2407 2408 Not Collective 2409 2410 Input Parameters: 2411 + dm - The DMPlex object 2412 . numPoints - The number of input points for the meet 2413 - points - The input points 2414 2415 Output Parameters: 2416 + numCoveredPoints - The number of points in the meet 2417 - coveredPoints - The points in the meet 2418 2419 Level: intermediate 2420 2421 .keywords: mesh 2422 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2423 @*/ 2424 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2425 { 2426 DM_Plex *mesh = (DM_Plex*) dm->data; 2427 PetscInt *offsets, **closures; 2428 PetscInt *meet[2]; 2429 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2430 PetscInt p, h, c, m; 2431 PetscErrorCode ierr; 2432 2433 PetscFunctionBegin; 2434 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2435 PetscValidPointer(points, 2); 2436 PetscValidPointer(numCoveredPoints, 3); 2437 PetscValidPointer(coveredPoints, 4); 2438 2439 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2440 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2441 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2442 maxSize = PetscPowInt(mesh->maxConeSize,height); 2443 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2444 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2445 2446 for (p = 0; p < numPoints; ++p) { 2447 PetscInt closureSize; 2448 2449 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2450 2451 offsets[p*(height+2)+0] = 0; 2452 for (h = 0; h < height+1; ++h) { 2453 PetscInt pStart, pEnd, i; 2454 2455 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2456 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2457 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2458 offsets[p*(height+2)+h+1] = i; 2459 break; 2460 } 2461 } 2462 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2463 } 2464 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); 2465 } 2466 for (h = 0; h < height+1; ++h) { 2467 PetscInt dof; 2468 2469 /* Copy in cone of first point */ 2470 dof = offsets[h+1] - offsets[h]; 2471 for (meetSize = 0; meetSize < dof; ++meetSize) { 2472 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2473 } 2474 /* Check each successive cone */ 2475 for (p = 1; p < numPoints && meetSize; ++p) { 2476 PetscInt newMeetSize = 0; 2477 2478 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2479 for (c = 0; c < dof; ++c) { 2480 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2481 2482 for (m = 0; m < meetSize; ++m) { 2483 if (point == meet[i][m]) { 2484 meet[1-i][newMeetSize++] = point; 2485 break; 2486 } 2487 } 2488 } 2489 meetSize = newMeetSize; 2490 i = 1-i; 2491 } 2492 if (meetSize) break; 2493 } 2494 *numCoveredPoints = meetSize; 2495 *coveredPoints = meet[i]; 2496 for (p = 0; p < numPoints; ++p) { 2497 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2498 } 2499 ierr = PetscFree(closures);CHKERRQ(ierr); 2500 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2501 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2502 PetscFunctionReturn(0); 2503 } 2504 2505 #undef __FUNCT__ 2506 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2507 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2508 { 2509 MPI_Comm comm; 2510 PetscInt cellDim; 2511 PetscErrorCode ierr; 2512 2513 PetscFunctionBegin; 2514 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2515 PetscValidPointer(numFaceVertices,3); 2516 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2517 switch (cellDim) { 2518 case 0: 2519 *numFaceVertices = 0; 2520 break; 2521 case 1: 2522 *numFaceVertices = 1; 2523 break; 2524 case 2: 2525 switch (numCorners) { 2526 case 3: /* triangle */ 2527 *numFaceVertices = 2; /* Edge has 2 vertices */ 2528 break; 2529 case 4: /* quadrilateral */ 2530 *numFaceVertices = 2; /* Edge has 2 vertices */ 2531 break; 2532 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2533 *numFaceVertices = 3; /* Edge has 3 vertices */ 2534 break; 2535 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2536 *numFaceVertices = 3; /* Edge has 3 vertices */ 2537 break; 2538 default: 2539 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2540 } 2541 break; 2542 case 3: 2543 switch (numCorners) { 2544 case 4: /* tetradehdron */ 2545 *numFaceVertices = 3; /* Face has 3 vertices */ 2546 break; 2547 case 6: /* tet cohesive cells */ 2548 *numFaceVertices = 4; /* Face has 4 vertices */ 2549 break; 2550 case 8: /* hexahedron */ 2551 *numFaceVertices = 4; /* Face has 4 vertices */ 2552 break; 2553 case 9: /* tet cohesive Lagrange cells */ 2554 *numFaceVertices = 6; /* Face has 6 vertices */ 2555 break; 2556 case 10: /* quadratic tetrahedron */ 2557 *numFaceVertices = 6; /* Face has 6 vertices */ 2558 break; 2559 case 12: /* hex cohesive Lagrange cells */ 2560 *numFaceVertices = 6; /* Face has 6 vertices */ 2561 break; 2562 case 18: /* quadratic tet cohesive Lagrange cells */ 2563 *numFaceVertices = 6; /* Face has 6 vertices */ 2564 break; 2565 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2566 *numFaceVertices = 9; /* Face has 9 vertices */ 2567 break; 2568 default: 2569 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2570 } 2571 break; 2572 default: 2573 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2574 } 2575 PetscFunctionReturn(0); 2576 } 2577 2578 #undef __FUNCT__ 2579 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2580 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2581 { 2582 const PetscInt maxFaceCases = 30; 2583 PetscInt numFaceCases = 0; 2584 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2585 PetscInt *off, *adj; 2586 PetscInt *neighborCells, *tmpClosure; 2587 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2588 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2589 PetscErrorCode ierr; 2590 2591 PetscFunctionBegin; 2592 /* For parallel partitioning, I think you have to communicate supports */ 2593 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2594 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2595 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2596 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2597 if (cEnd - cStart == 0) { 2598 if (numVertices) *numVertices = 0; 2599 if (offsets) *offsets = NULL; 2600 if (adjacency) *adjacency = NULL; 2601 PetscFunctionReturn(0); 2602 } 2603 numCells = cEnd - cStart; 2604 /* Setup face recognition */ 2605 if (depth == 1) { 2606 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 */ 2607 2608 for (c = cStart; c < cEnd; ++c) { 2609 PetscInt corners; 2610 2611 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2612 if (!cornersSeen[corners]) { 2613 PetscInt nFV; 2614 2615 if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2616 cornersSeen[corners] = 1; 2617 2618 ierr = DMPlexGetNumFaceVertices_Internal(dm, corners, &nFV);CHKERRQ(ierr); 2619 2620 numFaceVertices[numFaceCases++] = nFV; 2621 } 2622 } 2623 } 2624 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2625 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2626 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2627 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2628 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2629 /* Count neighboring cells */ 2630 for (cell = cStart; cell < cEnd; ++cell) { 2631 PetscInt numNeighbors = maxNeighbors, n; 2632 2633 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2634 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2635 for (n = 0; n < numNeighbors; ++n) { 2636 PetscInt cellPair[2]; 2637 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2638 PetscInt meetSize = 0; 2639 const PetscInt *meet = NULL; 2640 2641 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2642 if (cellPair[0] == cellPair[1]) continue; 2643 if (!found) { 2644 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2645 if (meetSize) { 2646 PetscInt f; 2647 2648 for (f = 0; f < numFaceCases; ++f) { 2649 if (numFaceVertices[f] == meetSize) { 2650 found = PETSC_TRUE; 2651 break; 2652 } 2653 } 2654 } 2655 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2656 } 2657 if (found) ++off[cell-cStart+1]; 2658 } 2659 } 2660 /* Prefix sum */ 2661 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2662 2663 if (adjacency) { 2664 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2665 /* Get neighboring cells */ 2666 for (cell = cStart; cell < cEnd; ++cell) { 2667 PetscInt numNeighbors = maxNeighbors, n; 2668 PetscInt cellOffset = 0; 2669 2670 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2671 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2672 for (n = 0; n < numNeighbors; ++n) { 2673 PetscInt cellPair[2]; 2674 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2675 PetscInt meetSize = 0; 2676 const PetscInt *meet = NULL; 2677 2678 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2679 if (cellPair[0] == cellPair[1]) continue; 2680 if (!found) { 2681 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2682 if (meetSize) { 2683 PetscInt f; 2684 2685 for (f = 0; f < numFaceCases; ++f) { 2686 if (numFaceVertices[f] == meetSize) { 2687 found = PETSC_TRUE; 2688 break; 2689 } 2690 } 2691 } 2692 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2693 } 2694 if (found) { 2695 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2696 ++cellOffset; 2697 } 2698 } 2699 } 2700 } 2701 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2702 if (numVertices) *numVertices = numCells; 2703 if (offsets) *offsets = off; 2704 if (adjacency) *adjacency = adj; 2705 PetscFunctionReturn(0); 2706 } 2707 2708 #if defined(PETSC_HAVE_CHACO) 2709 #if defined(PETSC_HAVE_UNISTD_H) 2710 #include <unistd.h> 2711 #endif 2712 /* Chaco does not have an include file */ 2713 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2714 float *ewgts, float *x, float *y, float *z, char *outassignname, 2715 char *outfilename, short *assignment, int architecture, int ndims_tot, 2716 int mesh_dims[3], double *goal, int global_method, int local_method, 2717 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2718 2719 extern int FREE_GRAPH; 2720 2721 #undef __FUNCT__ 2722 #define __FUNCT__ "DMPlexPartition_Chaco" 2723 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2724 { 2725 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2726 MPI_Comm comm; 2727 int nvtxs = numVertices; /* number of vertices in full graph */ 2728 int *vwgts = NULL; /* weights for all vertices */ 2729 float *ewgts = NULL; /* weights for all edges */ 2730 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2731 char *outassignname = NULL; /* name of assignment output file */ 2732 char *outfilename = NULL; /* output file name */ 2733 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2734 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2735 int mesh_dims[3]; /* dimensions of mesh of processors */ 2736 double *goal = NULL; /* desired set sizes for each set */ 2737 int global_method = 1; /* global partitioning algorithm */ 2738 int local_method = 1; /* local partitioning algorithm */ 2739 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2740 int vmax = 200; /* how many vertices to coarsen down to? */ 2741 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2742 double eigtol = 0.001; /* tolerance on eigenvectors */ 2743 long seed = 123636512; /* for random graph mutations */ 2744 short int *assignment; /* Output partition */ 2745 int fd_stdout, fd_pipe[2]; 2746 PetscInt *points; 2747 PetscMPIInt commSize; 2748 int i, v, p; 2749 PetscErrorCode ierr; 2750 2751 PetscFunctionBegin; 2752 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2753 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2754 if (!numVertices) { 2755 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2756 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2757 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2758 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2759 PetscFunctionReturn(0); 2760 } 2761 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2762 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2763 2764 if (global_method == INERTIAL_METHOD) { 2765 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2766 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2767 } 2768 mesh_dims[0] = commSize; 2769 mesh_dims[1] = 1; 2770 mesh_dims[2] = 1; 2771 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2772 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2773 /* TODO: check error codes for UNIX calls */ 2774 #if defined(PETSC_HAVE_UNISTD_H) 2775 { 2776 int piperet; 2777 piperet = pipe(fd_pipe); 2778 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2779 fd_stdout = dup(1); 2780 close(1); 2781 dup2(fd_pipe[1], 1); 2782 } 2783 #endif 2784 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2785 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2786 vmax, ndims, eigtol, seed); 2787 #if defined(PETSC_HAVE_UNISTD_H) 2788 { 2789 char msgLog[10000]; 2790 int count; 2791 2792 fflush(stdout); 2793 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2794 if (count < 0) count = 0; 2795 msgLog[count] = 0; 2796 close(1); 2797 dup2(fd_stdout, 1); 2798 close(fd_stdout); 2799 close(fd_pipe[0]); 2800 close(fd_pipe[1]); 2801 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2802 } 2803 #endif 2804 /* Convert to PetscSection+IS */ 2805 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2806 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2807 for (v = 0; v < nvtxs; ++v) { 2808 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2809 } 2810 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2811 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2812 for (p = 0, i = 0; p < commSize; ++p) { 2813 for (v = 0; v < nvtxs; ++v) { 2814 if (assignment[v] == p) points[i++] = v; 2815 } 2816 } 2817 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2818 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2819 if (global_method == INERTIAL_METHOD) { 2820 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2821 } 2822 ierr = PetscFree(assignment);CHKERRQ(ierr); 2823 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2824 PetscFunctionReturn(0); 2825 } 2826 #endif 2827 2828 #if defined(PETSC_HAVE_PARMETIS) 2829 #undef __FUNCT__ 2830 #define __FUNCT__ "DMPlexPartition_ParMetis" 2831 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2832 { 2833 PetscFunctionBegin; 2834 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ParMetis not yet supported"); 2835 PetscFunctionReturn(0); 2836 } 2837 #endif 2838 2839 #undef __FUNCT__ 2840 #define __FUNCT__ "DMPlexEnlargePartition" 2841 /* Expand the partition by BFS on the adjacency graph */ 2842 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2843 { 2844 PetscHashI h; 2845 const PetscInt *points; 2846 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2847 PetscInt pStart, pEnd, part, q; 2848 PetscErrorCode ierr; 2849 2850 PetscFunctionBegin; 2851 PetscHashICreate(h); 2852 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2853 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2854 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2855 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2856 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2857 for (part = pStart; part < pEnd; ++part) { 2858 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2859 2860 PetscHashIClear(h); 2861 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2862 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2863 /* Add all existing points to h */ 2864 for (p = 0; p < numPoints; ++p) { 2865 const PetscInt point = points[off+p]; 2866 PetscHashIAdd(h, point, 1); 2867 } 2868 PetscHashISize(h, nP); 2869 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2870 /* Add all points in next BFS level */ 2871 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2872 for (p = 0; p < numPoints; ++p) { 2873 const PetscInt point = points[off+p]; 2874 PetscInt s = start[point], e = start[point+1], a; 2875 2876 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2877 } 2878 PetscHashISize(h, numNewPoints); 2879 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2880 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2881 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2882 totPoints += numNewPoints; 2883 } 2884 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2885 PetscHashIDestroy(h); 2886 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2887 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2888 for (part = pStart, q = 0; part < pEnd; ++part) { 2889 PetscInt numPoints, p; 2890 2891 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2892 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2893 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2894 } 2895 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2896 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2897 PetscFunctionReturn(0); 2898 } 2899 2900 #undef __FUNCT__ 2901 #define __FUNCT__ "DMPlexCreatePartition" 2902 /* 2903 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2904 2905 Collective on DM 2906 2907 Input Parameters: 2908 + dm - The DM 2909 . height - The height for points in the partition 2910 - enlarge - Expand each partition with neighbors 2911 2912 Output Parameters: 2913 + partSection - The PetscSection giving the division of points by partition 2914 . partition - The list of points by partition 2915 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2916 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2917 2918 Level: developer 2919 2920 .seealso DMPlexDistribute() 2921 */ 2922 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2923 { 2924 PetscMPIInt size; 2925 PetscErrorCode ierr; 2926 2927 PetscFunctionBegin; 2928 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2929 2930 *origPartSection = NULL; 2931 *origPartition = NULL; 2932 if (size == 1) { 2933 PetscInt *points; 2934 PetscInt cStart, cEnd, c; 2935 2936 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2937 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2938 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2939 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2940 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2941 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2942 for (c = cStart; c < cEnd; ++c) points[c] = c; 2943 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2944 PetscFunctionReturn(0); 2945 } 2946 if (height == 0) { 2947 PetscInt numVertices; 2948 PetscInt *start = NULL; 2949 PetscInt *adjacency = NULL; 2950 2951 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2952 if (1) { 2953 #if defined(PETSC_HAVE_CHACO) 2954 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2955 #endif 2956 } else { 2957 #if defined(PETSC_HAVE_PARMETIS) 2958 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2959 #endif 2960 } 2961 if (enlarge) { 2962 *origPartSection = *partSection; 2963 *origPartition = *partition; 2964 2965 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2966 } 2967 ierr = PetscFree(start);CHKERRQ(ierr); 2968 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2969 # if 0 2970 } else if (height == 1) { 2971 /* Build the dual graph for faces and partition the hypergraph */ 2972 PetscInt numEdges; 2973 2974 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2975 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2976 destroyCSR(numEdges, start, adjacency); 2977 #endif 2978 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2979 PetscFunctionReturn(0); 2980 } 2981 2982 #undef __FUNCT__ 2983 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2984 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2985 { 2986 /* const PetscInt height = 0; */ 2987 const PetscInt *partArray; 2988 PetscInt *allPoints, *partPoints = NULL; 2989 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2990 PetscErrorCode ierr; 2991 2992 PetscFunctionBegin; 2993 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2994 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2995 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2996 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2997 for (rank = rStart; rank < rEnd; ++rank) { 2998 PetscInt partSize = 0; 2999 PetscInt numPoints, offset, p; 3000 3001 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3002 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3003 for (p = 0; p < numPoints; ++p) { 3004 PetscInt point = partArray[offset+p], closureSize, c; 3005 PetscInt *closure = NULL; 3006 3007 /* TODO Include support for height > 0 case */ 3008 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3009 /* Merge into existing points */ 3010 if (partSize+closureSize > maxPartSize) { 3011 PetscInt *tmpPoints; 3012 3013 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 3014 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 3015 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3016 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3017 3018 partPoints = tmpPoints; 3019 } 3020 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3021 partSize += closureSize; 3022 3023 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3024 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3025 } 3026 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3027 } 3028 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3029 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3030 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3031 3032 for (rank = rStart; rank < rEnd; ++rank) { 3033 PetscInt partSize = 0, newOffset; 3034 PetscInt numPoints, offset, p; 3035 3036 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3037 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3038 for (p = 0; p < numPoints; ++p) { 3039 PetscInt point = partArray[offset+p], closureSize, c; 3040 PetscInt *closure = NULL; 3041 3042 /* TODO Include support for height > 0 case */ 3043 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3044 /* Merge into existing points */ 3045 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3046 partSize += closureSize; 3047 3048 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3049 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3050 } 3051 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3052 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3053 } 3054 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3055 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3056 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3057 PetscFunctionReturn(0); 3058 } 3059 3060 #undef __FUNCT__ 3061 #define __FUNCT__ "DMPlexDistributeField" 3062 /* 3063 Input Parameters: 3064 . originalSection 3065 , originalVec 3066 3067 Output Parameters: 3068 . newSection 3069 . newVec 3070 */ 3071 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3072 { 3073 PetscSF fieldSF; 3074 PetscInt *remoteOffsets, fieldSize; 3075 PetscScalar *originalValues, *newValues; 3076 PetscErrorCode ierr; 3077 3078 PetscFunctionBegin; 3079 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3080 3081 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3082 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3083 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3084 3085 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3086 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3087 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3088 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3089 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3090 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3091 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3092 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3093 PetscFunctionReturn(0); 3094 } 3095 3096 #undef __FUNCT__ 3097 #define __FUNCT__ "DMPlexDistribute" 3098 /*@C 3099 DMPlexDistribute - Distributes the mesh and any associated sections. 3100 3101 Not Collective 3102 3103 Input Parameter: 3104 + dm - The original DMPlex object 3105 . partitioner - The partitioning package, or NULL for the default 3106 - overlap - The overlap of partitions, 0 is the default 3107 3108 Output Parameter: 3109 . parallelMesh - The distributed DMPlex object, or NULL 3110 3111 Note: If the mesh was not distributed, the return value is NULL 3112 3113 Level: intermediate 3114 3115 .keywords: mesh, elements 3116 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3117 @*/ 3118 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3119 { 3120 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3121 MPI_Comm comm; 3122 const PetscInt height = 0; 3123 PetscInt dim, numRemoteRanks; 3124 IS origCellPart, cellPart, part; 3125 PetscSection origCellPartSection, cellPartSection, partSection; 3126 PetscSFNode *remoteRanks; 3127 PetscSF partSF, pointSF, coneSF; 3128 ISLocalToGlobalMapping renumbering; 3129 PetscSection originalConeSection, newConeSection; 3130 PetscInt *remoteOffsets; 3131 PetscInt *cones, *newCones, newConesSize; 3132 PetscBool flg; 3133 PetscMPIInt rank, numProcs, p; 3134 PetscErrorCode ierr; 3135 3136 PetscFunctionBegin; 3137 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3138 PetscValidPointer(dmParallel,4); 3139 3140 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3141 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3142 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3143 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3144 3145 *dmParallel = NULL; 3146 if (numProcs == 1) PetscFunctionReturn(0); 3147 3148 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3149 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3150 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3151 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3152 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3153 if (!rank) numRemoteRanks = numProcs; 3154 else numRemoteRanks = 0; 3155 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3156 for (p = 0; p < numRemoteRanks; ++p) { 3157 remoteRanks[p].rank = p; 3158 remoteRanks[p].index = 0; 3159 } 3160 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3161 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3162 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3163 if (flg) { 3164 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3165 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3166 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3167 if (origCellPart) { 3168 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3169 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3170 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3171 } 3172 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3173 } 3174 /* Close the partition over the mesh */ 3175 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3176 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3177 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3178 /* Create new mesh */ 3179 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3180 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3181 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3182 pmesh = (DM_Plex*) (*dmParallel)->data; 3183 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3184 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3185 if (flg) { 3186 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3187 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3188 ierr = ISView(part, NULL);CHKERRQ(ierr); 3189 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3190 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3191 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3192 } 3193 /* Distribute cone section */ 3194 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3195 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3196 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3197 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3198 { 3199 PetscInt pStart, pEnd, p; 3200 3201 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3202 for (p = pStart; p < pEnd; ++p) { 3203 PetscInt coneSize; 3204 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3205 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3206 } 3207 } 3208 /* Communicate and renumber cones */ 3209 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3210 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3211 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3212 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3213 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3214 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3215 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3216 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3217 if (flg) { 3218 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3219 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3220 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3221 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3222 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3223 } 3224 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3225 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3226 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3227 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3228 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3229 /* Create supports and stratify sieve */ 3230 { 3231 PetscInt pStart, pEnd; 3232 3233 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3234 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3235 } 3236 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3237 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3238 /* Distribute Coordinates */ 3239 { 3240 PetscSection originalCoordSection, newCoordSection; 3241 Vec originalCoordinates, newCoordinates; 3242 const char *name; 3243 3244 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3245 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3246 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3247 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3248 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3249 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3250 3251 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3252 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3253 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3254 } 3255 /* Distribute labels */ 3256 { 3257 DMLabel next = mesh->labels, newNext = pmesh->labels; 3258 PetscInt numLabels = 0, l; 3259 3260 /* Bcast number of labels */ 3261 while (next) { 3262 ++numLabels; next = next->next; 3263 } 3264 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3265 next = mesh->labels; 3266 for (l = 0; l < numLabels; ++l) { 3267 DMLabel newLabel; 3268 const PetscInt *partArray; 3269 char *name; 3270 PetscInt *stratumSizes = NULL, *points = NULL; 3271 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3272 PetscInt nameSize, s, p; 3273 PetscBool isdepth; 3274 size_t len = 0; 3275 3276 /* Bcast name (could filter for no points) */ 3277 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3278 nameSize = len; 3279 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3280 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3281 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3282 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3283 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3284 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3285 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3286 newLabel->name = name; 3287 /* Bcast numStrata (could filter for no points in stratum) */ 3288 if (!rank) newLabel->numStrata = next->numStrata; 3289 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3290 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3291 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3292 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3293 /* Bcast stratumValues (could filter for no points in stratum) */ 3294 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3295 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3296 /* Find size on each process and Scatter */ 3297 if (!rank) { 3298 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3299 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3300 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3301 for (s = 0; s < next->numStrata; ++s) { 3302 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3303 const PetscInt point = next->points[p]; 3304 PetscInt proc; 3305 3306 for (proc = 0; proc < numProcs; ++proc) { 3307 PetscInt dof, off, pPart; 3308 3309 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3310 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3311 for (pPart = off; pPart < off+dof; ++pPart) { 3312 if (partArray[pPart] == point) { 3313 ++stratumSizes[proc*next->numStrata+s]; 3314 break; 3315 } 3316 } 3317 } 3318 } 3319 } 3320 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3321 } 3322 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3323 /* Calculate stratumOffsets */ 3324 newLabel->stratumOffsets[0] = 0; 3325 for (s = 0; s < newLabel->numStrata; ++s) { 3326 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3327 } 3328 /* Pack points and Scatter */ 3329 if (!rank) { 3330 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3331 displs[0] = 0; 3332 for (p = 0; p < numProcs; ++p) { 3333 sendcnts[p] = 0; 3334 for (s = 0; s < next->numStrata; ++s) { 3335 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3336 } 3337 offsets[p] = displs[p]; 3338 displs[p+1] = displs[p] + sendcnts[p]; 3339 } 3340 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3341 for (s = 0; s < next->numStrata; ++s) { 3342 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3343 const PetscInt point = next->points[p]; 3344 PetscInt proc; 3345 3346 for (proc = 0; proc < numProcs; ++proc) { 3347 PetscInt dof, off, pPart; 3348 3349 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3350 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3351 for (pPart = off; pPart < off+dof; ++pPart) { 3352 if (partArray[pPart] == point) { 3353 points[offsets[proc]++] = point; 3354 break; 3355 } 3356 } 3357 } 3358 } 3359 } 3360 } 3361 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3362 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3363 ierr = PetscFree(points);CHKERRQ(ierr); 3364 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3365 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3366 /* Renumber points */ 3367 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3368 /* Sort points */ 3369 for (s = 0; s < newLabel->numStrata; ++s) { 3370 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3371 } 3372 /* Insert into list */ 3373 if (newNext) newNext->next = newLabel; 3374 else pmesh->labels = newLabel; 3375 newNext = newLabel; 3376 if (!rank) next = next->next; 3377 } 3378 } 3379 /* Cleanup Partition */ 3380 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3381 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3382 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3383 ierr = ISDestroy(&part);CHKERRQ(ierr); 3384 /* Create point SF for parallel mesh */ 3385 { 3386 const PetscInt *leaves; 3387 PetscSFNode *remotePoints, *rowners, *lowners; 3388 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3389 PetscInt pStart, pEnd; 3390 3391 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3392 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3393 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3394 for (p=0; p<numRoots; p++) { 3395 rowners[p].rank = -1; 3396 rowners[p].index = -1; 3397 } 3398 if (origCellPart) { 3399 /* Make sure cells in the original partition are not assigned to other procs */ 3400 const PetscInt *origCells; 3401 3402 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3403 for (p = 0; p < numProcs; ++p) { 3404 PetscInt dof, off, d; 3405 3406 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3407 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3408 for (d = off; d < off+dof; ++d) { 3409 rowners[origCells[d]].rank = p; 3410 } 3411 } 3412 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3413 } 3414 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3415 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3416 3417 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3418 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3419 for (p = 0; p < numLeaves; ++p) { 3420 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3421 lowners[p].rank = rank; 3422 lowners[p].index = leaves ? leaves[p] : p; 3423 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3424 lowners[p].rank = -2; 3425 lowners[p].index = -2; 3426 } 3427 } 3428 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3429 rowners[p].rank = -3; 3430 rowners[p].index = -3; 3431 } 3432 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3433 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3434 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3435 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3436 for (p = 0; p < numLeaves; ++p) { 3437 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3438 if (lowners[p].rank != rank) ++numGhostPoints; 3439 } 3440 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3441 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3442 for (p = 0, gp = 0; p < numLeaves; ++p) { 3443 if (lowners[p].rank != rank) { 3444 ghostPoints[gp] = leaves ? leaves[p] : p; 3445 remotePoints[gp].rank = lowners[p].rank; 3446 remotePoints[gp].index = lowners[p].index; 3447 ++gp; 3448 } 3449 } 3450 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3451 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3452 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3453 } 3454 /* Cleanup */ 3455 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3456 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3457 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3458 PetscFunctionReturn(0); 3459 } 3460 3461 #undef __FUNCT__ 3462 #define __FUNCT__ "DMPlexRenumber_Private" 3463 /* 3464 Reasons to renumber: 3465 3466 1) Permute points, e.g. bandwidth reduction (Renumber) 3467 3468 a) Must not mix strata 3469 3470 2) Shift numbers for point insertion (Shift) 3471 3472 a) Want operation brken into parts so that insertion can be interleaved 3473 3474 renumbering - An IS which provides the new numbering 3475 */ 3476 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3477 { 3478 PetscFunctionBegin; 3479 PetscFunctionReturn(0); 3480 } 3481 3482 #undef __FUNCT__ 3483 #define __FUNCT__ "DMPlexShiftPoint_Private" 3484 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3485 { 3486 if (depth < 0) return p; 3487 /* Cells */ if (p < depthEnd[depth]) return p; 3488 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3489 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3490 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3491 } 3492 3493 #undef __FUNCT__ 3494 #define __FUNCT__ "DMPlexShiftSizes_Private" 3495 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3496 { 3497 PetscInt *depthEnd; 3498 PetscInt depth = 0, d, pStart, pEnd, p; 3499 PetscErrorCode ierr; 3500 3501 PetscFunctionBegin; 3502 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3503 if (depth < 0) PetscFunctionReturn(0); 3504 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3505 /* Step 1: Expand chart */ 3506 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3507 for (d = 0; d <= depth; ++d) { 3508 pEnd += depthShift[d]; 3509 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3510 } 3511 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3512 /* Step 2: Set cone and support sizes */ 3513 for (d = 0; d <= depth; ++d) { 3514 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3515 for (p = pStart; p < pEnd; ++p) { 3516 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3517 PetscInt size; 3518 3519 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3520 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3521 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3522 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3523 } 3524 } 3525 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3526 PetscFunctionReturn(0); 3527 } 3528 3529 #undef __FUNCT__ 3530 #define __FUNCT__ "DMPlexShiftPoints_Private" 3531 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3532 { 3533 PetscInt *depthEnd, *newpoints; 3534 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3535 PetscErrorCode ierr; 3536 3537 PetscFunctionBegin; 3538 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3539 if (depth < 0) PetscFunctionReturn(0); 3540 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3541 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3542 for (d = 0; d <= depth; ++d) { 3543 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3544 } 3545 /* Step 5: Set cones and supports */ 3546 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3547 for (p = pStart; p < pEnd; ++p) { 3548 const PetscInt *points = NULL, *orientations = NULL; 3549 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3550 3551 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3552 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3553 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3554 for (i = 0; i < size; ++i) { 3555 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3556 } 3557 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3558 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3559 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3560 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3561 for (i = 0; i < size; ++i) { 3562 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3563 } 3564 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3565 } 3566 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3567 PetscFunctionReturn(0); 3568 } 3569 3570 #undef __FUNCT__ 3571 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3572 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3573 { 3574 PetscSection coordSection, newCoordSection; 3575 Vec coordinates, newCoordinates; 3576 PetscScalar *coords, *newCoords; 3577 PetscInt *depthEnd, coordSize; 3578 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3579 PetscErrorCode ierr; 3580 3581 PetscFunctionBegin; 3582 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3583 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3584 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3585 for (d = 0; d <= depth; ++d) { 3586 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3587 } 3588 /* Step 8: Convert coordinates */ 3589 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3590 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3591 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3592 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);CHKERRQ(ierr); 3593 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3594 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3595 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3596 for (v = vStartNew; v < vEndNew; ++v) { 3597 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3598 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3599 } 3600 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3601 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3602 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3603 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &newCoordinates);CHKERRQ(ierr); 3604 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3605 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3606 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3607 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3608 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3609 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3610 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3611 for (v = vStart; v < vEnd; ++v) { 3612 PetscInt dof, off, noff, d; 3613 3614 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3615 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3616 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3617 for (d = 0; d < dof; ++d) { 3618 newCoords[noff+d] = coords[off+d]; 3619 } 3620 } 3621 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3622 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3623 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3624 ierr = PetscSectionDestroy(&newCoordSection);CHKERRQ(ierr); 3625 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3626 PetscFunctionReturn(0); 3627 } 3628 3629 #undef __FUNCT__ 3630 #define __FUNCT__ "DMPlexShiftSF_Private" 3631 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3632 { 3633 PetscInt *depthEnd; 3634 PetscInt depth = 0, d; 3635 PetscSF sfPoint, sfPointNew; 3636 const PetscSFNode *remotePoints; 3637 PetscSFNode *gremotePoints; 3638 const PetscInt *localPoints; 3639 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3640 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3641 PetscMPIInt numProcs; 3642 PetscErrorCode ierr; 3643 3644 PetscFunctionBegin; 3645 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3646 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3647 for (d = 0; d <= depth; ++d) { 3648 totShift += depthShift[d]; 3649 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3650 } 3651 /* Step 9: Convert pointSF */ 3652 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 3653 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3654 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3655 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3656 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3657 if (numRoots >= 0) { 3658 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3659 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3660 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3661 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3662 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3663 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3664 for (l = 0; l < numLeaves; ++l) { 3665 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3666 gremotePoints[l].rank = remotePoints[l].rank; 3667 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3668 } 3669 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3670 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3671 } 3672 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3673 PetscFunctionReturn(0); 3674 } 3675 3676 #undef __FUNCT__ 3677 #define __FUNCT__ "DMPlexShiftLabels_Private" 3678 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3679 { 3680 PetscSF sfPoint; 3681 DMLabel vtkLabel, ghostLabel; 3682 PetscInt *depthEnd; 3683 const PetscSFNode *leafRemote; 3684 const PetscInt *leafLocal; 3685 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3686 PetscMPIInt rank; 3687 PetscErrorCode ierr; 3688 3689 PetscFunctionBegin; 3690 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3691 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3692 for (d = 0; d <= depth; ++d) { 3693 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3694 } 3695 /* Step 10: Convert labels */ 3696 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3697 for (l = 0; l < numLabels; ++l) { 3698 DMLabel label, newlabel; 3699 const char *lname; 3700 PetscBool isDepth; 3701 IS valueIS; 3702 const PetscInt *values; 3703 PetscInt numValues, val; 3704 3705 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3706 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3707 if (isDepth) continue; 3708 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3709 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3710 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3711 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3712 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3713 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3714 for (val = 0; val < numValues; ++val) { 3715 IS pointIS; 3716 const PetscInt *points; 3717 PetscInt numPoints, p; 3718 3719 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3720 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3721 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3722 for (p = 0; p < numPoints; ++p) { 3723 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3724 3725 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3726 } 3727 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3728 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3729 } 3730 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3731 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3732 } 3733 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3734 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3735 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 3736 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3737 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3738 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3739 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3740 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3741 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3742 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3743 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3744 for (; c < leafLocal[l] && c < cEnd; ++c) { 3745 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3746 } 3747 if (leafLocal[l] >= cEnd) break; 3748 if (leafRemote[l].rank == rank) { 3749 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3750 } else { 3751 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3752 } 3753 } 3754 for (; c < cEnd; ++c) { 3755 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3756 } 3757 if (0) { 3758 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3759 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3760 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3761 } 3762 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3763 for (f = fStart; f < fEnd; ++f) { 3764 PetscInt numCells; 3765 3766 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3767 if (numCells < 2) { 3768 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3769 } else { 3770 const PetscInt *cells = NULL; 3771 PetscInt vA, vB; 3772 3773 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3774 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3775 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3776 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3777 } 3778 } 3779 if (0) { 3780 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3781 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3782 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3783 } 3784 PetscFunctionReturn(0); 3785 } 3786 3787 #undef __FUNCT__ 3788 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3789 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3790 { 3791 DMLabel label; 3792 IS valueIS; 3793 const PetscInt *values; 3794 PetscInt *depthShift; 3795 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3796 PetscErrorCode ierr; 3797 3798 PetscFunctionBegin; 3799 /* Count ghost cells */ 3800 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3801 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3802 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3803 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3804 3805 *numGhostCells = 0; 3806 for (fs = 0; fs < numFS; ++fs) { 3807 PetscInt numBdFaces; 3808 3809 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3810 3811 *numGhostCells += numBdFaces; 3812 } 3813 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3814 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3815 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3816 if (depth >= 0) depthShift[depth] = *numGhostCells; 3817 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3818 /* Step 3: Set cone/support sizes for new points */ 3819 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3820 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3821 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3822 } 3823 for (fs = 0; fs < numFS; ++fs) { 3824 IS faceIS; 3825 const PetscInt *faces; 3826 PetscInt numFaces, f; 3827 3828 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3829 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3830 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3831 for (f = 0; f < numFaces; ++f) { 3832 PetscInt size; 3833 3834 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3835 if (size != 1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3836 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3837 } 3838 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3839 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3840 } 3841 /* Step 4: Setup ghosted DM */ 3842 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3843 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3844 /* Step 6: Set cones and supports for new points */ 3845 ghostCell = cEnd; 3846 for (fs = 0; fs < numFS; ++fs) { 3847 IS faceIS; 3848 const PetscInt *faces; 3849 PetscInt numFaces, f; 3850 3851 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3852 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3853 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3854 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3855 PetscInt newFace = faces[f] + *numGhostCells; 3856 3857 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3858 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3859 } 3860 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3861 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3862 } 3863 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3864 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3865 /* Step 7: Stratify */ 3866 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3867 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3868 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3869 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3870 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3871 PetscFunctionReturn(0); 3872 } 3873 3874 #undef __FUNCT__ 3875 #define __FUNCT__ "DMPlexConstructGhostCells" 3876 /*@C 3877 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3878 3879 Collective on dm 3880 3881 Input Parameters: 3882 + dm - The original DM 3883 - labelName - The label specifying the boundary faces (this could be auto-generated) 3884 3885 Output Parameters: 3886 + numGhostCells - The number of ghost cells added to the DM 3887 - dmGhosted - The new DM 3888 3889 Level: developer 3890 3891 .seealso: DMCreate() 3892 */ 3893 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3894 { 3895 DM gdm; 3896 PetscInt dim; 3897 PetscErrorCode ierr; 3898 3899 PetscFunctionBegin; 3900 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3901 PetscValidPointer(numGhostCells, 3); 3902 PetscValidPointer(dmGhosted, 4); 3903 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &gdm);CHKERRQ(ierr); 3904 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3905 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3906 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3907 switch (dim) { 3908 case 2: 3909 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3910 break; 3911 default: 3912 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3913 } 3914 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3915 *dmGhosted = gdm; 3916 PetscFunctionReturn(0); 3917 } 3918 3919 #undef __FUNCT__ 3920 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3921 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3922 { 3923 MPI_Comm comm; 3924 IS valueIS, *pointIS; 3925 const PetscInt *values, **splitPoints; 3926 PetscSection coordSection; 3927 Vec coordinates; 3928 PetscScalar *coords; 3929 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3930 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3931 PetscErrorCode ierr; 3932 3933 PetscFunctionBegin; 3934 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3935 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3936 /* Count split points and add cohesive cells */ 3937 if (label) { 3938 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3939 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3940 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3941 } 3942 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3943 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3944 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3945 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3946 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3947 for (d = 0; d <= depth; ++d) { 3948 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3949 numSplitPoints[d] = 0; 3950 splitPoints[d] = NULL; 3951 pointIS[d] = NULL; 3952 } 3953 for (sp = 0; sp < numSP; ++sp) { 3954 const PetscInt dep = values[sp]; 3955 3956 if ((dep < 0) || (dep > depth)) continue; 3957 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3958 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3959 if (pointIS[dep]) { 3960 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3961 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3962 } 3963 } 3964 if (depth >= 0) { 3965 /* Calculate number of additional points */ 3966 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3967 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3968 /* Calculate hybrid bound for each dimension */ 3969 pMaxNew[0] += depthShift[depth]; 3970 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3971 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3972 3973 /* Calculate point offset for each dimension */ 3974 depthOffset[depth] = 0; 3975 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3976 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3977 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3978 } 3979 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3980 /* Step 3: Set cone/support sizes for new points */ 3981 for (dep = 0; dep <= depth; ++dep) { 3982 for (p = 0; p < numSplitPoints[dep]; ++p) { 3983 const PetscInt oldp = splitPoints[dep][p]; 3984 const PetscInt newp = depthOffset[dep] + oldp; 3985 const PetscInt splitp = pMaxNew[dep] + p; 3986 const PetscInt *support; 3987 PetscInt coneSize, supportSize, q, e; 3988 3989 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3990 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3991 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3992 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3993 if (dep == depth-1) { 3994 const PetscInt ccell = pMaxNew[depth] + p; 3995 /* Add cohesive cells, they are prisms */ 3996 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3997 } else if (dep == 0) { 3998 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3999 4000 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4001 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4002 for (e = 0, q = 0; e < supportSize; ++e) { 4003 PetscInt val; 4004 4005 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4006 if ((val == 1) || (val == (shift + 1))) ++q; 4007 } 4008 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 4009 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4010 for (e = 0, q = 0; e < supportSize; ++e) { 4011 PetscInt val; 4012 4013 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4014 if ((val == 1) || (val == -(shift + 1))) ++q; 4015 } 4016 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 4017 /* Add cohesive edges */ 4018 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 4019 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4020 } else if (dep == dim-2) { 4021 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4022 /* Split old edge: Faces in positive side cells and old split faces */ 4023 for (e = 0, q = 0; e < supportSize; ++e) { 4024 PetscInt val; 4025 4026 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4027 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4028 } 4029 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4030 /* Split new edge: Faces in negative side cells and new split faces */ 4031 for (e = 0, q = 0; e < supportSize; ++e) { 4032 PetscInt val; 4033 4034 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4035 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4036 } 4037 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4038 } 4039 } 4040 } 4041 /* Step 4: Setup split DM */ 4042 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4043 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4044 /* Step 6: Set cones and supports for new points */ 4045 for (dep = 0; dep <= depth; ++dep) { 4046 for (p = 0; p < numSplitPoints[dep]; ++p) { 4047 const PetscInt oldp = splitPoints[dep][p]; 4048 const PetscInt newp = depthOffset[dep] + oldp; 4049 const PetscInt splitp = pMaxNew[dep] + p; 4050 const PetscInt *cone, *support, *ornt; 4051 PetscInt coneSize, supportSize, q, v, e, s; 4052 4053 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4054 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4055 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4056 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4057 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4058 if (dep == depth-1) { 4059 const PetscInt ccell = pMaxNew[depth] + p; 4060 const PetscInt *supportF; 4061 4062 /* Split face: copy in old face to new face to start */ 4063 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4064 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4065 /* Split old face: old vertices/edges in cone so no change */ 4066 /* Split new face: new vertices/edges in cone */ 4067 for (q = 0; q < coneSize; ++q) { 4068 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4069 4070 coneNew[2+q] = pMaxNew[dim-2] + v; 4071 } 4072 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4073 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4074 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4075 coneNew[0] = newp; 4076 coneNew[1] = splitp; 4077 for (q = 0; q < coneSize; ++q) { 4078 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4079 } 4080 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4081 4082 4083 for (s = 0; s < supportSize; ++s) { 4084 PetscInt val; 4085 4086 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4087 if (val < 0) { 4088 /* Split old face: Replace negative side cell with cohesive cell */ 4089 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4090 } else { 4091 /* Split new face: Replace positive side cell with cohesive cell */ 4092 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4093 } 4094 } 4095 } else if (dep == 0) { 4096 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4097 4098 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4099 for (e = 0, q = 0; e < supportSize; ++e) { 4100 PetscInt val; 4101 4102 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4103 if ((val == 1) || (val == (shift + 1))) { 4104 supportNew[q++] = depthOffset[1] + support[e]; 4105 } 4106 } 4107 supportNew[q] = cedge; 4108 4109 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4110 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4111 for (e = 0, q = 0; e < supportSize; ++e) { 4112 PetscInt val, edge; 4113 4114 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4115 if (val == 1) { 4116 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4117 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4118 supportNew[q++] = pMaxNew[1] + edge; 4119 } else if (val == -(shift + 1)) { 4120 supportNew[q++] = depthOffset[1] + support[e]; 4121 } 4122 } 4123 supportNew[q] = cedge; 4124 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4125 /* Cohesive edge: Old and new split vertex, punting on support */ 4126 coneNew[0] = newp; 4127 coneNew[1] = splitp; 4128 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4129 } else if (dep == dim-2) { 4130 /* Split old edge: old vertices in cone so no change */ 4131 /* Split new edge: new vertices in cone */ 4132 for (q = 0; q < coneSize; ++q) { 4133 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4134 4135 coneNew[q] = pMaxNew[dim-3] + v; 4136 } 4137 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4138 /* Split old edge: Faces in positive side cells and old split faces */ 4139 for (e = 0, q = 0; e < supportSize; ++e) { 4140 PetscInt val; 4141 4142 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4143 if ((val == dim-1) || (val == (shift + dim-1))) { 4144 supportNew[q++] = depthOffset[dim-1] + support[e]; 4145 } 4146 } 4147 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4148 /* Split new edge: Faces in negative side cells and new split faces */ 4149 for (e = 0, q = 0; e < supportSize; ++e) { 4150 PetscInt val, face; 4151 4152 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4153 if (val == dim-1) { 4154 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4155 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4156 supportNew[q++] = pMaxNew[dim-1] + face; 4157 } else if (val == -(shift + dim-1)) { 4158 supportNew[q++] = depthOffset[dim-1] + support[e]; 4159 } 4160 } 4161 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4162 } 4163 } 4164 } 4165 /* Step 6b: Replace split points in negative side cones */ 4166 for (sp = 0; sp < numSP; ++sp) { 4167 PetscInt dep = values[sp]; 4168 IS pIS; 4169 PetscInt numPoints; 4170 const PetscInt *points; 4171 4172 if (dep >= 0) continue; 4173 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4174 if (!pIS) continue; 4175 dep = -dep - shift; 4176 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4177 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4178 for (p = 0; p < numPoints; ++p) { 4179 const PetscInt oldp = points[p]; 4180 const PetscInt newp = depthOffset[dep] + oldp; 4181 const PetscInt *cone; 4182 PetscInt coneSize, c; 4183 PetscBool replaced = PETSC_FALSE; 4184 4185 /* Negative edge: replace split vertex */ 4186 /* Negative cell: replace split face */ 4187 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4188 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4189 for (c = 0; c < coneSize; ++c) { 4190 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4191 PetscInt csplitp, cp, val; 4192 4193 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4194 if (val == dep-1) { 4195 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4196 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4197 csplitp = pMaxNew[dep-1] + cp; 4198 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4199 replaced = PETSC_TRUE; 4200 } 4201 } 4202 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4203 } 4204 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4205 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4206 } 4207 /* Step 7: Stratify */ 4208 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4209 /* Step 8: Coordinates */ 4210 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4211 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4212 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4213 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4214 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4215 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4216 const PetscInt splitp = pMaxNew[0] + v; 4217 PetscInt dof, off, soff, d; 4218 4219 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4220 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4221 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4222 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4223 } 4224 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4225 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4226 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4227 /* Step 10: Labels */ 4228 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4229 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4230 for (dep = 0; dep <= depth; ++dep) { 4231 for (p = 0; p < numSplitPoints[dep]; ++p) { 4232 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4233 const PetscInt splitp = pMaxNew[dep] + p; 4234 PetscInt l; 4235 4236 for (l = 0; l < numLabels; ++l) { 4237 DMLabel mlabel; 4238 const char *lname; 4239 PetscInt val; 4240 4241 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4242 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4243 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4244 if (val >= 0) { 4245 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4246 if (dep == 0) { 4247 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4248 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4249 } 4250 } 4251 } 4252 } 4253 } 4254 for (sp = 0; sp < numSP; ++sp) { 4255 const PetscInt dep = values[sp]; 4256 4257 if ((dep < 0) || (dep > depth)) continue; 4258 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4259 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4260 } 4261 if (label) { 4262 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4263 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4264 } 4265 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4266 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4267 PetscFunctionReturn(0); 4268 } 4269 4270 #undef __FUNCT__ 4271 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4272 /*@C 4273 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4274 4275 Collective on dm 4276 4277 Input Parameters: 4278 + dm - The original DM 4279 - labelName - The label specifying the boundary faces (this could be auto-generated) 4280 4281 Output Parameters: 4282 - dmSplit - The new DM 4283 4284 Level: developer 4285 4286 .seealso: DMCreate() 4287 */ 4288 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4289 { 4290 DM sdm; 4291 PetscInt dim; 4292 PetscErrorCode ierr; 4293 4294 PetscFunctionBegin; 4295 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4296 PetscValidPointer(dmSplit, 4); 4297 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 4298 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4299 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4300 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4301 switch (dim) { 4302 case 2: 4303 case 3: 4304 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4305 break; 4306 default: 4307 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4308 } 4309 *dmSplit = sdm; 4310 PetscFunctionReturn(0); 4311 } 4312 4313 #undef __FUNCT__ 4314 #define __FUNCT__ "DMLabelCohesiveComplete" 4315 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4316 { 4317 IS dimIS; 4318 const PetscInt *points; 4319 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4320 PetscErrorCode ierr; 4321 4322 PetscFunctionBegin; 4323 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4324 /* Cell orientation for face gives the side of the fault */ 4325 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4326 if (!dimIS) PetscFunctionReturn(0); 4327 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4328 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4329 for (p = 0; p < numPoints; ++p) { 4330 const PetscInt *support; 4331 PetscInt supportSize, s; 4332 4333 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4334 if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4335 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4336 for (s = 0; s < supportSize; ++s) { 4337 const PetscInt *cone, *ornt; 4338 PetscInt coneSize, c; 4339 PetscBool pos = PETSC_TRUE; 4340 4341 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4342 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4343 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4344 for (c = 0; c < coneSize; ++c) { 4345 if (cone[c] == points[p]) { 4346 if (ornt[c] >= 0) { 4347 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4348 } else { 4349 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4350 pos = PETSC_FALSE; 4351 } 4352 break; 4353 } 4354 } 4355 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]); 4356 /* Put faces touching the fault in the label */ 4357 for (c = 0; c < coneSize; ++c) { 4358 const PetscInt point = cone[c]; 4359 4360 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4361 if (val == -1) { 4362 PetscInt *closure = NULL; 4363 PetscInt closureSize, cl; 4364 4365 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4366 for (cl = 0; cl < closureSize*2; cl += 2) { 4367 const PetscInt clp = closure[cl]; 4368 4369 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4370 if ((val >= 0) && (val < dim-1)) { 4371 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4372 break; 4373 } 4374 } 4375 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4376 } 4377 } 4378 } 4379 } 4380 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4381 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4382 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4383 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4384 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4385 if (!dimIS) PetscFunctionReturn(0); 4386 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4387 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4388 for (p = 0; p < numPoints; ++p) { 4389 PetscInt *star = NULL; 4390 PetscInt starSize, s; 4391 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4392 4393 /* First mark cells connected to the fault */ 4394 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4395 while (again) { 4396 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4397 again = 0; 4398 for (s = 0; s < starSize*2; s += 2) { 4399 const PetscInt point = star[s]; 4400 const PetscInt *cone; 4401 PetscInt coneSize, c; 4402 4403 if ((point < cStart) || (point >= cEnd)) continue; 4404 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4405 if (val != -1) continue; 4406 again = 2; 4407 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4408 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4409 for (c = 0; c < coneSize; ++c) { 4410 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4411 if (val != -1) { 4412 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); 4413 if (val > 0) { 4414 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4415 } else { 4416 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4417 } 4418 again = 1; 4419 break; 4420 } 4421 } 4422 } 4423 } 4424 /* Classify the rest by cell membership */ 4425 for (s = 0; s < starSize*2; s += 2) { 4426 const PetscInt point = star[s]; 4427 4428 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4429 if (val == -1) { 4430 PetscInt *sstar = NULL; 4431 PetscInt sstarSize, ss; 4432 PetscBool marked = PETSC_FALSE; 4433 4434 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4435 for (ss = 0; ss < sstarSize*2; ss += 2) { 4436 const PetscInt spoint = sstar[ss]; 4437 4438 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4439 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4440 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4441 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4442 if (val > 0) { 4443 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4444 } else { 4445 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4446 } 4447 marked = PETSC_TRUE; 4448 break; 4449 } 4450 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4451 if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 4452 } 4453 } 4454 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4455 } 4456 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4457 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4458 PetscFunctionReturn(0); 4459 } 4460 4461 #undef __FUNCT__ 4462 #define __FUNCT__ "DMPlexInterpolate_2D" 4463 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4464 { 4465 DM idm; 4466 DM_Plex *mesh; 4467 PetscHashIJ edgeTable; 4468 PetscInt *off; 4469 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4470 PetscInt numEdges, firstEdge, edge, e; 4471 PetscErrorCode ierr; 4472 4473 PetscFunctionBegin; 4474 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4475 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4476 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4477 numCells = cEnd - cStart; 4478 numVertices = vEnd - vStart; 4479 firstEdge = numCells + numVertices; 4480 numEdges = 0; 4481 /* Count edges using algorithm from CreateNeighborCSR */ 4482 ierr = DMPlexCreateNeighborCSR(dm, NULL, &off, NULL);CHKERRQ(ierr); 4483 if (off) { 4484 PetscInt numCorners = 0; 4485 4486 numEdges = off[numCells]/2; 4487 #if 0 4488 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4489 numEdges += 3*numCells - off[numCells]; 4490 #else 4491 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4492 for (c = cStart; c < cEnd; ++c) { 4493 PetscInt coneSize; 4494 4495 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4496 numCorners += coneSize; 4497 } 4498 numEdges += numCorners - off[numCells]; 4499 #endif 4500 } 4501 #if 0 4502 /* Check Euler characteristic V - E + F = 1 */ 4503 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4504 #endif 4505 /* Create interpolated mesh */ 4506 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 4507 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4508 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4509 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4510 for (c = 0; c < numCells; ++c) { 4511 PetscInt numCorners; 4512 4513 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4514 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4515 } 4516 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4517 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4518 } 4519 ierr = DMSetUp(idm);CHKERRQ(ierr); 4520 /* Get edge cones from subsets of cell vertices */ 4521 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4522 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4523 4524 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4525 const PetscInt *cellFaces; 4526 PetscInt numCellFaces, faceSize, cf; 4527 4528 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4529 if (faceSize != 2) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4530 for (cf = 0; cf < numCellFaces; ++cf) { 4531 #if 1 4532 PetscHashIJKey key; 4533 4534 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4535 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4536 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4537 if (e < 0) { 4538 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4539 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4540 e = edge++; 4541 } 4542 #else 4543 PetscBool found = PETSC_FALSE; 4544 4545 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4546 for (e = firstEdge; e < edge; ++e) { 4547 const PetscInt *cone; 4548 4549 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4550 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4551 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4552 found = PETSC_TRUE; 4553 break; 4554 } 4555 } 4556 if (!found) { 4557 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4558 ++edge; 4559 } 4560 #endif 4561 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4562 } 4563 } 4564 if (edge != firstEdge+numEdges) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4565 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4566 ierr = PetscFree(off);CHKERRQ(ierr); 4567 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4568 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4569 mesh = (DM_Plex*) (idm)->data; 4570 /* Orient edges */ 4571 for (c = 0; c < numCells; ++c) { 4572 const PetscInt *cone = NULL, *cellFaces; 4573 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4574 4575 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4576 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4577 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4578 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4579 if (coneSize != numCellFaces) SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4580 for (cf = 0; cf < numCellFaces; ++cf) { 4581 const PetscInt *econe = NULL; 4582 PetscInt esize; 4583 4584 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4585 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4586 if (esize != 2) SETERRQ2(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4587 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4588 /* Correctly oriented */ 4589 mesh->coneOrientations[coff+cf] = 0; 4590 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4591 /* Start at index 1, and reverse orientation */ 4592 mesh->coneOrientations[coff+cf] = -(1+1); 4593 } 4594 } 4595 } 4596 *dmInt = idm; 4597 PetscFunctionReturn(0); 4598 } 4599 4600 #undef __FUNCT__ 4601 #define __FUNCT__ "DMPlexInterpolate_3D" 4602 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4603 { 4604 DM idm, fdm; 4605 DM_Plex *mesh; 4606 PetscInt *off; 4607 const PetscInt numCorners = 4; 4608 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4609 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4610 PetscErrorCode ierr; 4611 4612 PetscFunctionBegin; 4613 { 4614 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4615 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4616 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4617 } 4618 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4619 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4620 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4621 numCells = cEnd - cStart; 4622 numVertices = vEnd - vStart; 4623 firstFace = numCells + numVertices; 4624 numFaces = 0; 4625 /* Count faces using algorithm from CreateNeighborCSR */ 4626 ierr = DMPlexCreateNeighborCSR(dm, NULL, &off, NULL);CHKERRQ(ierr); 4627 if (off) { 4628 numFaces = off[numCells]/2; 4629 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4630 numFaces += 4*numCells - off[numCells]; 4631 } 4632 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4633 firstEdge = firstFace + numFaces; 4634 numEdges = numVertices + numFaces - numCells - 1; 4635 /* Create interpolated mesh */ 4636 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); 4637 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4638 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4639 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4640 for (c = 0; c < numCells; ++c) { 4641 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4642 } 4643 for (f = firstFace; f < firstFace+numFaces; ++f) { 4644 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4645 } 4646 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4647 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4648 } 4649 ierr = DMSetUp(idm);CHKERRQ(ierr); 4650 /* Get face cones from subsets of cell vertices */ 4651 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &fdm);CHKERRQ(ierr); 4652 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4653 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4654 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4655 for (f = firstFace; f < firstFace+numFaces; ++f) { 4656 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4657 } 4658 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4659 for (c = 0, face = firstFace; c < numCells; ++c) { 4660 const PetscInt *cellFaces; 4661 PetscInt numCellFaces, faceSize, cf; 4662 4663 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4664 if (faceSize != 3) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4665 for (cf = 0; cf < numCellFaces; ++cf) { 4666 PetscBool found = PETSC_FALSE; 4667 4668 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4669 for (f = firstFace; f < face; ++f) { 4670 const PetscInt *cone = NULL; 4671 4672 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4673 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4674 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4675 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4676 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4677 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4678 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4679 found = PETSC_TRUE; 4680 break; 4681 } 4682 } 4683 if (!found) { 4684 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4685 /* Save the vertices for orientation calculation */ 4686 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4687 ++face; 4688 } 4689 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4690 } 4691 } 4692 if (face != firstFace+numFaces) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4693 /* Get edge cones from subsets of face vertices */ 4694 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4695 const PetscInt *cellFaces; 4696 PetscInt numCellFaces, faceSize, cf; 4697 4698 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4699 if (faceSize != 2) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4700 for (cf = 0; cf < numCellFaces; ++cf) { 4701 PetscBool found = PETSC_FALSE; 4702 4703 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4704 for (e = firstEdge; e < edge; ++e) { 4705 const PetscInt *cone = NULL; 4706 4707 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4708 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4709 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4710 found = PETSC_TRUE; 4711 break; 4712 } 4713 } 4714 if (!found) { 4715 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4716 ++edge; 4717 } 4718 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4719 } 4720 } 4721 if (edge != firstEdge+numEdges) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4722 ierr = PetscFree(off);CHKERRQ(ierr); 4723 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4724 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4725 mesh = (DM_Plex*) (idm)->data; 4726 /* Orient edges */ 4727 for (f = firstFace; f < firstFace+numFaces; ++f) { 4728 const PetscInt *cone, *cellFaces; 4729 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4730 4731 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4732 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4733 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4734 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4735 if (coneSize != numCellFaces) SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4736 for (cf = 0; cf < numCellFaces; ++cf) { 4737 const PetscInt *econe; 4738 PetscInt esize; 4739 4740 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4741 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4742 if (esize != 2) SETERRQ2(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4743 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4744 /* Correctly oriented */ 4745 mesh->coneOrientations[coff+cf] = 0; 4746 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4747 /* Start at index 1, and reverse orientation */ 4748 mesh->coneOrientations[coff+cf] = -(1+1); 4749 } 4750 } 4751 } 4752 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4753 /* Orient faces */ 4754 for (c = 0; c < numCells; ++c) { 4755 const PetscInt *cone, *cellFaces; 4756 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4757 4758 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4759 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4760 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4761 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4762 if (coneSize != numCellFaces) SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4763 for (cf = 0; cf < numCellFaces; ++cf) { 4764 PetscInt *origClosure = NULL, *closure; 4765 PetscInt closureSize, i; 4766 4767 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4768 if (closureSize != 7) SETERRQ2(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4769 for (i = 4; i < 7; ++i) { 4770 if ((origClosure[i*2] < vStart) || (origClosure[i*2] >= vEnd)) SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Invalid closure point %D should be a vertex in [%D, %D)", origClosure[i*2], vStart, vEnd); 4771 } 4772 closure = &origClosure[4*2]; 4773 /* Remember that this is the orientation for edges, not vertices */ 4774 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4775 /* Correctly oriented */ 4776 mesh->coneOrientations[coff+cf] = 0; 4777 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4778 /* Shifted by 1 */ 4779 mesh->coneOrientations[coff+cf] = 1; 4780 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4781 /* Shifted by 2 */ 4782 mesh->coneOrientations[coff+cf] = 2; 4783 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4784 /* Start at edge 1, and reverse orientation */ 4785 mesh->coneOrientations[coff+cf] = -(1+1); 4786 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4787 /* Start at index 0, and reverse orientation */ 4788 mesh->coneOrientations[coff+cf] = -(0+1); 4789 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4790 /* Start at index 2, and reverse orientation */ 4791 mesh->coneOrientations[coff+cf] = -(2+1); 4792 } else SETERRQ3(PetscObjectComm((PetscObject)idm), PETSC_ERR_PLIB, "Face %D did not match local face %D in cell %D for any orientation", cone[cf], cf, c); 4793 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4794 } 4795 } 4796 { 4797 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4798 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4799 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4800 } 4801 *dmInt = idm; 4802 PetscFunctionReturn(0); 4803 } 4804 4805 #undef __FUNCT__ 4806 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4807 /* 4808 This takes as input the common mesh generator output, a list of the vertices for each cell 4809 */ 4810 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4811 { 4812 PetscInt *cone, c, p; 4813 PetscErrorCode ierr; 4814 4815 PetscFunctionBegin; 4816 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4817 for (c = 0; c < numCells; ++c) { 4818 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4819 } 4820 ierr = DMSetUp(dm);CHKERRQ(ierr); 4821 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4822 for (c = 0; c < numCells; ++c) { 4823 for (p = 0; p < numCorners; ++p) { 4824 cone[p] = cells[c*numCorners+p]+numCells; 4825 } 4826 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4827 } 4828 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4829 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4830 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4831 PetscFunctionReturn(0); 4832 } 4833 4834 #undef __FUNCT__ 4835 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4836 /* 4837 This takes as input the coordinates for each vertex 4838 */ 4839 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4840 { 4841 PetscSection coordSection; 4842 Vec coordinates; 4843 PetscScalar *coords; 4844 PetscInt coordSize, v, d; 4845 PetscErrorCode ierr; 4846 4847 PetscFunctionBegin; 4848 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4849 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4850 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4851 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4852 for (v = numCells; v < numCells+numVertices; ++v) { 4853 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4854 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4855 } 4856 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4857 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4858 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4859 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4860 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4861 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4862 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4863 for (v = 0; v < numVertices; ++v) { 4864 for (d = 0; d < spaceDim; ++d) { 4865 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4866 } 4867 } 4868 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4869 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4870 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4871 PetscFunctionReturn(0); 4872 } 4873 4874 #undef __FUNCT__ 4875 #define __FUNCT__ "DMPlexCreateFromCellList" 4876 /* 4877 This takes as input the common mesh generator output, a list of the vertices for each cell 4878 */ 4879 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4880 { 4881 PetscErrorCode ierr; 4882 4883 PetscFunctionBegin; 4884 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4885 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4886 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4887 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4888 if (interpolate) { 4889 DM idm; 4890 4891 switch (dim) { 4892 case 2: 4893 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4894 case 3: 4895 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4896 default: 4897 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4898 } 4899 ierr = DMDestroy(dm);CHKERRQ(ierr); 4900 *dm = idm; 4901 } 4902 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4903 PetscFunctionReturn(0); 4904 } 4905 4906 #if defined(PETSC_HAVE_TRIANGLE) 4907 #include <triangle.h> 4908 4909 #undef __FUNCT__ 4910 #define __FUNCT__ "InitInput_Triangle" 4911 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4912 { 4913 PetscFunctionBegin; 4914 inputCtx->numberofpoints = 0; 4915 inputCtx->numberofpointattributes = 0; 4916 inputCtx->pointlist = NULL; 4917 inputCtx->pointattributelist = NULL; 4918 inputCtx->pointmarkerlist = NULL; 4919 inputCtx->numberofsegments = 0; 4920 inputCtx->segmentlist = NULL; 4921 inputCtx->segmentmarkerlist = NULL; 4922 inputCtx->numberoftriangleattributes = 0; 4923 inputCtx->trianglelist = NULL; 4924 inputCtx->numberofholes = 0; 4925 inputCtx->holelist = NULL; 4926 inputCtx->numberofregions = 0; 4927 inputCtx->regionlist = NULL; 4928 PetscFunctionReturn(0); 4929 } 4930 4931 #undef __FUNCT__ 4932 #define __FUNCT__ "InitOutput_Triangle" 4933 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4934 { 4935 PetscFunctionBegin; 4936 outputCtx->numberofpoints = 0; 4937 outputCtx->pointlist = NULL; 4938 outputCtx->pointattributelist = NULL; 4939 outputCtx->pointmarkerlist = NULL; 4940 outputCtx->numberoftriangles = 0; 4941 outputCtx->trianglelist = NULL; 4942 outputCtx->triangleattributelist = NULL; 4943 outputCtx->neighborlist = NULL; 4944 outputCtx->segmentlist = NULL; 4945 outputCtx->segmentmarkerlist = NULL; 4946 outputCtx->numberofedges = 0; 4947 outputCtx->edgelist = NULL; 4948 outputCtx->edgemarkerlist = NULL; 4949 PetscFunctionReturn(0); 4950 } 4951 4952 #undef __FUNCT__ 4953 #define __FUNCT__ "FiniOutput_Triangle" 4954 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4955 { 4956 PetscFunctionBegin; 4957 free(outputCtx->pointmarkerlist); 4958 free(outputCtx->edgelist); 4959 free(outputCtx->edgemarkerlist); 4960 free(outputCtx->trianglelist); 4961 free(outputCtx->neighborlist); 4962 PetscFunctionReturn(0); 4963 } 4964 4965 #undef __FUNCT__ 4966 #define __FUNCT__ "DMPlexGenerate_Triangle" 4967 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4968 { 4969 MPI_Comm comm; 4970 PetscInt dim = 2; 4971 const PetscBool createConvexHull = PETSC_FALSE; 4972 const PetscBool constrained = PETSC_FALSE; 4973 struct triangulateio in; 4974 struct triangulateio out; 4975 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4976 PetscMPIInt rank; 4977 PetscErrorCode ierr; 4978 4979 PetscFunctionBegin; 4980 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4981 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4982 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4983 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4984 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4985 4986 in.numberofpoints = vEnd - vStart; 4987 if (in.numberofpoints > 0) { 4988 PetscSection coordSection; 4989 Vec coordinates; 4990 PetscScalar *array; 4991 4992 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4993 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4994 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4995 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4996 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4997 for (v = vStart; v < vEnd; ++v) { 4998 const PetscInt idx = v - vStart; 4999 PetscInt off, d; 5000 5001 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5002 for (d = 0; d < dim; ++d) { 5003 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5004 } 5005 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5006 } 5007 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5008 } 5009 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 5010 in.numberofsegments = eEnd - eStart; 5011 if (in.numberofsegments > 0) { 5012 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 5013 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 5014 for (e = eStart; e < eEnd; ++e) { 5015 const PetscInt idx = e - eStart; 5016 const PetscInt *cone; 5017 5018 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 5019 5020 in.segmentlist[idx*2+0] = cone[0] - vStart; 5021 in.segmentlist[idx*2+1] = cone[1] - vStart; 5022 5023 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5024 } 5025 } 5026 #if 0 /* Do not currently support holes */ 5027 PetscReal *holeCoords; 5028 PetscInt h, d; 5029 5030 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5031 if (in.numberofholes > 0) { 5032 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5033 for (h = 0; h < in.numberofholes; ++h) { 5034 for (d = 0; d < dim; ++d) { 5035 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5036 } 5037 } 5038 } 5039 #endif 5040 if (!rank) { 5041 char args[32]; 5042 5043 /* Take away 'Q' for verbose output */ 5044 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5045 if (createConvexHull) { 5046 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5047 } 5048 if (constrained) { 5049 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5050 } 5051 triangulate(args, &in, &out, NULL); 5052 } 5053 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5054 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5055 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5056 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5057 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5058 5059 { 5060 const PetscInt numCorners = 3; 5061 const PetscInt numCells = out.numberoftriangles; 5062 const PetscInt numVertices = out.numberofpoints; 5063 const int *cells = out.trianglelist; 5064 const double *meshCoords = out.pointlist; 5065 5066 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5067 /* Set labels */ 5068 for (v = 0; v < numVertices; ++v) { 5069 if (out.pointmarkerlist[v]) { 5070 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5071 } 5072 } 5073 if (interpolate) { 5074 for (e = 0; e < out.numberofedges; e++) { 5075 if (out.edgemarkerlist[e]) { 5076 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5077 const PetscInt *edges; 5078 PetscInt numEdges; 5079 5080 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5081 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5082 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5083 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5084 } 5085 } 5086 } 5087 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5088 } 5089 #if 0 /* Do not currently support holes */ 5090 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5091 #endif 5092 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5093 PetscFunctionReturn(0); 5094 } 5095 5096 #undef __FUNCT__ 5097 #define __FUNCT__ "DMPlexRefine_Triangle" 5098 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5099 { 5100 MPI_Comm comm; 5101 PetscInt dim = 2; 5102 struct triangulateio in; 5103 struct triangulateio out; 5104 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5105 PetscMPIInt rank; 5106 PetscErrorCode ierr; 5107 5108 PetscFunctionBegin; 5109 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5110 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5111 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5112 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5113 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5114 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5115 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5116 5117 in.numberofpoints = vEnd - vStart; 5118 if (in.numberofpoints > 0) { 5119 PetscSection coordSection; 5120 Vec coordinates; 5121 PetscScalar *array; 5122 5123 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5124 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5125 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5126 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5127 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5128 for (v = vStart; v < vEnd; ++v) { 5129 const PetscInt idx = v - vStart; 5130 PetscInt off, d; 5131 5132 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5133 for (d = 0; d < dim; ++d) { 5134 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5135 } 5136 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5137 } 5138 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5139 } 5140 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5141 5142 in.numberofcorners = 3; 5143 in.numberoftriangles = cEnd - cStart; 5144 5145 in.trianglearealist = (double*) maxVolumes; 5146 if (in.numberoftriangles > 0) { 5147 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5148 for (c = cStart; c < cEnd; ++c) { 5149 const PetscInt idx = c - cStart; 5150 PetscInt *closure = NULL; 5151 PetscInt closureSize; 5152 5153 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5154 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5155 for (v = 0; v < 3; ++v) { 5156 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5157 } 5158 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5159 } 5160 } 5161 /* TODO: Segment markers are missing on input */ 5162 #if 0 /* Do not currently support holes */ 5163 PetscReal *holeCoords; 5164 PetscInt h, d; 5165 5166 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5167 if (in.numberofholes > 0) { 5168 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5169 for (h = 0; h < in.numberofholes; ++h) { 5170 for (d = 0; d < dim; ++d) { 5171 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5172 } 5173 } 5174 } 5175 #endif 5176 if (!rank) { 5177 char args[32]; 5178 5179 /* Take away 'Q' for verbose output */ 5180 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5181 triangulate(args, &in, &out, NULL); 5182 } 5183 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5184 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5185 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5186 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5187 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5188 5189 { 5190 const PetscInt numCorners = 3; 5191 const PetscInt numCells = out.numberoftriangles; 5192 const PetscInt numVertices = out.numberofpoints; 5193 const int *cells = out.trianglelist; 5194 const double *meshCoords = out.pointlist; 5195 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5196 5197 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5198 /* Set labels */ 5199 for (v = 0; v < numVertices; ++v) { 5200 if (out.pointmarkerlist[v]) { 5201 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5202 } 5203 } 5204 if (interpolate) { 5205 PetscInt e; 5206 5207 for (e = 0; e < out.numberofedges; e++) { 5208 if (out.edgemarkerlist[e]) { 5209 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5210 const PetscInt *edges; 5211 PetscInt numEdges; 5212 5213 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5214 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5215 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5216 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5217 } 5218 } 5219 } 5220 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5221 } 5222 #if 0 /* Do not currently support holes */ 5223 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5224 #endif 5225 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5226 PetscFunctionReturn(0); 5227 } 5228 #endif 5229 5230 #if defined(PETSC_HAVE_TETGEN) 5231 #include <tetgen.h> 5232 #undef __FUNCT__ 5233 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5234 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5235 { 5236 MPI_Comm comm; 5237 const PetscInt dim = 3; 5238 ::tetgenio in; 5239 ::tetgenio out; 5240 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5241 PetscMPIInt rank; 5242 PetscErrorCode ierr; 5243 5244 PetscFunctionBegin; 5245 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5246 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5247 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5248 in.numberofpoints = vEnd - vStart; 5249 if (in.numberofpoints > 0) { 5250 PetscSection coordSection; 5251 Vec coordinates; 5252 PetscScalar *array; 5253 5254 in.pointlist = new double[in.numberofpoints*dim]; 5255 in.pointmarkerlist = new int[in.numberofpoints]; 5256 5257 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5258 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5259 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5260 for (v = vStart; v < vEnd; ++v) { 5261 const PetscInt idx = v - vStart; 5262 PetscInt off, d; 5263 5264 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5265 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5266 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5267 } 5268 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5269 } 5270 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5271 5272 in.numberoffacets = fEnd - fStart; 5273 if (in.numberoffacets > 0) { 5274 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5275 in.facetmarkerlist = new int[in.numberoffacets]; 5276 for (f = fStart; f < fEnd; ++f) { 5277 const PetscInt idx = f - fStart; 5278 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 5279 5280 in.facetlist[idx].numberofpolygons = 1; 5281 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5282 in.facetlist[idx].numberofholes = 0; 5283 in.facetlist[idx].holelist = NULL; 5284 5285 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5286 for (p = 0; p < numPoints*2; p += 2) { 5287 const PetscInt point = points[p]; 5288 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5289 } 5290 5291 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5292 poly->numberofvertices = numVertices; 5293 poly->vertexlist = new int[poly->numberofvertices]; 5294 for (v = 0; v < numVertices; ++v) { 5295 const PetscInt vIdx = points[v] - vStart; 5296 poly->vertexlist[v] = vIdx; 5297 } 5298 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5299 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5300 } 5301 } 5302 if (!rank) { 5303 char args[32]; 5304 5305 /* Take away 'Q' for verbose output */ 5306 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5307 ::tetrahedralize(args, &in, &out); 5308 } 5309 { 5310 const PetscInt numCorners = 4; 5311 const PetscInt numCells = out.numberoftetrahedra; 5312 const PetscInt numVertices = out.numberofpoints; 5313 const int *cells = out.tetrahedronlist; 5314 const double *meshCoords = out.pointlist; 5315 5316 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5317 /* Set labels */ 5318 for (v = 0; v < numVertices; ++v) { 5319 if (out.pointmarkerlist[v]) { 5320 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5321 } 5322 } 5323 if (interpolate) { 5324 PetscInt e; 5325 5326 for (e = 0; e < out.numberofedges; e++) { 5327 if (out.edgemarkerlist[e]) { 5328 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5329 const PetscInt *edges; 5330 PetscInt numEdges; 5331 5332 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5333 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5334 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5335 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5336 } 5337 } 5338 for (f = 0; f < out.numberoftrifaces; f++) { 5339 if (out.trifacemarkerlist[f]) { 5340 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5341 const PetscInt *faces; 5342 PetscInt numFaces; 5343 5344 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5345 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5346 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5347 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5348 } 5349 } 5350 } 5351 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5352 } 5353 PetscFunctionReturn(0); 5354 } 5355 5356 #undef __FUNCT__ 5357 #define __FUNCT__ "DMPlexRefine_Tetgen" 5358 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5359 { 5360 MPI_Comm comm; 5361 const PetscInt dim = 3; 5362 ::tetgenio in; 5363 ::tetgenio out; 5364 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5365 PetscMPIInt rank; 5366 PetscErrorCode ierr; 5367 5368 PetscFunctionBegin; 5369 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5370 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5371 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5372 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5373 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5374 5375 in.numberofpoints = vEnd - vStart; 5376 if (in.numberofpoints > 0) { 5377 PetscSection coordSection; 5378 Vec coordinates; 5379 PetscScalar *array; 5380 5381 in.pointlist = new double[in.numberofpoints*dim]; 5382 in.pointmarkerlist = new int[in.numberofpoints]; 5383 5384 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5385 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5386 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5387 for (v = vStart; v < vEnd; ++v) { 5388 const PetscInt idx = v - vStart; 5389 PetscInt off, d; 5390 5391 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5392 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5393 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5394 } 5395 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5396 } 5397 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5398 5399 in.numberofcorners = 4; 5400 in.numberoftetrahedra = cEnd - cStart; 5401 in.tetrahedronvolumelist = (double*) maxVolumes; 5402 if (in.numberoftetrahedra > 0) { 5403 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5404 for (c = cStart; c < cEnd; ++c) { 5405 const PetscInt idx = c - cStart; 5406 PetscInt *closure = NULL; 5407 PetscInt closureSize; 5408 5409 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5410 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5411 for (v = 0; v < 4; ++v) { 5412 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5413 } 5414 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5415 } 5416 } 5417 /* TODO: Put in boundary faces with markers */ 5418 if (!rank) { 5419 char args[32]; 5420 5421 /* Take away 'Q' for verbose output */ 5422 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5423 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5424 ::tetrahedralize(args, &in, &out); 5425 } 5426 in.tetrahedronvolumelist = NULL; 5427 5428 { 5429 const PetscInt numCorners = 4; 5430 const PetscInt numCells = out.numberoftetrahedra; 5431 const PetscInt numVertices = out.numberofpoints; 5432 const int *cells = out.tetrahedronlist; 5433 const double *meshCoords = out.pointlist; 5434 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5435 5436 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5437 /* Set labels */ 5438 for (v = 0; v < numVertices; ++v) { 5439 if (out.pointmarkerlist[v]) { 5440 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5441 } 5442 } 5443 if (interpolate) { 5444 PetscInt e, f; 5445 5446 for (e = 0; e < out.numberofedges; e++) { 5447 if (out.edgemarkerlist[e]) { 5448 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5449 const PetscInt *edges; 5450 PetscInt numEdges; 5451 5452 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5453 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5454 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5455 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5456 } 5457 } 5458 for (f = 0; f < out.numberoftrifaces; f++) { 5459 if (out.trifacemarkerlist[f]) { 5460 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5461 const PetscInt *faces; 5462 PetscInt numFaces; 5463 5464 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5465 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5466 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5467 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5468 } 5469 } 5470 } 5471 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5472 } 5473 PetscFunctionReturn(0); 5474 } 5475 #endif 5476 5477 #if defined(PETSC_HAVE_CTETGEN) 5478 #include "ctetgen.h" 5479 5480 #undef __FUNCT__ 5481 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5482 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5483 { 5484 MPI_Comm comm; 5485 const PetscInt dim = 3; 5486 PLC *in, *out; 5487 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5488 PetscMPIInt rank; 5489 PetscErrorCode ierr; 5490 5491 PetscFunctionBegin; 5492 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5493 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5494 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5495 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5496 ierr = PLCCreate(&in);CHKERRQ(ierr); 5497 ierr = PLCCreate(&out);CHKERRQ(ierr); 5498 5499 in->numberofpoints = vEnd - vStart; 5500 if (in->numberofpoints > 0) { 5501 PetscSection coordSection; 5502 Vec coordinates; 5503 PetscScalar *array; 5504 5505 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5506 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5507 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5508 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5509 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5510 for (v = vStart; v < vEnd; ++v) { 5511 const PetscInt idx = v - vStart; 5512 PetscInt off, d, m; 5513 5514 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5515 for (d = 0; d < dim; ++d) { 5516 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5517 } 5518 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5519 5520 in->pointmarkerlist[idx] = (int) m; 5521 } 5522 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5523 } 5524 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5525 5526 in->numberoffacets = fEnd - fStart; 5527 if (in->numberoffacets > 0) { 5528 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5529 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5530 for (f = fStart; f < fEnd; ++f) { 5531 const PetscInt idx = f - fStart; 5532 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5533 polygon *poly; 5534 5535 in->facetlist[idx].numberofpolygons = 1; 5536 5537 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5538 5539 in->facetlist[idx].numberofholes = 0; 5540 in->facetlist[idx].holelist = NULL; 5541 5542 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5543 for (p = 0; p < numPoints*2; p += 2) { 5544 const PetscInt point = points[p]; 5545 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5546 } 5547 5548 poly = in->facetlist[idx].polygonlist; 5549 poly->numberofvertices = numVertices; 5550 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5551 for (v = 0; v < numVertices; ++v) { 5552 const PetscInt vIdx = points[v] - vStart; 5553 poly->vertexlist[v] = vIdx; 5554 } 5555 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5556 in->facetmarkerlist[idx] = (int) m; 5557 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5558 } 5559 } 5560 if (!rank) { 5561 TetGenOpts t; 5562 5563 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5564 t.in = boundary; /* Should go away */ 5565 t.plc = 1; 5566 t.quality = 1; 5567 t.edgesout = 1; 5568 t.zeroindex = 1; 5569 t.quiet = 1; 5570 t.verbose = verbose; 5571 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5572 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5573 } 5574 { 5575 const PetscInt numCorners = 4; 5576 const PetscInt numCells = out->numberoftetrahedra; 5577 const PetscInt numVertices = out->numberofpoints; 5578 const int *cells = out->tetrahedronlist; 5579 const double *meshCoords = out->pointlist; 5580 5581 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5582 /* Set labels */ 5583 for (v = 0; v < numVertices; ++v) { 5584 if (out->pointmarkerlist[v]) { 5585 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5586 } 5587 } 5588 if (interpolate) { 5589 PetscInt e; 5590 5591 for (e = 0; e < out->numberofedges; e++) { 5592 if (out->edgemarkerlist[e]) { 5593 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5594 const PetscInt *edges; 5595 PetscInt numEdges; 5596 5597 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5598 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5599 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5600 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5601 } 5602 } 5603 for (f = 0; f < out->numberoftrifaces; f++) { 5604 if (out->trifacemarkerlist[f]) { 5605 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5606 const PetscInt *faces; 5607 PetscInt numFaces; 5608 5609 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5610 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5611 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5612 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5613 } 5614 } 5615 } 5616 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5617 } 5618 5619 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5620 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5621 PetscFunctionReturn(0); 5622 } 5623 5624 #undef __FUNCT__ 5625 #define __FUNCT__ "DMPlexRefine_CTetgen" 5626 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5627 { 5628 MPI_Comm comm; 5629 const PetscInt dim = 3; 5630 PLC *in, *out; 5631 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5632 PetscMPIInt rank; 5633 PetscErrorCode ierr; 5634 5635 PetscFunctionBegin; 5636 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5637 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5638 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5639 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5640 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5641 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5642 ierr = PLCCreate(&in);CHKERRQ(ierr); 5643 ierr = PLCCreate(&out);CHKERRQ(ierr); 5644 5645 in->numberofpoints = vEnd - vStart; 5646 if (in->numberofpoints > 0) { 5647 PetscSection coordSection; 5648 Vec coordinates; 5649 PetscScalar *array; 5650 5651 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5652 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5653 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5654 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5655 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5656 for (v = vStart; v < vEnd; ++v) { 5657 const PetscInt idx = v - vStart; 5658 PetscInt off, d, m; 5659 5660 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5661 for (d = 0; d < dim; ++d) { 5662 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5663 } 5664 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5665 5666 in->pointmarkerlist[idx] = (int) m; 5667 } 5668 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5669 } 5670 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5671 5672 in->numberofcorners = 4; 5673 in->numberoftetrahedra = cEnd - cStart; 5674 in->tetrahedronvolumelist = maxVolumes; 5675 if (in->numberoftetrahedra > 0) { 5676 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5677 for (c = cStart; c < cEnd; ++c) { 5678 const PetscInt idx = c - cStart; 5679 PetscInt *closure = NULL; 5680 PetscInt closureSize; 5681 5682 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5683 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5684 for (v = 0; v < 4; ++v) { 5685 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5686 } 5687 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5688 } 5689 } 5690 if (!rank) { 5691 TetGenOpts t; 5692 5693 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5694 5695 t.in = dm; /* Should go away */ 5696 t.refine = 1; 5697 t.varvolume = 1; 5698 t.quality = 1; 5699 t.edgesout = 1; 5700 t.zeroindex = 1; 5701 t.quiet = 1; 5702 t.verbose = verbose; /* Change this */ 5703 5704 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5705 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5706 } 5707 { 5708 const PetscInt numCorners = 4; 5709 const PetscInt numCells = out->numberoftetrahedra; 5710 const PetscInt numVertices = out->numberofpoints; 5711 const int *cells = out->tetrahedronlist; 5712 const double *meshCoords = out->pointlist; 5713 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5714 5715 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5716 /* Set labels */ 5717 for (v = 0; v < numVertices; ++v) { 5718 if (out->pointmarkerlist[v]) { 5719 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5720 } 5721 } 5722 if (interpolate) { 5723 PetscInt e, f; 5724 5725 for (e = 0; e < out->numberofedges; e++) { 5726 if (out->edgemarkerlist[e]) { 5727 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5728 const PetscInt *edges; 5729 PetscInt numEdges; 5730 5731 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5732 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5733 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5734 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5735 } 5736 } 5737 for (f = 0; f < out->numberoftrifaces; f++) { 5738 if (out->trifacemarkerlist[f]) { 5739 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5740 const PetscInt *faces; 5741 PetscInt numFaces; 5742 5743 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5744 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5745 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5746 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5747 } 5748 } 5749 } 5750 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5751 } 5752 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5753 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5754 PetscFunctionReturn(0); 5755 } 5756 #endif 5757 5758 #undef __FUNCT__ 5759 #define __FUNCT__ "DMPlexGenerate" 5760 /*@C 5761 DMPlexGenerate - Generates a mesh. 5762 5763 Not Collective 5764 5765 Input Parameters: 5766 + boundary - The DMPlex boundary object 5767 . name - The mesh generation package name 5768 - interpolate - Flag to create intermediate mesh elements 5769 5770 Output Parameter: 5771 . mesh - The DMPlex object 5772 5773 Level: intermediate 5774 5775 .keywords: mesh, elements 5776 .seealso: DMPlexCreate(), DMRefine() 5777 @*/ 5778 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5779 { 5780 PetscInt dim; 5781 char genname[1024]; 5782 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5783 PetscErrorCode ierr; 5784 5785 PetscFunctionBegin; 5786 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5787 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5788 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5789 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5790 if (flg) name = genname; 5791 if (name) { 5792 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5793 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5794 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5795 } 5796 switch (dim) { 5797 case 1: 5798 if (!name || isTriangle) { 5799 #if defined(PETSC_HAVE_TRIANGLE) 5800 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5801 #else 5802 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5803 #endif 5804 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5805 break; 5806 case 2: 5807 if (!name || isCTetgen) { 5808 #if defined(PETSC_HAVE_CTETGEN) 5809 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5810 #else 5811 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5812 #endif 5813 } else if (isTetgen) { 5814 #if defined(PETSC_HAVE_TETGEN) 5815 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5816 #else 5817 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5818 #endif 5819 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5820 break; 5821 default: 5822 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5823 } 5824 PetscFunctionReturn(0); 5825 } 5826 5827 typedef PetscInt CellRefiner; 5828 5829 #undef __FUNCT__ 5830 #define __FUNCT__ "GetDepthStart_Private" 5831 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5832 { 5833 PetscFunctionBegin; 5834 if (cStart) *cStart = 0; 5835 if (vStart) *vStart = depthSize[depth]; 5836 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5837 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5838 PetscFunctionReturn(0); 5839 } 5840 5841 #undef __FUNCT__ 5842 #define __FUNCT__ "GetDepthEnd_Private" 5843 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5844 { 5845 PetscFunctionBegin; 5846 if (cEnd) *cEnd = depthSize[depth]; 5847 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5848 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5849 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5850 PetscFunctionReturn(0); 5851 } 5852 5853 #undef __FUNCT__ 5854 #define __FUNCT__ "CellRefinerGetSizes" 5855 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5856 { 5857 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5858 PetscErrorCode ierr; 5859 5860 PetscFunctionBegin; 5861 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5862 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5863 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5864 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5865 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5866 switch (refiner) { 5867 case 1: 5868 /* Simplicial 2D */ 5869 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5870 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5871 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5872 break; 5873 case 3: 5874 /* Hybrid 2D */ 5875 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5876 cMax = PetscMin(cEnd, cMax); 5877 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5878 fMax = PetscMin(fEnd, fMax); 5879 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5880 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 */ 5881 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5882 break; 5883 case 2: 5884 /* Hex 2D */ 5885 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5886 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5887 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5888 break; 5889 default: 5890 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5891 } 5892 PetscFunctionReturn(0); 5893 } 5894 5895 #undef __FUNCT__ 5896 #define __FUNCT__ "CellRefinerSetConeSizes" 5897 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5898 { 5899 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5900 PetscErrorCode ierr; 5901 5902 PetscFunctionBegin; 5903 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5904 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5905 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5906 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5907 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5908 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5909 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5910 switch (refiner) { 5911 case 1: 5912 /* Simplicial 2D */ 5913 /* All cells have 3 faces */ 5914 for (c = cStart; c < cEnd; ++c) { 5915 for (r = 0; r < 4; ++r) { 5916 const PetscInt newp = (c - cStart)*4 + r; 5917 5918 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5919 } 5920 } 5921 /* Split faces have 2 vertices and the same cells as the parent */ 5922 for (f = fStart; f < fEnd; ++f) { 5923 for (r = 0; r < 2; ++r) { 5924 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5925 PetscInt size; 5926 5927 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5928 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5929 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5930 } 5931 } 5932 /* Interior faces have 2 vertices and 2 cells */ 5933 for (c = cStart; c < cEnd; ++c) { 5934 for (r = 0; r < 3; ++r) { 5935 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5936 5937 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5938 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5939 } 5940 } 5941 /* Old vertices have identical supports */ 5942 for (v = vStart; v < vEnd; ++v) { 5943 const PetscInt newp = vStartNew + (v - vStart); 5944 PetscInt size; 5945 5946 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5947 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5948 } 5949 /* Face vertices have 2 + cells*2 supports */ 5950 for (f = fStart; f < fEnd; ++f) { 5951 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5952 PetscInt size; 5953 5954 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5955 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5956 } 5957 break; 5958 case 2: 5959 /* Hex 2D */ 5960 /* All cells have 4 faces */ 5961 for (c = cStart; c < cEnd; ++c) { 5962 for (r = 0; r < 4; ++r) { 5963 const PetscInt newp = (c - cStart)*4 + r; 5964 5965 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5966 } 5967 } 5968 /* Split faces have 2 vertices and the same cells as the parent */ 5969 for (f = fStart; f < fEnd; ++f) { 5970 for (r = 0; r < 2; ++r) { 5971 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5972 PetscInt size; 5973 5974 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5975 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5976 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5977 } 5978 } 5979 /* Interior faces have 2 vertices and 2 cells */ 5980 for (c = cStart; c < cEnd; ++c) { 5981 for (r = 0; r < 4; ++r) { 5982 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5983 5984 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5985 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5986 } 5987 } 5988 /* Old vertices have identical supports */ 5989 for (v = vStart; v < vEnd; ++v) { 5990 const PetscInt newp = vStartNew + (v - vStart); 5991 PetscInt size; 5992 5993 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5994 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5995 } 5996 /* Face vertices have 2 + cells supports */ 5997 for (f = fStart; f < fEnd; ++f) { 5998 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5999 PetscInt size; 6000 6001 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6002 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 6003 } 6004 /* Cell vertices have 4 supports */ 6005 for (c = cStart; c < cEnd; ++c) { 6006 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6007 6008 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 6009 } 6010 break; 6011 case 3: 6012 /* Hybrid 2D */ 6013 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6014 cMax = PetscMin(cEnd, cMax); 6015 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6016 fMax = PetscMin(fEnd, fMax); 6017 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6018 /* Interior cells have 3 faces */ 6019 for (c = cStart; c < cMax; ++c) { 6020 for (r = 0; r < 4; ++r) { 6021 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 6022 6023 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 6024 } 6025 } 6026 /* Hybrid cells have 4 faces */ 6027 for (c = cMax; c < cEnd; ++c) { 6028 for (r = 0; r < 2; ++r) { 6029 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6030 6031 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6032 } 6033 } 6034 /* Interior split faces have 2 vertices and the same cells as the parent */ 6035 for (f = fStart; f < fMax; ++f) { 6036 for (r = 0; r < 2; ++r) { 6037 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6038 PetscInt size; 6039 6040 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6041 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6042 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6043 } 6044 } 6045 /* Interior cell faces have 2 vertices and 2 cells */ 6046 for (c = cStart; c < cMax; ++c) { 6047 for (r = 0; r < 3; ++r) { 6048 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6049 6050 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6051 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6052 } 6053 } 6054 /* Hybrid faces have 2 vertices and the same cells */ 6055 for (f = fMax; f < fEnd; ++f) { 6056 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6057 PetscInt size; 6058 6059 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6060 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6061 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6062 } 6063 /* Hybrid cell faces have 2 vertices and 2 cells */ 6064 for (c = cMax; c < cEnd; ++c) { 6065 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6066 6067 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6068 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6069 } 6070 /* Old vertices have identical supports */ 6071 for (v = vStart; v < vEnd; ++v) { 6072 const PetscInt newp = vStartNew + (v - vStart); 6073 PetscInt size; 6074 6075 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6076 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6077 } 6078 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6079 for (f = fStart; f < fMax; ++f) { 6080 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6081 const PetscInt *support; 6082 PetscInt size, newSize = 2, s; 6083 6084 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6085 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6086 for (s = 0; s < size; ++s) { 6087 if (support[s] >= cMax) newSize += 1; 6088 else newSize += 2; 6089 } 6090 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6091 } 6092 break; 6093 default: 6094 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6095 } 6096 PetscFunctionReturn(0); 6097 } 6098 6099 #undef __FUNCT__ 6100 #define __FUNCT__ "CellRefinerSetCones" 6101 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6102 { 6103 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; 6104 PetscInt maxSupportSize, *supportRef; 6105 PetscErrorCode ierr; 6106 6107 PetscFunctionBegin; 6108 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6109 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6110 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6111 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6112 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6113 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6114 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6115 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6116 switch (refiner) { 6117 case 1: 6118 /* Simplicial 2D */ 6119 /* 6120 2 6121 |\ 6122 | \ 6123 | \ 6124 | \ 6125 | C \ 6126 | \ 6127 | \ 6128 2---1---1 6129 |\ D / \ 6130 | 2 0 \ 6131 |A \ / B \ 6132 0---0-------1 6133 */ 6134 /* All cells have 3 faces */ 6135 for (c = cStart; c < cEnd; ++c) { 6136 const PetscInt newp = cStartNew + (c - cStart)*4; 6137 const PetscInt *cone, *ornt; 6138 PetscInt coneNew[3], orntNew[3]; 6139 6140 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6141 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6142 /* A triangle */ 6143 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6144 orntNew[0] = ornt[0]; 6145 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6146 orntNew[1] = -2; 6147 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6148 orntNew[2] = ornt[2]; 6149 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6150 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6151 #if 1 6152 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); 6153 for (p = 0; p < 3; ++p) { 6154 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); 6155 } 6156 #endif 6157 /* B triangle */ 6158 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6159 orntNew[0] = ornt[0]; 6160 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6161 orntNew[1] = ornt[1]; 6162 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6163 orntNew[2] = -2; 6164 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6165 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6166 #if 1 6167 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); 6168 for (p = 0; p < 3; ++p) { 6169 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); 6170 } 6171 #endif 6172 /* C triangle */ 6173 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6174 orntNew[0] = -2; 6175 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6176 orntNew[1] = ornt[1]; 6177 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6178 orntNew[2] = ornt[2]; 6179 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6180 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6181 #if 1 6182 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); 6183 for (p = 0; p < 3; ++p) { 6184 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); 6185 } 6186 #endif 6187 /* D triangle */ 6188 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6189 orntNew[0] = 0; 6190 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6191 orntNew[1] = 0; 6192 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6193 orntNew[2] = 0; 6194 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6195 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6196 #if 1 6197 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); 6198 for (p = 0; p < 3; ++p) { 6199 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6200 } 6201 #endif 6202 } 6203 /* Split faces have 2 vertices and the same cells as the parent */ 6204 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6205 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6206 for (f = fStart; f < fEnd; ++f) { 6207 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6208 6209 for (r = 0; r < 2; ++r) { 6210 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6211 const PetscInt *cone, *support; 6212 PetscInt coneNew[2], coneSize, c, supportSize, s; 6213 6214 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6215 coneNew[0] = vStartNew + (cone[0] - vStart); 6216 coneNew[1] = vStartNew + (cone[1] - vStart); 6217 coneNew[(r+1)%2] = newv; 6218 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6219 #if 1 6220 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6221 for (p = 0; p < 2; ++p) { 6222 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); 6223 } 6224 #endif 6225 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6226 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6227 for (s = 0; s < supportSize; ++s) { 6228 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6229 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6230 for (c = 0; c < coneSize; ++c) { 6231 if (cone[c] == f) break; 6232 } 6233 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6234 } 6235 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6236 #if 1 6237 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6238 for (p = 0; p < supportSize; ++p) { 6239 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); 6240 } 6241 #endif 6242 } 6243 } 6244 /* Interior faces have 2 vertices and 2 cells */ 6245 for (c = cStart; c < cEnd; ++c) { 6246 const PetscInt *cone; 6247 6248 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6249 for (r = 0; r < 3; ++r) { 6250 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6251 PetscInt coneNew[2]; 6252 PetscInt supportNew[2]; 6253 6254 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6255 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6256 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6257 #if 1 6258 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6259 for (p = 0; p < 2; ++p) { 6260 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); 6261 } 6262 #endif 6263 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6264 supportNew[1] = (c - cStart)*4 + 3; 6265 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6266 #if 1 6267 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6268 for (p = 0; p < 2; ++p) { 6269 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); 6270 } 6271 #endif 6272 } 6273 } 6274 /* Old vertices have identical supports */ 6275 for (v = vStart; v < vEnd; ++v) { 6276 const PetscInt newp = vStartNew + (v - vStart); 6277 const PetscInt *support, *cone; 6278 PetscInt size, s; 6279 6280 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6281 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6282 for (s = 0; s < size; ++s) { 6283 PetscInt r = 0; 6284 6285 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6286 if (cone[1] == v) r = 1; 6287 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6288 } 6289 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6290 #if 1 6291 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6292 for (p = 0; p < size; ++p) { 6293 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); 6294 } 6295 #endif 6296 } 6297 /* Face vertices have 2 + cells*2 supports */ 6298 for (f = fStart; f < fEnd; ++f) { 6299 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6300 const PetscInt *cone, *support; 6301 PetscInt size, s; 6302 6303 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6304 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6305 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6306 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6307 for (s = 0; s < size; ++s) { 6308 PetscInt r = 0; 6309 6310 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6311 if (cone[1] == f) r = 1; 6312 else if (cone[2] == f) r = 2; 6313 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6314 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6315 } 6316 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6317 #if 1 6318 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6319 for (p = 0; p < 2+size*2; ++p) { 6320 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); 6321 } 6322 #endif 6323 } 6324 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6325 break; 6326 case 2: 6327 /* Hex 2D */ 6328 /* 6329 3---------2---------2 6330 | | | 6331 | D 2 C | 6332 | | | 6333 3----3----0----1----1 6334 | | | 6335 | A 0 B | 6336 | | | 6337 0---------0---------1 6338 */ 6339 /* All cells have 4 faces */ 6340 for (c = cStart; c < cEnd; ++c) { 6341 const PetscInt newp = (c - cStart)*4; 6342 const PetscInt *cone, *ornt; 6343 PetscInt coneNew[4], orntNew[4]; 6344 6345 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6346 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6347 /* A quad */ 6348 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6349 orntNew[0] = ornt[0]; 6350 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6351 orntNew[1] = 0; 6352 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6353 orntNew[2] = -2; 6354 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6355 orntNew[3] = ornt[3]; 6356 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6357 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6358 #if 1 6359 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); 6360 for (p = 0; p < 4; ++p) { 6361 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); 6362 } 6363 #endif 6364 /* B quad */ 6365 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6366 orntNew[0] = ornt[0]; 6367 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6368 orntNew[1] = ornt[1]; 6369 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6370 orntNew[2] = 0; 6371 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6372 orntNew[3] = -2; 6373 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6374 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6375 #if 1 6376 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); 6377 for (p = 0; p < 4; ++p) { 6378 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); 6379 } 6380 #endif 6381 /* C quad */ 6382 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6383 orntNew[0] = -2; 6384 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6385 orntNew[1] = ornt[1]; 6386 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6387 orntNew[2] = ornt[2]; 6388 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6389 orntNew[3] = 0; 6390 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6391 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6392 #if 1 6393 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); 6394 for (p = 0; p < 4; ++p) { 6395 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); 6396 } 6397 #endif 6398 /* D quad */ 6399 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6400 orntNew[0] = 0; 6401 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6402 orntNew[1] = -2; 6403 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6404 orntNew[2] = ornt[2]; 6405 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6406 orntNew[3] = ornt[3]; 6407 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6408 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6409 #if 1 6410 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); 6411 for (p = 0; p < 4; ++p) { 6412 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); 6413 } 6414 #endif 6415 } 6416 /* Split faces have 2 vertices and the same cells as the parent */ 6417 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6418 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6419 for (f = fStart; f < fEnd; ++f) { 6420 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6421 6422 for (r = 0; r < 2; ++r) { 6423 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6424 const PetscInt *cone, *support; 6425 PetscInt coneNew[2], coneSize, c, supportSize, s; 6426 6427 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6428 coneNew[0] = vStartNew + (cone[0] - vStart); 6429 coneNew[1] = vStartNew + (cone[1] - vStart); 6430 coneNew[(r+1)%2] = newv; 6431 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6432 #if 1 6433 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6434 for (p = 0; p < 2; ++p) { 6435 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); 6436 } 6437 #endif 6438 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6439 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6440 for (s = 0; s < supportSize; ++s) { 6441 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6442 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6443 for (c = 0; c < coneSize; ++c) { 6444 if (cone[c] == f) break; 6445 } 6446 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6447 } 6448 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6449 #if 1 6450 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6451 for (p = 0; p < supportSize; ++p) { 6452 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); 6453 } 6454 #endif 6455 } 6456 } 6457 /* Interior faces have 2 vertices and 2 cells */ 6458 for (c = cStart; c < cEnd; ++c) { 6459 const PetscInt *cone; 6460 PetscInt coneNew[2], supportNew[2]; 6461 6462 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6463 for (r = 0; r < 4; ++r) { 6464 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6465 6466 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6467 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6468 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6469 #if 1 6470 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6471 for (p = 0; p < 2; ++p) { 6472 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); 6473 } 6474 #endif 6475 supportNew[0] = (c - cStart)*4 + r; 6476 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6477 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6478 #if 1 6479 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6480 for (p = 0; p < 2; ++p) { 6481 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); 6482 } 6483 #endif 6484 } 6485 } 6486 /* Old vertices have identical supports */ 6487 for (v = vStart; v < vEnd; ++v) { 6488 const PetscInt newp = vStartNew + (v - vStart); 6489 const PetscInt *support, *cone; 6490 PetscInt size, s; 6491 6492 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6493 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6494 for (s = 0; s < size; ++s) { 6495 PetscInt r = 0; 6496 6497 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6498 if (cone[1] == v) r = 1; 6499 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6500 } 6501 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6502 #if 1 6503 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6504 for (p = 0; p < size; ++p) { 6505 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); 6506 } 6507 #endif 6508 } 6509 /* Face vertices have 2 + cells supports */ 6510 for (f = fStart; f < fEnd; ++f) { 6511 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6512 const PetscInt *cone, *support; 6513 PetscInt size, s; 6514 6515 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6516 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6517 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6518 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6519 for (s = 0; s < size; ++s) { 6520 PetscInt r = 0; 6521 6522 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6523 if (cone[1] == f) r = 1; 6524 else if (cone[2] == f) r = 2; 6525 else if (cone[3] == f) r = 3; 6526 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6527 } 6528 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6529 #if 1 6530 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6531 for (p = 0; p < 2+size; ++p) { 6532 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); 6533 } 6534 #endif 6535 } 6536 /* Cell vertices have 4 supports */ 6537 for (c = cStart; c < cEnd; ++c) { 6538 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6539 PetscInt supportNew[4]; 6540 6541 for (r = 0; r < 4; ++r) { 6542 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6543 } 6544 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6545 } 6546 break; 6547 case 3: 6548 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6549 cMax = PetscMin(cEnd, cMax); 6550 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6551 fMax = PetscMin(fEnd, fMax); 6552 /* Interior cells have 3 faces */ 6553 for (c = cStart; c < cMax; ++c) { 6554 const PetscInt newp = cStartNew + (c - cStart)*4; 6555 const PetscInt *cone, *ornt; 6556 PetscInt coneNew[3], orntNew[3]; 6557 6558 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6559 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6560 /* A triangle */ 6561 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6562 orntNew[0] = ornt[0]; 6563 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6564 orntNew[1] = -2; 6565 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6566 orntNew[2] = ornt[2]; 6567 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6568 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6569 #if 1 6570 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); 6571 for (p = 0; p < 3; ++p) { 6572 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); 6573 } 6574 #endif 6575 /* B triangle */ 6576 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6577 orntNew[0] = ornt[0]; 6578 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6579 orntNew[1] = ornt[1]; 6580 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6581 orntNew[2] = -2; 6582 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6583 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6584 #if 1 6585 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); 6586 for (p = 0; p < 3; ++p) { 6587 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); 6588 } 6589 #endif 6590 /* C triangle */ 6591 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6592 orntNew[0] = -2; 6593 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6594 orntNew[1] = ornt[1]; 6595 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6596 orntNew[2] = ornt[2]; 6597 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6598 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6599 #if 1 6600 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); 6601 for (p = 0; p < 3; ++p) { 6602 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); 6603 } 6604 #endif 6605 /* D triangle */ 6606 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6607 orntNew[0] = 0; 6608 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6609 orntNew[1] = 0; 6610 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6611 orntNew[2] = 0; 6612 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6613 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6614 #if 1 6615 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); 6616 for (p = 0; p < 3; ++p) { 6617 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); 6618 } 6619 #endif 6620 } 6621 /* 6622 2----3----3 6623 | | 6624 | B | 6625 | | 6626 0----4--- 1 6627 | | 6628 | A | 6629 | | 6630 0----2----1 6631 */ 6632 /* Hybrid cells have 4 faces */ 6633 for (c = cMax; c < cEnd; ++c) { 6634 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6635 const PetscInt *cone, *ornt; 6636 PetscInt coneNew[4], orntNew[4]; 6637 6638 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6639 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6640 /* A quad */ 6641 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6642 orntNew[0] = ornt[0]; 6643 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6644 orntNew[1] = ornt[1]; 6645 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6646 orntNew[2] = 0; 6647 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6648 orntNew[3] = 0; 6649 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6650 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6651 #if 1 6652 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); 6653 for (p = 0; p < 4; ++p) { 6654 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); 6655 } 6656 #endif 6657 /* B quad */ 6658 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6659 orntNew[0] = ornt[0]; 6660 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6661 orntNew[1] = ornt[1]; 6662 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6663 orntNew[2] = 0; 6664 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6665 orntNew[3] = 0; 6666 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6667 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6668 #if 1 6669 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); 6670 for (p = 0; p < 4; ++p) { 6671 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); 6672 } 6673 #endif 6674 } 6675 /* Interior split faces have 2 vertices and the same cells as the parent */ 6676 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6677 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6678 for (f = fStart; f < fMax; ++f) { 6679 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6680 6681 for (r = 0; r < 2; ++r) { 6682 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6683 const PetscInt *cone, *support; 6684 PetscInt coneNew[2], coneSize, c, supportSize, s; 6685 6686 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6687 coneNew[0] = vStartNew + (cone[0] - vStart); 6688 coneNew[1] = vStartNew + (cone[1] - vStart); 6689 coneNew[(r+1)%2] = newv; 6690 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6691 #if 1 6692 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6693 for (p = 0; p < 2; ++p) { 6694 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); 6695 } 6696 #endif 6697 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6698 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6699 for (s = 0; s < supportSize; ++s) { 6700 if (support[s] >= cMax) { 6701 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6702 } else { 6703 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6704 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6705 for (c = 0; c < coneSize; ++c) { 6706 if (cone[c] == f) break; 6707 } 6708 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6709 } 6710 } 6711 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6712 #if 1 6713 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6714 for (p = 0; p < supportSize; ++p) { 6715 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); 6716 } 6717 #endif 6718 } 6719 } 6720 /* Interior cell faces have 2 vertices and 2 cells */ 6721 for (c = cStart; c < cMax; ++c) { 6722 const PetscInt *cone; 6723 6724 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6725 for (r = 0; r < 3; ++r) { 6726 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6727 PetscInt coneNew[2]; 6728 PetscInt supportNew[2]; 6729 6730 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6731 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6732 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6733 #if 1 6734 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6735 for (p = 0; p < 2; ++p) { 6736 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); 6737 } 6738 #endif 6739 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6740 supportNew[1] = (c - cStart)*4 + 3; 6741 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6742 #if 1 6743 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6744 for (p = 0; p < 2; ++p) { 6745 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); 6746 } 6747 #endif 6748 } 6749 } 6750 /* Interior hybrid faces have 2 vertices and the same cells */ 6751 for (f = fMax; f < fEnd; ++f) { 6752 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6753 const PetscInt *cone; 6754 const PetscInt *support; 6755 PetscInt coneNew[2]; 6756 PetscInt supportNew[2]; 6757 PetscInt size, s, r; 6758 6759 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6760 coneNew[0] = vStartNew + (cone[0] - vStart); 6761 coneNew[1] = vStartNew + (cone[1] - vStart); 6762 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6763 #if 1 6764 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6765 for (p = 0; p < 2; ++p) { 6766 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); 6767 } 6768 #endif 6769 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6770 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6771 for (s = 0; s < size; ++s) { 6772 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6773 for (r = 0; r < 2; ++r) { 6774 if (cone[r+2] == f) break; 6775 } 6776 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6777 } 6778 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6779 #if 1 6780 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6781 for (p = 0; p < size; ++p) { 6782 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); 6783 } 6784 #endif 6785 } 6786 /* Cell hybrid faces have 2 vertices and 2 cells */ 6787 for (c = cMax; c < cEnd; ++c) { 6788 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6789 const PetscInt *cone; 6790 PetscInt coneNew[2]; 6791 PetscInt supportNew[2]; 6792 6793 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6794 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6795 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6796 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6797 #if 1 6798 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6799 for (p = 0; p < 2; ++p) { 6800 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); 6801 } 6802 #endif 6803 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6804 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6805 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6806 #if 1 6807 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6808 for (p = 0; p < 2; ++p) { 6809 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); 6810 } 6811 #endif 6812 } 6813 /* Old vertices have identical supports */ 6814 for (v = vStart; v < vEnd; ++v) { 6815 const PetscInt newp = vStartNew + (v - vStart); 6816 const PetscInt *support, *cone; 6817 PetscInt size, s; 6818 6819 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6820 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6821 for (s = 0; s < size; ++s) { 6822 if (support[s] >= fMax) { 6823 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6824 } else { 6825 PetscInt r = 0; 6826 6827 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6828 if (cone[1] == v) r = 1; 6829 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6830 } 6831 } 6832 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6833 #if 1 6834 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6835 for (p = 0; p < size; ++p) { 6836 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); 6837 } 6838 #endif 6839 } 6840 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6841 for (f = fStart; f < fMax; ++f) { 6842 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6843 const PetscInt *cone, *support; 6844 PetscInt size, newSize = 2, s; 6845 6846 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6847 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6848 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6849 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6850 for (s = 0; s < size; ++s) { 6851 PetscInt r = 0; 6852 6853 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6854 if (support[s] >= cMax) { 6855 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6856 6857 newSize += 1; 6858 } else { 6859 if (cone[1] == f) r = 1; 6860 else if (cone[2] == f) r = 2; 6861 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6862 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6863 6864 newSize += 2; 6865 } 6866 } 6867 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6868 #if 1 6869 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6870 for (p = 0; p < newSize; ++p) { 6871 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); 6872 } 6873 #endif 6874 } 6875 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6876 break; 6877 default: 6878 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6879 } 6880 PetscFunctionReturn(0); 6881 } 6882 6883 #undef __FUNCT__ 6884 #define __FUNCT__ "CellRefinerSetCoordinates" 6885 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6886 { 6887 PetscSection coordSection, coordSectionNew; 6888 Vec coordinates, coordinatesNew; 6889 PetscScalar *coords, *coordsNew; 6890 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6891 PetscErrorCode ierr; 6892 6893 PetscFunctionBegin; 6894 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6895 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6896 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6897 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6898 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6899 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6900 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6901 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6902 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6903 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6904 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6905 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6906 if (fMax < 0) fMax = fEnd; 6907 switch (refiner) { 6908 case 1: 6909 case 2: 6910 case 3: 6911 /* Simplicial and Hex 2D */ 6912 /* All vertices have the dim coordinates */ 6913 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6914 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6915 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6916 } 6917 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6918 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6919 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6920 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6921 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6922 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6923 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6924 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6925 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6926 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6927 /* Old vertices have the same coordinates */ 6928 for (v = vStart; v < vEnd; ++v) { 6929 const PetscInt newv = vStartNew + (v - vStart); 6930 PetscInt off, offnew, d; 6931 6932 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6933 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6934 for (d = 0; d < dim; ++d) { 6935 coordsNew[offnew+d] = coords[off+d]; 6936 } 6937 } 6938 /* Face vertices have the average of endpoint coordinates */ 6939 for (f = fStart; f < fMax; ++f) { 6940 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6941 const PetscInt *cone; 6942 PetscInt coneSize, offA, offB, offnew, d; 6943 6944 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6945 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6946 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6947 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6948 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6949 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6950 for (d = 0; d < dim; ++d) { 6951 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6952 } 6953 } 6954 /* Just Hex 2D */ 6955 if (refiner == 2) { 6956 /* Cell vertices have the average of corner coordinates */ 6957 for (c = cStart; c < cEnd; ++c) { 6958 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6959 PetscInt *cone = NULL; 6960 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6961 6962 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6963 for (p = 0; p < closureSize*2; p += 2) { 6964 const PetscInt point = cone[p]; 6965 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6966 } 6967 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6968 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6969 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6970 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6971 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6972 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6973 for (d = 0; d < dim; ++d) { 6974 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6975 } 6976 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6977 } 6978 } 6979 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6980 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6981 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6982 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6983 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 6984 break; 6985 default: 6986 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6987 } 6988 PetscFunctionReturn(0); 6989 } 6990 6991 #undef __FUNCT__ 6992 #define __FUNCT__ "DMPlexCreateProcessSF" 6993 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6994 { 6995 PetscInt numRoots, numLeaves, l; 6996 const PetscInt *localPoints; 6997 const PetscSFNode *remotePoints; 6998 PetscInt *localPointsNew; 6999 PetscSFNode *remotePointsNew; 7000 PetscInt *ranks, *ranksNew; 7001 PetscErrorCode ierr; 7002 7003 PetscFunctionBegin; 7004 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7005 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 7006 for (l = 0; l < numLeaves; ++l) { 7007 ranks[l] = remotePoints[l].rank; 7008 } 7009 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 7010 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 7011 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7012 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7013 for (l = 0; l < numLeaves; ++l) { 7014 ranksNew[l] = ranks[l]; 7015 localPointsNew[l] = l; 7016 remotePointsNew[l].index = 0; 7017 remotePointsNew[l].rank = ranksNew[l]; 7018 } 7019 ierr = PetscFree(ranks);CHKERRQ(ierr); 7020 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 7021 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 7022 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 7023 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7024 PetscFunctionReturn(0); 7025 } 7026 7027 #undef __FUNCT__ 7028 #define __FUNCT__ "CellRefinerCreateSF" 7029 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7030 { 7031 PetscSF sf, sfNew, sfProcess; 7032 IS processRanks; 7033 MPI_Datatype depthType; 7034 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7035 const PetscInt *localPoints, *neighbors; 7036 const PetscSFNode *remotePoints; 7037 PetscInt *localPointsNew; 7038 PetscSFNode *remotePointsNew; 7039 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7040 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7041 PetscErrorCode ierr; 7042 7043 PetscFunctionBegin; 7044 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7045 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7046 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7047 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7048 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7049 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7050 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7051 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7052 switch (refiner) { 7053 case 3: 7054 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7055 cMax = PetscMin(cEnd, cMax); 7056 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7057 fMax = PetscMin(fEnd, fMax); 7058 } 7059 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7060 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7061 /* Caculate size of new SF */ 7062 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7063 if (numRoots < 0) PetscFunctionReturn(0); 7064 for (l = 0; l < numLeaves; ++l) { 7065 const PetscInt p = localPoints[l]; 7066 7067 switch (refiner) { 7068 case 1: 7069 /* Simplicial 2D */ 7070 if ((p >= vStart) && (p < vEnd)) { 7071 /* Old vertices stay the same */ 7072 ++numLeavesNew; 7073 } else if ((p >= fStart) && (p < fEnd)) { 7074 /* Old faces add new faces and vertex */ 7075 numLeavesNew += 1 + 2; 7076 } else if ((p >= cStart) && (p < cEnd)) { 7077 /* Old cells add new cells and interior faces */ 7078 numLeavesNew += 4 + 3; 7079 } 7080 break; 7081 case 2: 7082 /* Hex 2D */ 7083 if ((p >= vStart) && (p < vEnd)) { 7084 /* Old vertices stay the same */ 7085 ++numLeavesNew; 7086 } else if ((p >= fStart) && (p < fEnd)) { 7087 /* Old faces add new faces and vertex */ 7088 numLeavesNew += 1 + 2; 7089 } else if ((p >= cStart) && (p < cEnd)) { 7090 /* Old cells add new cells and interior faces */ 7091 numLeavesNew += 4 + 4; 7092 } 7093 break; 7094 default: 7095 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7096 } 7097 } 7098 /* Communicate depthSizes for each remote rank */ 7099 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7100 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7101 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7102 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); 7103 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7104 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7105 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7106 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7107 for (n = 0; n < numNeighbors; ++n) { 7108 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7109 } 7110 depthSizeOld[depth] = cMax; 7111 depthSizeOld[0] = vMax; 7112 depthSizeOld[depth-1] = fMax; 7113 depthSizeOld[1] = eMax; 7114 7115 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7116 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7117 7118 depthSizeOld[depth] = cEnd - cStart; 7119 depthSizeOld[0] = vEnd - vStart; 7120 depthSizeOld[depth-1] = fEnd - fStart; 7121 depthSizeOld[1] = eEnd - eStart; 7122 7123 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7124 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7125 for (n = 0; n < numNeighbors; ++n) { 7126 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7127 } 7128 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7129 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7130 /* Calculate new point SF */ 7131 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7132 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7133 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7134 for (l = 0, m = 0; l < numLeaves; ++l) { 7135 PetscInt p = localPoints[l]; 7136 PetscInt rp = remotePoints[l].index, n; 7137 PetscMPIInt rrank = remotePoints[l].rank; 7138 7139 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7140 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7141 switch (refiner) { 7142 case 1: 7143 /* Simplicial 2D */ 7144 if ((p >= vStart) && (p < vEnd)) { 7145 /* Old vertices stay the same */ 7146 localPointsNew[m] = vStartNew + (p - vStart); 7147 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7148 remotePointsNew[m].rank = rrank; 7149 ++m; 7150 } else if ((p >= fStart) && (p < fEnd)) { 7151 /* Old faces add new faces and vertex */ 7152 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7153 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7154 remotePointsNew[m].rank = rrank; 7155 ++m; 7156 for (r = 0; r < 2; ++r, ++m) { 7157 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7158 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7159 remotePointsNew[m].rank = rrank; 7160 } 7161 } else if ((p >= cStart) && (p < cEnd)) { 7162 /* Old cells add new cells and interior faces */ 7163 for (r = 0; r < 4; ++r, ++m) { 7164 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7165 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7166 remotePointsNew[m].rank = rrank; 7167 } 7168 for (r = 0; r < 3; ++r, ++m) { 7169 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7170 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7171 remotePointsNew[m].rank = rrank; 7172 } 7173 } 7174 break; 7175 case 2: 7176 /* Hex 2D */ 7177 if ((p >= vStart) && (p < vEnd)) { 7178 /* Old vertices stay the same */ 7179 localPointsNew[m] = vStartNew + (p - vStart); 7180 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7181 remotePointsNew[m].rank = rrank; 7182 ++m; 7183 } else if ((p >= fStart) && (p < fEnd)) { 7184 /* Old faces add new faces and vertex */ 7185 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7186 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7187 remotePointsNew[m].rank = rrank; 7188 ++m; 7189 for (r = 0; r < 2; ++r, ++m) { 7190 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7191 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7192 remotePointsNew[m].rank = rrank; 7193 } 7194 } else if ((p >= cStart) && (p < cEnd)) { 7195 /* Old cells add new cells and interior faces */ 7196 for (r = 0; r < 4; ++r, ++m) { 7197 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7198 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7199 remotePointsNew[m].rank = rrank; 7200 } 7201 for (r = 0; r < 4; ++r, ++m) { 7202 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7203 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7204 remotePointsNew[m].rank = rrank; 7205 } 7206 } 7207 break; 7208 case 3: 7209 /* Hybrid simplicial 2D */ 7210 if ((p >= vStart) && (p < vEnd)) { 7211 /* Old vertices stay the same */ 7212 localPointsNew[m] = vStartNew + (p - vStart); 7213 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7214 remotePointsNew[m].rank = rrank; 7215 ++m; 7216 } else if ((p >= fStart) && (p < fMax)) { 7217 /* Old interior faces add new faces and vertex */ 7218 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7219 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7220 remotePointsNew[m].rank = rrank; 7221 ++m; 7222 for (r = 0; r < 2; ++r, ++m) { 7223 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7224 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7225 remotePointsNew[m].rank = rrank; 7226 } 7227 } else if ((p >= fMax) && (p < fEnd)) { 7228 /* Old hybrid faces stay the same */ 7229 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7230 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7231 remotePointsNew[m].rank = rrank; 7232 ++m; 7233 } else if ((p >= cStart) && (p < cMax)) { 7234 /* Old interior cells add new cells and interior faces */ 7235 for (r = 0; r < 4; ++r, ++m) { 7236 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7237 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7238 remotePointsNew[m].rank = rrank; 7239 } 7240 for (r = 0; r < 3; ++r, ++m) { 7241 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7242 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7243 remotePointsNew[m].rank = rrank; 7244 } 7245 } else if ((p >= cStart) && (p < cMax)) { 7246 /* Old hybrid cells add new cells and hybrid face */ 7247 for (r = 0; r < 2; ++r, ++m) { 7248 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7249 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7250 remotePointsNew[m].rank = rrank; 7251 } 7252 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7253 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]); 7254 remotePointsNew[m].rank = rrank; 7255 ++m; 7256 } 7257 break; 7258 default: 7259 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7260 } 7261 } 7262 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7263 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7264 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7265 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7266 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7267 PetscFunctionReturn(0); 7268 } 7269 7270 #undef __FUNCT__ 7271 #define __FUNCT__ "CellRefinerCreateLabels" 7272 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7273 { 7274 PetscInt numLabels, l; 7275 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7276 PetscErrorCode ierr; 7277 7278 PetscFunctionBegin; 7279 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7280 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7281 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7282 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7283 7284 cStartNew = 0; 7285 vStartNew = depthSize[2]; 7286 fStartNew = depthSize[2] + depthSize[0]; 7287 7288 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7289 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7290 switch (refiner) { 7291 case 3: 7292 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7293 cMax = PetscMin(cEnd, cMax); 7294 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7295 fMax = PetscMin(fEnd, fMax); 7296 } 7297 for (l = 0; l < numLabels; ++l) { 7298 DMLabel label, labelNew; 7299 const char *lname; 7300 PetscBool isDepth; 7301 IS valueIS; 7302 const PetscInt *values; 7303 PetscInt numValues, val; 7304 7305 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7306 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7307 if (isDepth) continue; 7308 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7309 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7310 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7311 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7312 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7313 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7314 for (val = 0; val < numValues; ++val) { 7315 IS pointIS; 7316 const PetscInt *points; 7317 PetscInt numPoints, n; 7318 7319 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7320 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7321 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7322 for (n = 0; n < numPoints; ++n) { 7323 const PetscInt p = points[n]; 7324 switch (refiner) { 7325 case 1: 7326 /* Simplicial 2D */ 7327 if ((p >= vStart) && (p < vEnd)) { 7328 /* Old vertices stay the same */ 7329 newp = vStartNew + (p - vStart); 7330 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7331 } else if ((p >= fStart) && (p < fEnd)) { 7332 /* Old faces add new faces and vertex */ 7333 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7334 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7335 for (r = 0; r < 2; ++r) { 7336 newp = fStartNew + (p - fStart)*2 + r; 7337 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7338 } 7339 } else if ((p >= cStart) && (p < cEnd)) { 7340 /* Old cells add new cells and interior faces */ 7341 for (r = 0; r < 4; ++r) { 7342 newp = cStartNew + (p - cStart)*4 + r; 7343 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7344 } 7345 for (r = 0; r < 3; ++r) { 7346 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7347 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7348 } 7349 } 7350 break; 7351 case 2: 7352 /* Hex 2D */ 7353 if ((p >= vStart) && (p < vEnd)) { 7354 /* Old vertices stay the same */ 7355 newp = vStartNew + (p - vStart); 7356 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7357 } else if ((p >= fStart) && (p < fEnd)) { 7358 /* Old faces add new faces and vertex */ 7359 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7360 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7361 for (r = 0; r < 2; ++r) { 7362 newp = fStartNew + (p - fStart)*2 + r; 7363 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7364 } 7365 } else if ((p >= cStart) && (p < cEnd)) { 7366 /* Old cells add new cells and interior faces and vertex */ 7367 for (r = 0; r < 4; ++r) { 7368 newp = cStartNew + (p - cStart)*4 + r; 7369 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7370 } 7371 for (r = 0; r < 4; ++r) { 7372 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7373 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7374 } 7375 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7376 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7377 } 7378 break; 7379 case 3: 7380 /* Hybrid simplicial 2D */ 7381 if ((p >= vStart) && (p < vEnd)) { 7382 /* Old vertices stay the same */ 7383 newp = vStartNew + (p - vStart); 7384 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7385 } else if ((p >= fStart) && (p < fMax)) { 7386 /* Old interior faces add new faces and vertex */ 7387 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7388 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7389 for (r = 0; r < 2; ++r) { 7390 newp = fStartNew + (p - fStart)*2 + r; 7391 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7392 } 7393 } else if ((p >= fMax) && (p < fEnd)) { 7394 /* Old hybrid faces stay the same */ 7395 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7396 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7397 } else if ((p >= cStart) && (p < cMax)) { 7398 /* Old interior cells add new cells and interior faces */ 7399 for (r = 0; r < 4; ++r) { 7400 newp = cStartNew + (p - cStart)*4 + r; 7401 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7402 } 7403 for (r = 0; r < 3; ++r) { 7404 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7405 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7406 } 7407 } else if ((p >= cMax) && (p < cEnd)) { 7408 /* Old hybrid cells add new cells and hybrid face */ 7409 for (r = 0; r < 2; ++r) { 7410 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7411 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7412 } 7413 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7414 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7415 } 7416 break; 7417 default: 7418 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7419 } 7420 } 7421 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7422 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7423 } 7424 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7425 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7426 if (0) { 7427 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7428 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7429 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7430 } 7431 } 7432 PetscFunctionReturn(0); 7433 } 7434 7435 #undef __FUNCT__ 7436 #define __FUNCT__ "DMPlexRefine_Uniform" 7437 /* This will only work for interpolated meshes */ 7438 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7439 { 7440 DM rdm; 7441 PetscInt *depthSize; 7442 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7443 PetscErrorCode ierr; 7444 7445 PetscFunctionBegin; 7446 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 7447 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7448 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7449 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7450 /* Calculate number of new points of each depth */ 7451 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7452 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7453 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7454 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7455 /* Step 1: Set chart */ 7456 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7457 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7458 /* Step 2: Set cone/support sizes */ 7459 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7460 /* Step 3: Setup refined DM */ 7461 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7462 /* Step 4: Set cones and supports */ 7463 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7464 /* Step 5: Stratify */ 7465 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7466 /* Step 6: Set coordinates for vertices */ 7467 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7468 /* Step 7: Create pointSF */ 7469 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7470 /* Step 8: Create labels */ 7471 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7472 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7473 7474 *dmRefined = rdm; 7475 PetscFunctionReturn(0); 7476 } 7477 7478 #undef __FUNCT__ 7479 #define __FUNCT__ "DMPlexSetRefinementUniform" 7480 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7481 { 7482 DM_Plex *mesh = (DM_Plex*) dm->data; 7483 7484 PetscFunctionBegin; 7485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7486 mesh->refinementUniform = refinementUniform; 7487 PetscFunctionReturn(0); 7488 } 7489 7490 #undef __FUNCT__ 7491 #define __FUNCT__ "DMPlexGetRefinementUniform" 7492 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7493 { 7494 DM_Plex *mesh = (DM_Plex*) dm->data; 7495 7496 PetscFunctionBegin; 7497 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7498 PetscValidPointer(refinementUniform, 2); 7499 *refinementUniform = mesh->refinementUniform; 7500 PetscFunctionReturn(0); 7501 } 7502 7503 #undef __FUNCT__ 7504 #define __FUNCT__ "DMPlexSetRefinementLimit" 7505 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7506 { 7507 DM_Plex *mesh = (DM_Plex*) dm->data; 7508 7509 PetscFunctionBegin; 7510 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7511 mesh->refinementLimit = refinementLimit; 7512 PetscFunctionReturn(0); 7513 } 7514 7515 #undef __FUNCT__ 7516 #define __FUNCT__ "DMPlexGetRefinementLimit" 7517 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7518 { 7519 DM_Plex *mesh = (DM_Plex*) dm->data; 7520 7521 PetscFunctionBegin; 7522 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7523 PetscValidPointer(refinementLimit, 2); 7524 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7525 *refinementLimit = mesh->refinementLimit; 7526 PetscFunctionReturn(0); 7527 } 7528 7529 #undef __FUNCT__ 7530 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7531 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7532 { 7533 PetscInt dim, cStart, coneSize, cMax; 7534 PetscErrorCode ierr; 7535 7536 PetscFunctionBegin; 7537 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7538 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7539 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7540 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7541 switch (dim) { 7542 case 2: 7543 switch (coneSize) { 7544 case 3: 7545 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7546 else *cellRefiner = 1; /* Triangular */ 7547 break; 7548 case 4: 7549 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7550 else *cellRefiner = 2; /* Quadrilateral */ 7551 break; 7552 default: 7553 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7554 } 7555 break; 7556 default: 7557 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7558 } 7559 PetscFunctionReturn(0); 7560 } 7561 7562 #undef __FUNCT__ 7563 #define __FUNCT__ "DMRefine_Plex" 7564 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7565 { 7566 PetscReal refinementLimit; 7567 PetscInt dim, cStart, cEnd; 7568 char genname[1024], *name = NULL; 7569 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7570 PetscErrorCode ierr; 7571 7572 PetscFunctionBegin; 7573 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7574 if (isUniform) { 7575 CellRefiner cellRefiner; 7576 7577 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7578 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7579 PetscFunctionReturn(0); 7580 } 7581 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7582 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7583 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7584 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7585 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7586 if (flg) name = genname; 7587 if (name) { 7588 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7589 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7590 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7591 } 7592 switch (dim) { 7593 case 2: 7594 if (!name || isTriangle) { 7595 #if defined(PETSC_HAVE_TRIANGLE) 7596 double *maxVolumes; 7597 PetscInt c; 7598 7599 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7600 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7601 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7602 #else 7603 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7604 #endif 7605 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7606 break; 7607 case 3: 7608 if (!name || isCTetgen) { 7609 #if defined(PETSC_HAVE_CTETGEN) 7610 PetscReal *maxVolumes; 7611 PetscInt c; 7612 7613 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7614 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7615 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7616 #else 7617 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7618 #endif 7619 } else if (isTetgen) { 7620 #if defined(PETSC_HAVE_TETGEN) 7621 double *maxVolumes; 7622 PetscInt c; 7623 7624 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7625 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7626 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7627 #else 7628 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7629 #endif 7630 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7631 break; 7632 default: 7633 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7634 } 7635 PetscFunctionReturn(0); 7636 } 7637 7638 #undef __FUNCT__ 7639 #define __FUNCT__ "DMPlexGetDepth" 7640 /*@ 7641 DMPlexGetDepth - get the number of strata 7642 7643 Not Collective 7644 7645 Input Parameters: 7646 . dm - The DMPlex object 7647 7648 Output Parameters: 7649 . depth - number of strata 7650 7651 Level: developer 7652 7653 Notes: 7654 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7655 7656 .keywords: mesh, points 7657 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7658 @*/ 7659 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7660 { 7661 PetscInt d; 7662 PetscErrorCode ierr; 7663 7664 PetscFunctionBegin; 7665 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7666 PetscValidPointer(depth, 2); 7667 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7668 *depth = d-1; 7669 PetscFunctionReturn(0); 7670 } 7671 7672 #undef __FUNCT__ 7673 #define __FUNCT__ "DMPlexGetDepthStratum" 7674 /*@ 7675 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7676 7677 Not Collective 7678 7679 Input Parameters: 7680 + dm - The DMPlex object 7681 - stratumValue - The requested depth 7682 7683 Output Parameters: 7684 + start - The first point at this depth 7685 - end - One beyond the last point at this depth 7686 7687 Level: developer 7688 7689 .keywords: mesh, points 7690 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7691 @*/ 7692 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7693 { 7694 DM_Plex *mesh = (DM_Plex*) dm->data; 7695 DMLabel next = mesh->labels; 7696 PetscBool flg = PETSC_FALSE; 7697 PetscInt depth; 7698 PetscErrorCode ierr; 7699 7700 PetscFunctionBegin; 7701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7702 if (stratumValue < 0) { 7703 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7704 PetscFunctionReturn(0); 7705 } else { 7706 PetscInt pStart, pEnd; 7707 7708 if (start) *start = 0; 7709 if (end) *end = 0; 7710 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7711 if (pStart == pEnd) PetscFunctionReturn(0); 7712 } 7713 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7714 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7715 /* We should have a generic GetLabel() and a Label class */ 7716 while (next) { 7717 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7718 if (flg) break; 7719 next = next->next; 7720 } 7721 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7722 depth = stratumValue; 7723 if ((depth < 0) || (depth >= next->numStrata)) { 7724 if (start) *start = 0; 7725 if (end) *end = 0; 7726 } else { 7727 if (start) *start = next->points[next->stratumOffsets[depth]]; 7728 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7729 } 7730 PetscFunctionReturn(0); 7731 } 7732 7733 #undef __FUNCT__ 7734 #define __FUNCT__ "DMPlexGetHeightStratum" 7735 /*@ 7736 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7737 7738 Not Collective 7739 7740 Input Parameters: 7741 + dm - The DMPlex object 7742 - stratumValue - The requested height 7743 7744 Output Parameters: 7745 + start - The first point at this height 7746 - end - One beyond the last point at this height 7747 7748 Level: developer 7749 7750 .keywords: mesh, points 7751 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7752 @*/ 7753 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7754 { 7755 DM_Plex *mesh = (DM_Plex*) dm->data; 7756 DMLabel next = mesh->labels; 7757 PetscBool flg = PETSC_FALSE; 7758 PetscInt depth; 7759 PetscErrorCode ierr; 7760 7761 PetscFunctionBegin; 7762 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7763 if (stratumValue < 0) { 7764 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7765 } else { 7766 PetscInt pStart, pEnd; 7767 7768 if (start) *start = 0; 7769 if (end) *end = 0; 7770 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7771 if (pStart == pEnd) PetscFunctionReturn(0); 7772 } 7773 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7774 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7775 /* We should have a generic GetLabel() and a Label class */ 7776 while (next) { 7777 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7778 if (flg) break; 7779 next = next->next; 7780 } 7781 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7782 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7783 if ((depth < 0) || (depth >= next->numStrata)) { 7784 if (start) *start = 0; 7785 if (end) *end = 0; 7786 } else { 7787 if (start) *start = next->points[next->stratumOffsets[depth]]; 7788 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7789 } 7790 PetscFunctionReturn(0); 7791 } 7792 7793 #undef __FUNCT__ 7794 #define __FUNCT__ "DMPlexCreateSectionInitial" 7795 /* Set the number of dof on each point and separate by fields */ 7796 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7797 { 7798 PetscInt *numDofTot; 7799 PetscInt pStart = 0, pEnd = 0; 7800 PetscInt p, d, f; 7801 PetscErrorCode ierr; 7802 7803 PetscFunctionBegin; 7804 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7805 for (d = 0; d <= dim; ++d) { 7806 numDofTot[d] = 0; 7807 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7808 } 7809 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7810 if (numFields > 0) { 7811 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7812 if (numComp) { 7813 for (f = 0; f < numFields; ++f) { 7814 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7815 } 7816 } 7817 } 7818 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7819 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7820 for (d = 0; d <= dim; ++d) { 7821 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7822 for (p = pStart; p < pEnd; ++p) { 7823 for (f = 0; f < numFields; ++f) { 7824 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7825 } 7826 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7827 } 7828 } 7829 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7830 PetscFunctionReturn(0); 7831 } 7832 7833 #undef __FUNCT__ 7834 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7835 /* Set the number of dof on each point and separate by fields 7836 If constDof is PETSC_DETERMINE, constrain every dof on the point 7837 */ 7838 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7839 { 7840 PetscInt numFields; 7841 PetscInt bc; 7842 PetscErrorCode ierr; 7843 7844 PetscFunctionBegin; 7845 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7846 for (bc = 0; bc < numBC; ++bc) { 7847 PetscInt field = 0; 7848 const PetscInt *idx; 7849 PetscInt n, i; 7850 7851 if (numFields) field = bcField[bc]; 7852 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7853 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7854 for (i = 0; i < n; ++i) { 7855 const PetscInt p = idx[i]; 7856 PetscInt numConst = constDof; 7857 7858 /* Constrain every dof on the point */ 7859 if (numConst < 0) { 7860 if (numFields) { 7861 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7862 } else { 7863 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7864 } 7865 } 7866 if (numFields) { 7867 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7868 } 7869 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7870 } 7871 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7872 } 7873 PetscFunctionReturn(0); 7874 } 7875 7876 #undef __FUNCT__ 7877 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7878 /* Set the constrained indices on each point and separate by fields */ 7879 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7880 { 7881 PetscInt *maxConstraints; 7882 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7883 PetscErrorCode ierr; 7884 7885 PetscFunctionBegin; 7886 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7887 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7888 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7889 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7890 for (p = pStart; p < pEnd; ++p) { 7891 PetscInt cdof; 7892 7893 if (numFields) { 7894 for (f = 0; f < numFields; ++f) { 7895 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7896 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7897 } 7898 } else { 7899 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7900 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7901 } 7902 } 7903 for (f = 0; f < numFields; ++f) { 7904 maxConstraints[numFields] += maxConstraints[f]; 7905 } 7906 if (maxConstraints[numFields]) { 7907 PetscInt *indices; 7908 7909 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7910 for (p = pStart; p < pEnd; ++p) { 7911 PetscInt cdof, d; 7912 7913 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7914 if (cdof) { 7915 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7916 if (numFields) { 7917 PetscInt numConst = 0, foff = 0; 7918 7919 for (f = 0; f < numFields; ++f) { 7920 PetscInt cfdof, fdof; 7921 7922 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7923 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7924 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7925 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7926 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7927 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7928 numConst += cfdof; 7929 foff += fdof; 7930 } 7931 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7932 } else { 7933 for (d = 0; d < cdof; ++d) indices[d] = d; 7934 } 7935 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7936 } 7937 } 7938 ierr = PetscFree(indices);CHKERRQ(ierr); 7939 } 7940 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7941 PetscFunctionReturn(0); 7942 } 7943 7944 #undef __FUNCT__ 7945 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7946 /* Set the constrained field indices on each point */ 7947 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7948 { 7949 const PetscInt *points, *indices; 7950 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7951 PetscErrorCode ierr; 7952 7953 PetscFunctionBegin; 7954 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7955 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7956 7957 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7958 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7959 if (!constraintIndices) { 7960 PetscInt *idx, i; 7961 7962 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7963 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7964 for (i = 0; i < maxDof; ++i) idx[i] = i; 7965 for (p = 0; p < numPoints; ++p) { 7966 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7967 } 7968 ierr = PetscFree(idx);CHKERRQ(ierr); 7969 } else { 7970 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7971 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7972 for (p = 0; p < numPoints; ++p) { 7973 PetscInt fcdof; 7974 7975 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7976 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); 7977 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7978 } 7979 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7980 } 7981 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7982 PetscFunctionReturn(0); 7983 } 7984 7985 #undef __FUNCT__ 7986 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7987 /* Set the constrained indices on each point and separate by fields */ 7988 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7989 { 7990 PetscInt *indices; 7991 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7992 PetscErrorCode ierr; 7993 7994 PetscFunctionBegin; 7995 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7996 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7997 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7998 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7999 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8000 for (p = pStart; p < pEnd; ++p) { 8001 PetscInt cdof, d; 8002 8003 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8004 if (cdof) { 8005 PetscInt numConst = 0, foff = 0; 8006 8007 for (f = 0; f < numFields; ++f) { 8008 const PetscInt *fcind; 8009 PetscInt fdof, fcdof; 8010 8011 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8012 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8013 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 8014 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8015 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 8016 foff += fdof; 8017 numConst += fcdof; 8018 } 8019 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8020 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8021 } 8022 } 8023 ierr = PetscFree(indices);CHKERRQ(ierr); 8024 PetscFunctionReturn(0); 8025 } 8026 8027 #undef __FUNCT__ 8028 #define __FUNCT__ "DMPlexCreateSection" 8029 /*@C 8030 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8031 8032 Not Collective 8033 8034 Input Parameters: 8035 + dm - The DMPlex object 8036 . dim - The spatial dimension of the problem 8037 . numFields - The number of fields in the problem 8038 . numComp - An array of size numFields that holds the number of components for each field 8039 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8040 . numBC - The number of boundary conditions 8041 . bcField - An array of size numBC giving the field number for each boundry condition 8042 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8043 8044 Output Parameter: 8045 . section - The PetscSection object 8046 8047 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 8048 nubmer of dof for field 0 on each edge. 8049 8050 Level: developer 8051 8052 .keywords: mesh, elements 8053 .seealso: DMPlexCreate(), PetscSectionCreate() 8054 @*/ 8055 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8056 { 8057 PetscErrorCode ierr; 8058 8059 PetscFunctionBegin; 8060 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8061 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8062 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8063 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8064 { 8065 PetscBool view = PETSC_FALSE; 8066 8067 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8068 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8069 } 8070 PetscFunctionReturn(0); 8071 } 8072 8073 #undef __FUNCT__ 8074 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8075 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8076 { 8077 PetscSection section; 8078 PetscErrorCode ierr; 8079 8080 PetscFunctionBegin; 8081 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8082 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8083 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8084 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8085 PetscFunctionReturn(0); 8086 } 8087 8088 #undef __FUNCT__ 8089 #define __FUNCT__ "DMPlexGetCoordinateSection" 8090 /*@ 8091 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8092 8093 Not Collective 8094 8095 Input Parameter: 8096 . dm - The DMPlex object 8097 8098 Output Parameter: 8099 . section - The PetscSection object 8100 8101 Level: intermediate 8102 8103 .keywords: mesh, coordinates 8104 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8105 @*/ 8106 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8107 { 8108 DM cdm; 8109 PetscErrorCode ierr; 8110 8111 PetscFunctionBegin; 8112 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8113 PetscValidPointer(section, 2); 8114 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8115 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8116 PetscFunctionReturn(0); 8117 } 8118 8119 #undef __FUNCT__ 8120 #define __FUNCT__ "DMPlexSetCoordinateSection" 8121 /*@ 8122 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8123 8124 Not Collective 8125 8126 Input Parameters: 8127 + dm - The DMPlex object 8128 - section - The PetscSection object 8129 8130 Level: intermediate 8131 8132 .keywords: mesh, coordinates 8133 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8134 @*/ 8135 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8136 { 8137 DM cdm; 8138 PetscErrorCode ierr; 8139 8140 PetscFunctionBegin; 8141 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8142 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 8143 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8144 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8145 PetscFunctionReturn(0); 8146 } 8147 8148 #undef __FUNCT__ 8149 #define __FUNCT__ "DMPlexGetConeSection" 8150 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8151 { 8152 DM_Plex *mesh = (DM_Plex*) dm->data; 8153 8154 PetscFunctionBegin; 8155 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8156 if (section) *section = mesh->coneSection; 8157 PetscFunctionReturn(0); 8158 } 8159 8160 #undef __FUNCT__ 8161 #define __FUNCT__ "DMPlexGetCones" 8162 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8163 { 8164 DM_Plex *mesh = (DM_Plex*) dm->data; 8165 8166 PetscFunctionBegin; 8167 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8168 if (cones) *cones = mesh->cones; 8169 PetscFunctionReturn(0); 8170 } 8171 8172 #undef __FUNCT__ 8173 #define __FUNCT__ "DMPlexGetConeOrientations" 8174 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8175 { 8176 DM_Plex *mesh = (DM_Plex*) dm->data; 8177 8178 PetscFunctionBegin; 8179 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8180 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8181 PetscFunctionReturn(0); 8182 } 8183 8184 #undef __FUNCT__ 8185 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8186 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8187 { 8188 const PetscInt embedDim = 2; 8189 PetscReal x = PetscRealPart(point[0]); 8190 PetscReal y = PetscRealPart(point[1]); 8191 PetscReal v0[2], J[4], invJ[4], detJ; 8192 PetscReal xi, eta; 8193 PetscErrorCode ierr; 8194 8195 PetscFunctionBegin; 8196 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8197 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8198 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8199 8200 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8201 else *cell = -1; 8202 PetscFunctionReturn(0); 8203 } 8204 8205 #undef __FUNCT__ 8206 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8207 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8208 { 8209 PetscSection coordSection; 8210 Vec coordsLocal; 8211 const PetscScalar *coords; 8212 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8213 PetscReal x = PetscRealPart(point[0]); 8214 PetscReal y = PetscRealPart(point[1]); 8215 PetscInt crossings = 0, f; 8216 PetscErrorCode ierr; 8217 8218 PetscFunctionBegin; 8219 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8220 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8221 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8222 for (f = 0; f < 4; ++f) { 8223 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8224 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8225 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8226 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8227 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8228 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8229 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8230 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8231 if ((cond1 || cond2) && above) ++crossings; 8232 } 8233 if (crossings % 2) *cell = c; 8234 else *cell = -1; 8235 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8236 PetscFunctionReturn(0); 8237 } 8238 8239 #undef __FUNCT__ 8240 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8241 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8242 { 8243 const PetscInt embedDim = 3; 8244 PetscReal v0[3], J[9], invJ[9], detJ; 8245 PetscReal x = PetscRealPart(point[0]); 8246 PetscReal y = PetscRealPart(point[1]); 8247 PetscReal z = PetscRealPart(point[2]); 8248 PetscReal xi, eta, zeta; 8249 PetscErrorCode ierr; 8250 8251 PetscFunctionBegin; 8252 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8253 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8254 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8255 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8256 8257 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8258 else *cell = -1; 8259 PetscFunctionReturn(0); 8260 } 8261 8262 #undef __FUNCT__ 8263 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8264 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8265 { 8266 PetscSection coordSection; 8267 Vec coordsLocal; 8268 const PetscScalar *coords; 8269 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8270 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8271 PetscBool found = PETSC_TRUE; 8272 PetscInt f; 8273 PetscErrorCode ierr; 8274 8275 PetscFunctionBegin; 8276 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8277 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8278 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8279 for (f = 0; f < 6; ++f) { 8280 /* Check the point is under plane */ 8281 /* Get face normal */ 8282 PetscReal v_i[3]; 8283 PetscReal v_j[3]; 8284 PetscReal normal[3]; 8285 PetscReal pp[3]; 8286 PetscReal dot; 8287 8288 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8289 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8290 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8291 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8292 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8293 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8294 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8295 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8296 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8297 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8298 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8299 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8300 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8301 8302 /* Check that projected point is in face (2D location problem) */ 8303 if (dot < 0.0) { 8304 found = PETSC_FALSE; 8305 break; 8306 } 8307 } 8308 if (found) *cell = c; 8309 else *cell = -1; 8310 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8311 PetscFunctionReturn(0); 8312 } 8313 8314 #undef __FUNCT__ 8315 #define __FUNCT__ "DMLocatePoints_Plex" 8316 /* 8317 Need to implement using the guess 8318 */ 8319 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8320 { 8321 PetscInt cell = -1 /*, guess = -1*/; 8322 PetscInt bs, numPoints, p; 8323 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8324 PetscInt *cells; 8325 PetscScalar *a; 8326 PetscErrorCode ierr; 8327 8328 PetscFunctionBegin; 8329 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8330 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8331 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 8332 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8333 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8334 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8335 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8336 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); 8337 numPoints /= bs; 8338 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8339 for (p = 0; p < numPoints; ++p) { 8340 const PetscScalar *point = &a[p*bs]; 8341 8342 switch (dim) { 8343 case 2: 8344 for (c = cStart; c < cEnd; ++c) { 8345 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8346 switch (coneSize) { 8347 case 3: 8348 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8349 break; 8350 case 4: 8351 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8352 break; 8353 default: 8354 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8355 } 8356 if (cell >= 0) break; 8357 } 8358 break; 8359 case 3: 8360 for (c = cStart; c < cEnd; ++c) { 8361 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8362 switch (coneSize) { 8363 case 4: 8364 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8365 break; 8366 case 8: 8367 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8368 break; 8369 default: 8370 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8371 } 8372 if (cell >= 0) break; 8373 } 8374 break; 8375 default: 8376 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8377 } 8378 cells[p] = cell; 8379 } 8380 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8381 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8382 PetscFunctionReturn(0); 8383 } 8384 8385 /******************************** FEM Support **********************************/ 8386 8387 #undef __FUNCT__ 8388 #define __FUNCT__ "DMPlexVecGetClosure" 8389 /*@C 8390 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8391 8392 Not collective 8393 8394 Input Parameters: 8395 + dm - The DM 8396 . section - The section describing the layout in v, or NULL to use the default section 8397 . v - The local vector 8398 - point - The sieve point in the DM 8399 8400 Output Parameters: 8401 + csize - The number of values in the closure, or NULL 8402 - values - The array of values, which is a borrowed array and should not be freed 8403 8404 Level: intermediate 8405 8406 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8407 @*/ 8408 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8409 { 8410 PetscScalar *array, *vArray; 8411 PetscInt *points = NULL; 8412 PetscInt offsets[32]; 8413 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8414 PetscErrorCode ierr; 8415 8416 PetscFunctionBegin; 8417 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8418 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8419 if (!section) { 8420 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8421 } 8422 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8423 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8424 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8425 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8426 /* Compress out points not in the section */ 8427 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8428 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8429 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8430 points[q*2] = points[p]; 8431 points[q*2+1] = points[p+1]; 8432 ++q; 8433 } 8434 } 8435 numPoints = q; 8436 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8437 PetscInt dof, fdof; 8438 8439 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8440 for (f = 0; f < numFields; ++f) { 8441 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8442 offsets[f+1] += fdof; 8443 } 8444 size += dof; 8445 } 8446 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8447 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8448 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8449 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8450 for (p = 0; p < numPoints*2; p += 2) { 8451 PetscInt o = points[p+1]; 8452 PetscInt dof, off, d; 8453 PetscScalar *varr; 8454 8455 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8456 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8457 varr = &vArray[off]; 8458 if (numFields) { 8459 PetscInt fdof, foff, fcomp, f, c; 8460 8461 for (f = 0, foff = 0; f < numFields; ++f) { 8462 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8463 if (o >= 0) { 8464 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8465 array[offsets[f]] = varr[foff+d]; 8466 } 8467 } else { 8468 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8469 for (d = fdof/fcomp-1; d >= 0; --d) { 8470 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8471 array[offsets[f]] = varr[foff+d*fcomp+c]; 8472 } 8473 } 8474 } 8475 foff += fdof; 8476 } 8477 } else { 8478 if (o >= 0) { 8479 for (d = 0; d < dof; ++d, ++offsets[0]) { 8480 array[offsets[0]] = varr[d]; 8481 } 8482 } else { 8483 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8484 array[offsets[0]] = varr[d]; 8485 } 8486 } 8487 } 8488 } 8489 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8490 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8491 if (csize) *csize = size; 8492 *values = array; 8493 PetscFunctionReturn(0); 8494 } 8495 8496 #undef __FUNCT__ 8497 #define __FUNCT__ "DMPlexVecRestoreClosure" 8498 /*@C 8499 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8500 8501 Not collective 8502 8503 Input Parameters: 8504 + dm - The DM 8505 . section - The section describing the layout in v, or NULL to use the default section 8506 . v - The local vector 8507 . point - The sieve point in the DM 8508 . csize - The number of values in the closure, or NULL 8509 - values - The array of values, which is a borrowed array and should not be freed 8510 8511 Level: intermediate 8512 8513 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8514 @*/ 8515 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8516 { 8517 PetscInt size = 0; 8518 PetscErrorCode ierr; 8519 8520 PetscFunctionBegin; 8521 /* Should work without recalculating size */ 8522 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8523 PetscFunctionReturn(0); 8524 } 8525 8526 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8527 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8528 8529 #undef __FUNCT__ 8530 #define __FUNCT__ "updatePoint_private" 8531 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8532 { 8533 PetscInt cdof; /* The number of constraints on this point */ 8534 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8535 PetscScalar *a; 8536 PetscInt off, cind = 0, k; 8537 PetscErrorCode ierr; 8538 8539 PetscFunctionBegin; 8540 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8541 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8542 a = &array[off]; 8543 if (!cdof || setBC) { 8544 if (orientation >= 0) { 8545 for (k = 0; k < dof; ++k) { 8546 fuse(&a[k], values[k]); 8547 } 8548 } else { 8549 for (k = 0; k < dof; ++k) { 8550 fuse(&a[k], values[dof-k-1]); 8551 } 8552 } 8553 } else { 8554 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8555 if (orientation >= 0) { 8556 for (k = 0; k < dof; ++k) { 8557 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8558 fuse(&a[k], values[k]); 8559 } 8560 } else { 8561 for (k = 0; k < dof; ++k) { 8562 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8563 fuse(&a[k], values[dof-k-1]); 8564 } 8565 } 8566 } 8567 PetscFunctionReturn(0); 8568 } 8569 8570 #undef __FUNCT__ 8571 #define __FUNCT__ "updatePointFields_private" 8572 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8573 { 8574 PetscScalar *a; 8575 PetscInt numFields, off, foff, f; 8576 PetscErrorCode ierr; 8577 8578 PetscFunctionBegin; 8579 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8580 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8581 a = &array[off]; 8582 for (f = 0, foff = 0; f < numFields; ++f) { 8583 PetscInt fdof, fcomp, fcdof; 8584 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8585 PetscInt cind = 0, k, c; 8586 8587 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8588 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8589 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8590 if (!fcdof || setBC) { 8591 if (orientation >= 0) { 8592 for (k = 0; k < fdof; ++k) { 8593 fuse(&a[foff+k], values[foffs[f]+k]); 8594 } 8595 } else { 8596 for (k = fdof/fcomp-1; k >= 0; --k) { 8597 for (c = 0; c < fcomp; ++c) { 8598 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8599 } 8600 } 8601 } 8602 } else { 8603 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8604 if (orientation >= 0) { 8605 for (k = 0; k < fdof; ++k) { 8606 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8607 fuse(&a[foff+k], values[foffs[f]+k]); 8608 } 8609 } else { 8610 for (k = fdof/fcomp-1; k >= 0; --k) { 8611 for (c = 0; c < fcomp; ++c) { 8612 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8613 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8614 } 8615 } 8616 } 8617 } 8618 foff += fdof; 8619 foffs[f] += fdof; 8620 } 8621 PetscFunctionReturn(0); 8622 } 8623 8624 #undef __FUNCT__ 8625 #define __FUNCT__ "DMPlexVecSetClosure" 8626 /*@C 8627 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8628 8629 Not collective 8630 8631 Input Parameters: 8632 + dm - The DM 8633 . section - The section describing the layout in v, or NULL to use the default sectionw 8634 . v - The local vector 8635 . point - The sieve point in the DM 8636 . values - The array of values, which is a borrowed array and should not be freed 8637 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8638 8639 Level: intermediate 8640 8641 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8642 @*/ 8643 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8644 { 8645 PetscScalar *array; 8646 PetscInt *points = NULL; 8647 PetscInt offsets[32]; 8648 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8649 PetscErrorCode ierr; 8650 8651 PetscFunctionBegin; 8652 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8653 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8654 if (!section) { 8655 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8656 } 8657 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8658 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8659 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8660 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8661 /* Compress out points not in the section */ 8662 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8663 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8664 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8665 points[q*2] = points[p]; 8666 points[q*2+1] = points[p+1]; 8667 ++q; 8668 } 8669 } 8670 numPoints = q; 8671 for (p = 0; p < numPoints*2; p += 2) { 8672 PetscInt fdof; 8673 8674 for (f = 0; f < numFields; ++f) { 8675 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8676 offsets[f+1] += fdof; 8677 } 8678 } 8679 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8680 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8681 if (numFields) { 8682 switch (mode) { 8683 case INSERT_VALUES: 8684 for (p = 0; p < numPoints*2; p += 2) { 8685 PetscInt o = points[p+1]; 8686 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8687 } break; 8688 case INSERT_ALL_VALUES: 8689 for (p = 0; p < numPoints*2; p += 2) { 8690 PetscInt o = points[p+1]; 8691 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8692 } break; 8693 case ADD_VALUES: 8694 for (p = 0; p < numPoints*2; p += 2) { 8695 PetscInt o = points[p+1]; 8696 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8697 } break; 8698 case ADD_ALL_VALUES: 8699 for (p = 0; p < numPoints*2; p += 2) { 8700 PetscInt o = points[p+1]; 8701 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8702 } break; 8703 default: 8704 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8705 } 8706 } else { 8707 switch (mode) { 8708 case INSERT_VALUES: 8709 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8710 PetscInt o = points[p+1]; 8711 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8712 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8713 } break; 8714 case INSERT_ALL_VALUES: 8715 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8716 PetscInt o = points[p+1]; 8717 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8718 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8719 } break; 8720 case ADD_VALUES: 8721 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8722 PetscInt o = points[p+1]; 8723 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8724 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8725 } break; 8726 case ADD_ALL_VALUES: 8727 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8728 PetscInt o = points[p+1]; 8729 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8730 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8731 } break; 8732 default: 8733 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8734 } 8735 } 8736 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8737 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8738 PetscFunctionReturn(0); 8739 } 8740 8741 #undef __FUNCT__ 8742 #define __FUNCT__ "DMPlexPrintMatSetValues" 8743 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8744 { 8745 PetscMPIInt rank; 8746 PetscInt i, j; 8747 PetscErrorCode ierr; 8748 8749 PetscFunctionBegin; 8750 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8751 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8752 for (i = 0; i < numIndices; i++) { 8753 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8754 } 8755 for (i = 0; i < numIndices; i++) { 8756 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8757 for (j = 0; j < numIndices; j++) { 8758 #if defined(PETSC_USE_COMPLEX) 8759 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8760 #else 8761 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8762 #endif 8763 } 8764 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8765 } 8766 PetscFunctionReturn(0); 8767 } 8768 8769 #undef __FUNCT__ 8770 #define __FUNCT__ "indicesPoint_private" 8771 /* . off - The global offset of this point */ 8772 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8773 { 8774 PetscInt dof; /* The number of unknowns on this point */ 8775 PetscInt cdof; /* The number of constraints on this point */ 8776 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8777 PetscInt cind = 0, k; 8778 PetscErrorCode ierr; 8779 8780 PetscFunctionBegin; 8781 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8782 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8783 if (!cdof || setBC) { 8784 if (orientation >= 0) { 8785 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8786 } else { 8787 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8788 } 8789 } else { 8790 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8791 if (orientation >= 0) { 8792 for (k = 0; k < dof; ++k) { 8793 if ((cind < cdof) && (k == cdofs[cind])) { 8794 /* Insert check for returning constrained indices */ 8795 indices[*loff+k] = -(off+k+1); 8796 ++cind; 8797 } else { 8798 indices[*loff+k] = off+k-cind; 8799 } 8800 } 8801 } else { 8802 for (k = 0; k < dof; ++k) { 8803 if ((cind < cdof) && (k == cdofs[cind])) { 8804 /* Insert check for returning constrained indices */ 8805 indices[*loff+dof-k-1] = -(off+k+1); 8806 ++cind; 8807 } else { 8808 indices[*loff+dof-k-1] = off+k-cind; 8809 } 8810 } 8811 } 8812 } 8813 *loff += dof; 8814 PetscFunctionReturn(0); 8815 } 8816 8817 #undef __FUNCT__ 8818 #define __FUNCT__ "indicesPointFields_private" 8819 /* . off - The global offset of this point */ 8820 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8821 { 8822 PetscInt numFields, foff, f; 8823 PetscErrorCode ierr; 8824 8825 PetscFunctionBegin; 8826 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8827 for (f = 0, foff = 0; f < numFields; ++f) { 8828 PetscInt fdof, fcomp, cfdof; 8829 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8830 PetscInt cind = 0, k, c; 8831 8832 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8833 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8834 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8835 if (!cfdof || setBC) { 8836 if (orientation >= 0) { 8837 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8838 } else { 8839 for (k = fdof/fcomp-1; k >= 0; --k) { 8840 for (c = 0; c < fcomp; ++c) { 8841 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8842 } 8843 } 8844 } 8845 } else { 8846 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8847 if (orientation >= 0) { 8848 for (k = 0; k < fdof; ++k) { 8849 if ((cind < cfdof) && (k == fcdofs[cind])) { 8850 indices[foffs[f]+k] = -(off+foff+k+1); 8851 ++cind; 8852 } else { 8853 indices[foffs[f]+k] = off+foff+k-cind; 8854 } 8855 } 8856 } else { 8857 for (k = fdof/fcomp-1; k >= 0; --k) { 8858 for (c = 0; c < fcomp; ++c) { 8859 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8860 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8861 ++cind; 8862 } else { 8863 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8864 } 8865 } 8866 } 8867 } 8868 } 8869 foff += fdof - cfdof; 8870 foffs[f] += fdof; 8871 } 8872 PetscFunctionReturn(0); 8873 } 8874 8875 #undef __FUNCT__ 8876 #define __FUNCT__ "DMPlexMatSetClosure" 8877 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8878 { 8879 DM_Plex *mesh = (DM_Plex*) dm->data; 8880 PetscInt *points = NULL; 8881 PetscInt *indices; 8882 PetscInt offsets[32]; 8883 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8884 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8885 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8886 PetscErrorCode ierr; 8887 8888 PetscFunctionBegin; 8889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8890 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8891 if (useDefault) { 8892 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8893 } 8894 if (useGlobalDefault) { 8895 if (useDefault) { 8896 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8897 } else { 8898 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8899 } 8900 } 8901 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8902 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8903 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8904 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8905 /* Compress out points not in the section */ 8906 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8907 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8908 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8909 points[q*2] = points[p]; 8910 points[q*2+1] = points[p+1]; 8911 ++q; 8912 } 8913 } 8914 numPoints = q; 8915 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8916 PetscInt fdof; 8917 8918 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8919 for (f = 0; f < numFields; ++f) { 8920 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8921 offsets[f+1] += fdof; 8922 } 8923 numIndices += dof; 8924 } 8925 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8926 8927 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8928 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8929 if (numFields) { 8930 for (p = 0; p < numPoints*2; p += 2) { 8931 PetscInt o = points[p+1]; 8932 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8933 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8934 } 8935 } else { 8936 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8937 PetscInt o = points[p+1]; 8938 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8939 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8940 } 8941 } 8942 if (useGlobalDefault && !useDefault) { 8943 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8944 } 8945 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8946 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8947 if (ierr) { 8948 PetscMPIInt rank; 8949 PetscErrorCode ierr2; 8950 8951 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8952 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8953 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8954 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8955 CHKERRQ(ierr); 8956 } 8957 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8958 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8959 PetscFunctionReturn(0); 8960 } 8961 8962 #undef __FUNCT__ 8963 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8964 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8965 { 8966 PetscSection coordSection; 8967 Vec coordinates; 8968 const PetscScalar *coords; 8969 const PetscInt dim = 2; 8970 PetscInt d, f; 8971 PetscErrorCode ierr; 8972 8973 PetscFunctionBegin; 8974 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8975 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8976 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8977 if (v0) { 8978 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8979 } 8980 if (J) { 8981 for (d = 0; d < dim; d++) { 8982 for (f = 0; f < dim; f++) { 8983 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8984 } 8985 } 8986 *detJ = J[0]*J[3] - J[1]*J[2]; 8987 #if 0 8988 if (detJ < 0.0) { 8989 const PetscReal xLength = mesh->periodicity[0]; 8990 8991 if (xLength != 0.0) { 8992 PetscReal v0x = coords[0*dim+0]; 8993 8994 if (v0x == 0.0) v0x = v0[0] = xLength; 8995 for (f = 0; f < dim; f++) { 8996 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8997 8998 J[0*dim+f] = 0.5*(px - v0x); 8999 } 9000 } 9001 detJ = J[0]*J[3] - J[1]*J[2]; 9002 } 9003 #endif 9004 PetscLogFlops(8.0 + 3.0); 9005 } 9006 if (invJ) { 9007 const PetscReal invDet = 1.0/(*detJ); 9008 9009 invJ[0] = invDet*J[3]; 9010 invJ[1] = -invDet*J[1]; 9011 invJ[2] = -invDet*J[2]; 9012 invJ[3] = invDet*J[0]; 9013 PetscLogFlops(5.0); 9014 } 9015 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9016 PetscFunctionReturn(0); 9017 } 9018 9019 #undef __FUNCT__ 9020 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9021 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9022 { 9023 PetscSection coordSection; 9024 Vec coordinates; 9025 const PetscScalar *coords; 9026 const PetscInt dim = 2; 9027 PetscInt d, f; 9028 PetscErrorCode ierr; 9029 9030 PetscFunctionBegin; 9031 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9032 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9033 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9034 if (v0) { 9035 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9036 } 9037 if (J) { 9038 for (d = 0; d < dim; d++) { 9039 for (f = 0; f < dim; f++) { 9040 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9041 } 9042 } 9043 *detJ = J[0]*J[3] - J[1]*J[2]; 9044 PetscLogFlops(8.0 + 3.0); 9045 } 9046 if (invJ) { 9047 const PetscReal invDet = 1.0/(*detJ); 9048 9049 invJ[0] = invDet*J[3]; 9050 invJ[1] = -invDet*J[1]; 9051 invJ[2] = -invDet*J[2]; 9052 invJ[3] = invDet*J[0]; 9053 PetscLogFlops(5.0); 9054 } 9055 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9056 PetscFunctionReturn(0); 9057 } 9058 9059 #undef __FUNCT__ 9060 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9061 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9062 { 9063 PetscSection coordSection; 9064 Vec coordinates; 9065 const PetscScalar *coords; 9066 const PetscInt dim = 3; 9067 PetscInt d, f; 9068 PetscErrorCode ierr; 9069 9070 PetscFunctionBegin; 9071 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9072 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9073 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9074 if (v0) { 9075 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9076 } 9077 if (J) { 9078 for (d = 0; d < dim; d++) { 9079 for (f = 0; f < dim; f++) { 9080 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9081 } 9082 } 9083 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9084 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9085 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9086 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9087 PetscLogFlops(18.0 + 12.0); 9088 } 9089 if (invJ) { 9090 const PetscReal invDet = 1.0/(*detJ); 9091 9092 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9093 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9094 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9095 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9096 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9097 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9098 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9099 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9100 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9101 PetscLogFlops(37.0); 9102 } 9103 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9104 PetscFunctionReturn(0); 9105 } 9106 9107 #undef __FUNCT__ 9108 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9109 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9110 { 9111 PetscSection coordSection; 9112 Vec coordinates; 9113 const PetscScalar *coords; 9114 const PetscInt dim = 3; 9115 PetscInt d; 9116 PetscErrorCode ierr; 9117 9118 PetscFunctionBegin; 9119 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9120 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9121 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9122 if (v0) { 9123 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9124 } 9125 if (J) { 9126 for (d = 0; d < dim; d++) { 9127 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9128 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9129 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9130 } 9131 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9132 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9133 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9134 PetscLogFlops(18.0 + 12.0); 9135 } 9136 if (invJ) { 9137 const PetscReal invDet = -1.0/(*detJ); 9138 9139 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9140 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9141 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9142 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9143 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9144 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9145 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9146 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9147 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9148 PetscLogFlops(37.0); 9149 } 9150 *detJ *= 8.0; 9151 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9152 PetscFunctionReturn(0); 9153 } 9154 9155 #undef __FUNCT__ 9156 #define __FUNCT__ "DMPlexComputeCellGeometry" 9157 /*@C 9158 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9159 9160 Collective on DM 9161 9162 Input Arguments: 9163 + dm - the DM 9164 - cell - the cell 9165 9166 Output Arguments: 9167 + v0 - the translation part of this affine transform 9168 . J - the Jacobian of the transform to the reference element 9169 . invJ - the inverse of the Jacobian 9170 - detJ - the Jacobian determinant 9171 9172 Level: advanced 9173 9174 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9175 @*/ 9176 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9177 { 9178 PetscInt dim, coneSize; 9179 PetscErrorCode ierr; 9180 9181 PetscFunctionBegin; 9182 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9183 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9184 switch (dim) { 9185 case 2: 9186 switch (coneSize) { 9187 case 3: 9188 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9189 break; 9190 case 4: 9191 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9192 break; 9193 default: 9194 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9195 } 9196 break; 9197 case 3: 9198 switch (coneSize) { 9199 case 4: 9200 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9201 break; 9202 case 8: 9203 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9204 break; 9205 default: 9206 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9207 } 9208 break; 9209 default: 9210 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9211 } 9212 PetscFunctionReturn(0); 9213 } 9214 9215 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9216 { 9217 switch (i) { 9218 case 0: 9219 switch (j) { 9220 case 0: return 0; 9221 case 1: 9222 switch (k) { 9223 case 0: return 0; 9224 case 1: return 0; 9225 case 2: return 1; 9226 } 9227 case 2: 9228 switch (k) { 9229 case 0: return 0; 9230 case 1: return -1; 9231 case 2: return 0; 9232 } 9233 } 9234 case 1: 9235 switch (j) { 9236 case 0: 9237 switch (k) { 9238 case 0: return 0; 9239 case 1: return 0; 9240 case 2: return -1; 9241 } 9242 case 1: return 0; 9243 case 2: 9244 switch (k) { 9245 case 0: return 1; 9246 case 1: return 0; 9247 case 2: return 0; 9248 } 9249 } 9250 case 2: 9251 switch (j) { 9252 case 0: 9253 switch (k) { 9254 case 0: return 0; 9255 case 1: return 1; 9256 case 2: return 0; 9257 } 9258 case 1: 9259 switch (k) { 9260 case 0: return -1; 9261 case 1: return 0; 9262 case 2: return 0; 9263 } 9264 case 2: return 0; 9265 } 9266 } 9267 return 0; 9268 } 9269 9270 #undef __FUNCT__ 9271 #define __FUNCT__ "DMPlexCreateRigidBody" 9272 /*@C 9273 DMPlexCreateRigidBody - create rigid body modes from coordinates 9274 9275 Collective on DM 9276 9277 Input Arguments: 9278 + dm - the DM 9279 . section - the local section associated with the rigid field, or NULL for the default section 9280 - globalSection - the global section associated with the rigid field, or NULL for the default section 9281 9282 Output Argument: 9283 . sp - the null space 9284 9285 Note: This is necessary to take account of Dirichlet conditions on the displacements 9286 9287 Level: advanced 9288 9289 .seealso: MatNullSpaceCreate() 9290 @*/ 9291 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9292 { 9293 MPI_Comm comm; 9294 Vec coordinates, localMode, mode[6]; 9295 PetscSection coordSection; 9296 PetscScalar *coords; 9297 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9298 PetscErrorCode ierr; 9299 9300 PetscFunctionBegin; 9301 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 9302 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9303 if (dim == 1) { 9304 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 9305 PetscFunctionReturn(0); 9306 } 9307 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9308 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9309 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9310 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9311 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9312 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9313 m = (dim*(dim+1))/2; 9314 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9315 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9316 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9317 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9318 /* Assume P1 */ 9319 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9320 for (d = 0; d < dim; ++d) { 9321 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9322 9323 values[d] = 1.0; 9324 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9325 for (v = vStart; v < vEnd; ++v) { 9326 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9327 } 9328 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9329 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9330 } 9331 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9332 for (d = dim; d < dim*(dim+1)/2; ++d) { 9333 PetscInt i, j, k = dim > 2 ? d - dim : d; 9334 9335 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9336 for (v = vStart; v < vEnd; ++v) { 9337 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9338 PetscInt off; 9339 9340 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9341 for (i = 0; i < dim; ++i) { 9342 for (j = 0; j < dim; ++j) { 9343 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9344 } 9345 } 9346 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9347 } 9348 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9349 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9350 } 9351 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9352 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9353 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 9354 /* Orthonormalize system */ 9355 for (i = dim; i < m; ++i) { 9356 PetscScalar dots[6]; 9357 9358 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9359 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9360 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9361 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 9362 } 9363 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9364 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9365 PetscFunctionReturn(0); 9366 } 9367 9368 #undef __FUNCT__ 9369 #define __FUNCT__ "DMPlexGetHybridBounds" 9370 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9371 { 9372 DM_Plex *mesh = (DM_Plex*) dm->data; 9373 PetscInt dim; 9374 PetscErrorCode ierr; 9375 9376 PetscFunctionBegin; 9377 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9378 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9379 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9380 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9381 if (eMax) *eMax = mesh->hybridPointMax[1]; 9382 if (vMax) *vMax = mesh->hybridPointMax[0]; 9383 PetscFunctionReturn(0); 9384 } 9385 9386 #undef __FUNCT__ 9387 #define __FUNCT__ "DMPlexSetHybridBounds" 9388 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9389 { 9390 DM_Plex *mesh = (DM_Plex*) dm->data; 9391 PetscInt dim; 9392 PetscErrorCode ierr; 9393 9394 PetscFunctionBegin; 9395 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9396 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9397 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9398 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9399 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9400 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9401 PetscFunctionReturn(0); 9402 } 9403 9404 #undef __FUNCT__ 9405 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9406 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9407 { 9408 DM_Plex *mesh = (DM_Plex*) dm->data; 9409 9410 PetscFunctionBegin; 9411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9412 PetscValidPointer(cellHeight, 2); 9413 *cellHeight = mesh->vtkCellHeight; 9414 PetscFunctionReturn(0); 9415 } 9416 9417 #undef __FUNCT__ 9418 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9419 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9420 { 9421 DM_Plex *mesh = (DM_Plex*) dm->data; 9422 9423 PetscFunctionBegin; 9424 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9425 mesh->vtkCellHeight = cellHeight; 9426 PetscFunctionReturn(0); 9427 } 9428 9429 #undef __FUNCT__ 9430 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9431 /* We can easily have a form that takes an IS instead */ 9432 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9433 { 9434 PetscSection section, globalSection; 9435 PetscInt *numbers, p; 9436 PetscErrorCode ierr; 9437 9438 PetscFunctionBegin; 9439 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 9440 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9441 for (p = pStart; p < pEnd; ++p) { 9442 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9443 } 9444 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9445 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9446 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9447 for (p = pStart; p < pEnd; ++p) { 9448 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9449 } 9450 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9451 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9452 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9453 PetscFunctionReturn(0); 9454 } 9455 9456 #undef __FUNCT__ 9457 #define __FUNCT__ "DMPlexGetCellNumbering" 9458 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9459 { 9460 DM_Plex *mesh = (DM_Plex*) dm->data; 9461 PetscInt cellHeight, cStart, cEnd, cMax; 9462 PetscErrorCode ierr; 9463 9464 PetscFunctionBegin; 9465 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9466 if (!mesh->globalCellNumbers) { 9467 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9468 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9469 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 9470 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9471 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9472 } 9473 *globalCellNumbers = mesh->globalCellNumbers; 9474 PetscFunctionReturn(0); 9475 } 9476 9477 #undef __FUNCT__ 9478 #define __FUNCT__ "DMPlexGetVertexNumbering" 9479 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9480 { 9481 DM_Plex *mesh = (DM_Plex*) dm->data; 9482 PetscInt vStart, vEnd, vMax; 9483 PetscErrorCode ierr; 9484 9485 PetscFunctionBegin; 9486 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9487 if (!mesh->globalVertexNumbers) { 9488 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9489 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9490 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9491 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9492 } 9493 *globalVertexNumbers = mesh->globalVertexNumbers; 9494 PetscFunctionReturn(0); 9495 } 9496 9497 #undef __FUNCT__ 9498 #define __FUNCT__ "DMPlexGetScale" 9499 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9500 { 9501 DM_Plex *mesh = (DM_Plex*) dm->data; 9502 9503 PetscFunctionBegin; 9504 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9505 PetscValidPointer(scale, 3); 9506 *scale = mesh->scale[unit]; 9507 PetscFunctionReturn(0); 9508 } 9509 9510 #undef __FUNCT__ 9511 #define __FUNCT__ "DMPlexSetScale" 9512 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9513 { 9514 DM_Plex *mesh = (DM_Plex*) dm->data; 9515 9516 PetscFunctionBegin; 9517 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9518 mesh->scale[unit] = scale; 9519 PetscFunctionReturn(0); 9520 } 9521 9522 9523 /******************************************************************************* 9524 This should be in a separate Discretization object, but I am not sure how to lay 9525 it out yet, so I am stuffing things here while I experiment. 9526 *******************************************************************************/ 9527 #undef __FUNCT__ 9528 #define __FUNCT__ "DMPlexSetFEMIntegration" 9529 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9530 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9531 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9532 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9533 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9534 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9535 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9536 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9537 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9538 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9539 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9540 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9541 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9542 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9543 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9544 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9545 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9546 { 9547 DM_Plex *mesh = (DM_Plex*) dm->data; 9548 9549 PetscFunctionBegin; 9550 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9551 mesh->integrateResidualFEM = integrateResidualFEM; 9552 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9553 mesh->integrateJacobianFEM = integrateJacobianFEM; 9554 PetscFunctionReturn(0); 9555 } 9556 9557 #undef __FUNCT__ 9558 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9559 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9560 { 9561 Vec coordinates; 9562 PetscSection section, cSection; 9563 PetscInt dim, vStart, vEnd, v, c, d; 9564 PetscScalar *values, *cArray; 9565 PetscReal *coords; 9566 PetscErrorCode ierr; 9567 9568 PetscFunctionBegin; 9569 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9570 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9571 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9572 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9573 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9574 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9575 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9576 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9577 for (v = vStart; v < vEnd; ++v) { 9578 PetscInt dof, off; 9579 9580 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9581 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9582 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9583 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9584 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9585 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9586 } 9587 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9588 /* Temporary, must be replaced by a projection on the finite element basis */ 9589 { 9590 PetscInt eStart = 0, eEnd = 0, e, depth; 9591 9592 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9593 --depth; 9594 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9595 for (e = eStart; e < eEnd; ++e) { 9596 const PetscInt *cone = NULL; 9597 PetscInt coneSize, d; 9598 PetscScalar *coordsA, *coordsB; 9599 9600 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9601 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9602 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9603 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9604 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9605 for (d = 0; d < dim; ++d) { 9606 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9607 } 9608 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9609 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9610 } 9611 } 9612 9613 ierr = PetscFree(coords);CHKERRQ(ierr); 9614 ierr = PetscFree(values);CHKERRQ(ierr); 9615 #if 0 9616 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9617 PetscReal detJ; 9618 9619 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9620 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9621 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9622 9623 for (PetscInt c = cStart; c < cEnd; ++c) { 9624 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9625 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9626 const int oSize = pV.getSize(); 9627 int v = 0; 9628 9629 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9630 for (PetscInt cl = 0; cl < oSize; ++cl) { 9631 const PetscInt fDim; 9632 9633 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9634 if (pointDim) { 9635 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9636 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9637 } 9638 } 9639 } 9640 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9641 pV.clear(); 9642 } 9643 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9644 ierr = PetscFree(values);CHKERRQ(ierr); 9645 #endif 9646 PetscFunctionReturn(0); 9647 } 9648 9649 #undef __FUNCT__ 9650 #define __FUNCT__ "DMPlexProjectFunction" 9651 /*@C 9652 DMPlexProjectFunction - This projects the given function into the function space provided. 9653 9654 Input Parameters: 9655 + dm - The DM 9656 . numComp - The number of components (functions) 9657 . funcs - The coordinate functions to evaluate 9658 - mode - The insertion mode for values 9659 9660 Output Parameter: 9661 . X - vector 9662 9663 Level: developer 9664 9665 Note: 9666 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9667 We will eventually fix it. 9668 9669 ,seealso: DMPlexComputeL2Diff() 9670 */ 9671 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9672 { 9673 Vec localX; 9674 PetscErrorCode ierr; 9675 9676 PetscFunctionBegin; 9677 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9678 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9679 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9680 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9681 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9682 PetscFunctionReturn(0); 9683 } 9684 9685 #undef __FUNCT__ 9686 #define __FUNCT__ "DMPlexComputeL2Diff" 9687 /*@C 9688 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9689 9690 Input Parameters: 9691 + dm - The DM 9692 . quad - The PetscQuadrature object for each field 9693 . funcs - The functions to evaluate for each field component 9694 - X - The coefficient vector u_h 9695 9696 Output Parameter: 9697 . diff - The diff ||u - u_h||_2 9698 9699 Level: developer 9700 9701 .seealso: DMPlexProjectFunction() 9702 */ 9703 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9704 { 9705 const PetscInt debug = 0; 9706 PetscSection section; 9707 Vec localX; 9708 PetscReal *coords, *v0, *J, *invJ, detJ; 9709 PetscReal localDiff = 0.0; 9710 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9711 PetscErrorCode ierr; 9712 9713 PetscFunctionBegin; 9714 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9715 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9716 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9717 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9718 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9719 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9720 for (field = 0; field < numFields; ++field) { 9721 numComponents += quad[field].numComponents; 9722 } 9723 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9724 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9725 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9726 for (c = cStart; c < cEnd; ++c) { 9727 const PetscScalar *x; 9728 PetscReal elemDiff = 0.0; 9729 9730 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9731 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9732 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9733 9734 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9735 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9736 const PetscReal *quadPoints = quad[field].quadPoints; 9737 const PetscReal *quadWeights = quad[field].quadWeights; 9738 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9739 const PetscInt numBasisComps = quad[field].numComponents; 9740 const PetscReal *basis = quad[field].basis; 9741 PetscInt q, d, e, fc, f; 9742 9743 if (debug) { 9744 char title[1024]; 9745 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9746 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9747 } 9748 for (q = 0; q < numQuadPoints; ++q) { 9749 for (d = 0; d < dim; d++) { 9750 coords[d] = v0[d]; 9751 for (e = 0; e < dim; e++) { 9752 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9753 } 9754 } 9755 for (fc = 0; fc < numBasisComps; ++fc) { 9756 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9757 PetscReal interpolant = 0.0; 9758 for (f = 0; f < numBasisFuncs; ++f) { 9759 const PetscInt fidx = f*numBasisComps+fc; 9760 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9761 } 9762 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9763 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9764 } 9765 } 9766 comp += numBasisComps; 9767 fieldOffset += numBasisFuncs*numBasisComps; 9768 } 9769 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9770 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9771 localDiff += elemDiff; 9772 } 9773 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9774 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9775 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9776 *diff = PetscSqrtReal(*diff); 9777 PetscFunctionReturn(0); 9778 } 9779 9780 #undef __FUNCT__ 9781 #define __FUNCT__ "DMPlexComputeResidualFEM" 9782 /*@ 9783 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9784 9785 Input Parameters: 9786 + dm - The mesh 9787 . X - Local input vector 9788 - user - The user context 9789 9790 Output Parameter: 9791 . F - Local output vector 9792 9793 Note: 9794 The second member of the user context must be an FEMContext. 9795 9796 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9797 like a GPU, or vectorize on a multicore machine. 9798 9799 .seealso: DMPlexComputeJacobianActionFEM() 9800 */ 9801 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9802 { 9803 DM_Plex *mesh = (DM_Plex*) dm->data; 9804 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9805 PetscQuadrature *quad = fem->quad; 9806 PetscSection section; 9807 PetscReal *v0, *J, *invJ, *detJ; 9808 PetscScalar *elemVec, *u; 9809 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9810 PetscInt cellDof = 0, numComponents = 0; 9811 PetscErrorCode ierr; 9812 9813 PetscFunctionBegin; 9814 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9815 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9816 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9817 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9818 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9819 numCells = cEnd - cStart; 9820 for (field = 0; field < numFields; ++field) { 9821 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9822 numComponents += quad[field].numComponents; 9823 } 9824 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9825 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9826 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); 9827 for (c = cStart; c < cEnd; ++c) { 9828 const PetscScalar *x; 9829 PetscInt i; 9830 9831 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9832 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9833 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9834 9835 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9836 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9837 } 9838 for (field = 0; field < numFields; ++field) { 9839 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9840 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9841 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9842 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9843 /* Conforming batches */ 9844 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9845 PetscInt numBlocks = 1; 9846 PetscInt batchSize = numBlocks * blockSize; 9847 PetscInt numBatches = numBatchesTmp; 9848 PetscInt numChunks = numCells / (numBatches*batchSize); 9849 /* Remainder */ 9850 PetscInt numRemainder = numCells % (numBatches * batchSize); 9851 PetscInt offset = numCells - numRemainder; 9852 9853 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9854 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9855 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9856 } 9857 for (c = cStart; c < cEnd; ++c) { 9858 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9859 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9860 } 9861 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9862 if (mesh->printFEM) { 9863 PetscMPIInt rank, numProcs; 9864 PetscInt p; 9865 9866 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9867 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9868 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9869 for (p = 0; p < numProcs; ++p) { 9870 if (p == rank) { 9871 Vec f; 9872 9873 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9874 ierr = VecCopy(F, f);CHKERRQ(ierr); 9875 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9876 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9877 ierr = VecDestroy(&f);CHKERRQ(ierr); 9878 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9879 } 9880 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9881 } 9882 } 9883 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9884 PetscFunctionReturn(0); 9885 } 9886 9887 #undef __FUNCT__ 9888 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9889 /*@C 9890 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9891 9892 Input Parameters: 9893 + dm - The mesh 9894 . J - The Jacobian shell matrix 9895 . X - Local input vector 9896 - user - The user context 9897 9898 Output Parameter: 9899 . F - Local output vector 9900 9901 Note: 9902 The second member of the user context must be an FEMContext. 9903 9904 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9905 like a GPU, or vectorize on a multicore machine. 9906 9907 .seealso: DMPlexComputeResidualFEM() 9908 */ 9909 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9910 { 9911 DM_Plex *mesh = (DM_Plex*) dm->data; 9912 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9913 PetscQuadrature *quad = fem->quad; 9914 PetscSection section; 9915 JacActionCtx *jctx; 9916 PetscReal *v0, *J, *invJ, *detJ; 9917 PetscScalar *elemVec, *u, *a; 9918 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9919 PetscInt cellDof = 0; 9920 PetscErrorCode ierr; 9921 9922 PetscFunctionBegin; 9923 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9924 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9925 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9926 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9927 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9928 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9929 numCells = cEnd - cStart; 9930 for (field = 0; field < numFields; ++field) { 9931 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9932 } 9933 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9934 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); 9935 for (c = cStart; c < cEnd; ++c) { 9936 const PetscScalar *x; 9937 PetscInt i; 9938 9939 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9940 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9941 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9942 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9943 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9944 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9945 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9946 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9947 } 9948 for (field = 0; field < numFields; ++field) { 9949 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9950 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9951 /* Conforming batches */ 9952 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9953 PetscInt numBlocks = 1; 9954 PetscInt batchSize = numBlocks * blockSize; 9955 PetscInt numBatches = numBatchesTmp; 9956 PetscInt numChunks = numCells / (numBatches*batchSize); 9957 /* Remainder */ 9958 PetscInt numRemainder = numCells % (numBatches * batchSize); 9959 PetscInt offset = numCells - numRemainder; 9960 9961 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); 9962 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], 9963 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9964 } 9965 for (c = cStart; c < cEnd; ++c) { 9966 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9967 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9968 } 9969 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9970 if (mesh->printFEM) { 9971 PetscMPIInt rank, numProcs; 9972 PetscInt p; 9973 9974 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9975 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9976 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9977 for (p = 0; p < numProcs; ++p) { 9978 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9979 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9980 } 9981 } 9982 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9983 PetscFunctionReturn(0); 9984 } 9985 9986 #undef __FUNCT__ 9987 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9988 /*@ 9989 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9990 9991 Input Parameters: 9992 + dm - The mesh 9993 . X - Local input vector 9994 - user - The user context 9995 9996 Output Parameter: 9997 . Jac - Jacobian matrix 9998 9999 Note: 10000 The second member of the user context must be an FEMContext. 10001 10002 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10003 like a GPU, or vectorize on a multicore machine. 10004 10005 .seealso: FormFunctionLocal() 10006 */ 10007 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10008 { 10009 DM_Plex *mesh = (DM_Plex*) dm->data; 10010 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10011 PetscQuadrature *quad = fem->quad; 10012 PetscSection section; 10013 PetscReal *v0, *J, *invJ, *detJ; 10014 PetscScalar *elemMat, *u; 10015 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10016 PetscInt cellDof = 0, numComponents = 0; 10017 PetscBool isShell; 10018 PetscErrorCode ierr; 10019 10020 PetscFunctionBegin; 10021 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10022 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10023 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10024 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10025 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10026 numCells = cEnd - cStart; 10027 for (field = 0; field < numFields; ++field) { 10028 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10029 numComponents += quad[field].numComponents; 10030 } 10031 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10032 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10033 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); 10034 for (c = cStart; c < cEnd; ++c) { 10035 const PetscScalar *x; 10036 PetscInt i; 10037 10038 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10039 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10040 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 10041 10042 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10043 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 10044 } 10045 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10046 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10047 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10048 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10049 PetscInt fieldJ; 10050 10051 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10052 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10053 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10054 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10055 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10056 /* Conforming batches */ 10057 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10058 PetscInt numBlocks = 1; 10059 PetscInt batchSize = numBlocks * blockSize; 10060 PetscInt numBatches = numBatchesTmp; 10061 PetscInt numChunks = numCells / (numBatches*batchSize); 10062 /* Remainder */ 10063 PetscInt numRemainder = numCells % (numBatches * batchSize); 10064 PetscInt offset = numCells - numRemainder; 10065 10066 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10067 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10068 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10069 } 10070 } 10071 for (c = cStart; c < cEnd; ++c) { 10072 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10073 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10074 } 10075 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10076 10077 /* Assemble matrix, using the 2-step process: 10078 MatAssemblyBegin(), MatAssemblyEnd(). */ 10079 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10080 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10081 10082 if (mesh->printFEM) { 10083 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10084 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10085 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10086 } 10087 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10088 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10089 if (isShell) { 10090 JacActionCtx *jctx; 10091 10092 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10093 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10094 } 10095 *str = SAME_NONZERO_PATTERN; 10096 PetscFunctionReturn(0); 10097 } 10098 10099 10100 #undef __FUNCT__ 10101 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10102 /*@C 10103 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10104 the local section and an SF describing the section point overlap. 10105 10106 Input Parameters: 10107 + s - The PetscSection for the local field layout 10108 . sf - The SF describing parallel layout of the section points 10109 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10110 . label - The label specifying the points 10111 - labelValue - The label stratum specifying the points 10112 10113 Output Parameter: 10114 . gsection - The PetscSection for the global field layout 10115 10116 Note: This gives negative sizes and offsets to points not owned by this process 10117 10118 Level: developer 10119 10120 .seealso: PetscSectionCreate() 10121 @*/ 10122 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10123 { 10124 PetscInt *neg; 10125 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10126 PetscErrorCode ierr; 10127 10128 PetscFunctionBegin; 10129 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10130 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10131 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10132 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10133 /* Mark ghost points with negative dof */ 10134 for (p = pStart; p < pEnd; ++p) { 10135 PetscInt value; 10136 10137 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10138 if (value != labelValue) continue; 10139 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10140 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10141 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10142 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10143 neg[p-pStart] = -(dof+1); 10144 } 10145 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10146 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 10147 if (nroots >= 0) { 10148 if (nroots > pEnd - pStart) { 10149 PetscInt *tmpDof; 10150 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10151 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10152 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10153 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10154 for (p = pStart; p < pEnd; ++p) { 10155 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 10156 } 10157 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10158 } else { 10159 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10160 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10161 } 10162 } 10163 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10164 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10165 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10166 10167 (*gsection)->atlasOff[p] = off; 10168 10169 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10170 } 10171 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10172 globalOff -= off; 10173 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10174 (*gsection)->atlasOff[p] += globalOff; 10175 10176 neg[p] = -((*gsection)->atlasOff[p]+1); 10177 } 10178 /* Put in negative offsets for ghost points */ 10179 if (nroots >= 0) { 10180 if (nroots > pEnd - pStart) { 10181 PetscInt *tmpOff; 10182 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10183 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10184 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10185 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10186 for (p = pStart; p < pEnd; ++p) { 10187 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 10188 } 10189 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10190 } else { 10191 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10192 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10193 } 10194 } 10195 ierr = PetscFree(neg);CHKERRQ(ierr); 10196 PetscFunctionReturn(0); 10197 } 10198