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