1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/vecimpl.h> 4 #include <petsc-private/isimpl.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 8 9 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "VecView_Plex_Local" 14 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 15 { 16 DM dm; 17 PetscBool isvtk; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 22 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 23 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 24 if (isvtk) { 25 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 26 PetscSection section; 27 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 28 29 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 30 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 33 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 34 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 35 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 36 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 37 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 38 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 39 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 40 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 41 } else if (cdof && vdof) { 42 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 43 } else if (cdof) { 44 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 45 * vector or just happens to have the same number of dofs as the dimension. */ 46 if (cdof == dim) { 47 ft = PETSC_VTK_CELL_VECTOR_FIELD; 48 } else { 49 ft = PETSC_VTK_CELL_FIELD; 50 } 51 } else if (vdof) { 52 if (vdof == dim) { 53 ft = PETSC_VTK_POINT_VECTOR_FIELD; 54 } else { 55 ft = PETSC_VTK_POINT_FIELD; 56 } 57 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 58 59 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 61 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 62 } else { 63 PetscBool isseq; 64 65 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 66 if (isseq) { 67 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 68 } else { 69 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "VecView_Plex" 77 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 78 { 79 DM dm; 80 PetscBool isvtk; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 85 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 86 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 87 if (isvtk) { 88 Vec locv; 89 const char *name; 90 91 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 92 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 93 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 96 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 97 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 98 } else { 99 PetscBool isseq; 100 101 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 102 if (isseq) { 103 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 104 } else { 105 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexView_Ascii" 113 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 114 { 115 DM_Plex *mesh = (DM_Plex*) dm->data; 116 DM cdm; 117 DMLabel markers; 118 PetscSection coordSection; 119 Vec coordinates; 120 PetscViewerFormat format; 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 125 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 126 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 127 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 128 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 129 const char *name; 130 PetscInt maxConeSize, maxSupportSize; 131 PetscInt pStart, pEnd, p; 132 PetscMPIInt rank, size; 133 134 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 135 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 136 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 137 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 138 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 143 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 144 for (p = pStart; p < pEnd; ++p) { 145 PetscInt dof, off, s; 146 147 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 148 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 149 for (s = off; s < off+dof; ++s) { 150 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 151 } 152 } 153 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 154 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 155 for (p = pStart; p < pEnd; ++p) { 156 PetscInt dof, off, c; 157 158 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 159 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 160 for (c = off; c < off+dof; ++c) { 161 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 162 } 163 } 164 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 165 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 166 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 167 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 168 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for (c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 284 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 285 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 286 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 287 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 288 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 289 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 290 if (depth == 1) { 291 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 292 pEnd = pEnd - pStart; 293 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 294 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 295 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 296 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 297 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 298 pEnd = pEnd - pStart; 299 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 300 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 301 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 302 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 303 } else { 304 for (d = 0; d <= dim; d++) { 305 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 306 pEnd = pEnd - pStart; 307 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 308 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 309 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 310 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 311 } 312 } 313 ierr = PetscFree(sizes);CHKERRQ(ierr); 314 } 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "DMView_Plex" 320 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 321 { 322 PetscBool iascii, isbinary; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 327 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 330 if (iascii) { 331 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 332 #if 0 333 } else if (isbinary) { 334 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 335 #endif 336 } 337 PetscFunctionReturn(0); 338 } 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "DMDestroy_Plex" 342 PetscErrorCode DMDestroy_Plex(DM dm) 343 { 344 DM_Plex *mesh = (DM_Plex*) dm->data; 345 DMLabel next = mesh->labels; 346 PetscErrorCode ierr; 347 348 PetscFunctionBegin; 349 if (--mesh->refct > 0) PetscFunctionReturn(0); 350 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 353 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 355 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 356 while (next) { 357 DMLabel tmp = next->next; 358 359 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 360 next = tmp; 361 } 362 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 364 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 365 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 366 ierr = PetscFree(mesh);CHKERRQ(ierr); 367 PetscFunctionReturn(0); 368 } 369 370 #undef __FUNCT__ 371 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 372 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 373 { 374 const PetscInt *support = NULL; 375 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 376 PetscErrorCode ierr; 377 378 PetscFunctionBegin; 379 if (useClosure) { 380 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 381 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 382 for (s = 0; s < supportSize; ++s) { 383 const PetscInt *cone = NULL; 384 PetscInt coneSize, c, q; 385 386 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 387 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 388 for (c = 0; c < coneSize; ++c) { 389 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 390 if (cone[c] == adj[q]) break; 391 } 392 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 393 } 394 } 395 } else { 396 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 397 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 398 for (s = 0; s < supportSize; ++s) { 399 const PetscInt *cone = NULL; 400 PetscInt coneSize, c, q; 401 402 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 403 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 404 for (c = 0; c < coneSize; ++c) { 405 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 406 if (cone[c] == adj[q]) break; 407 } 408 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 409 } 410 } 411 } 412 *adjSize = numAdj; 413 PetscFunctionReturn(0); 414 } 415 416 #undef __FUNCT__ 417 #define __FUNCT__ "DMPlexGetAdjacency_Private" 418 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 419 { 420 const PetscInt *star = tmpClosure; 421 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 422 PetscErrorCode ierr; 423 424 PetscFunctionBegin; 425 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 426 for (s = 2; s < starSize*2; s += 2) { 427 const PetscInt *closure = NULL; 428 PetscInt closureSize, c, q; 429 430 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 431 for (c = 0; c < closureSize*2; c += 2) { 432 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 433 if (closure[c] == adj[q]) break; 434 } 435 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 436 } 437 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 438 } 439 *adjSize = numAdj; 440 PetscFunctionReturn(0); 441 } 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 445 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 446 { 447 DM_Plex *mesh = (DM_Plex*) dm->data; 448 449 PetscFunctionBegin; 450 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 451 mesh->preallocCenterDim = preallocCenterDim; 452 PetscFunctionReturn(0); 453 } 454 455 #undef __FUNCT__ 456 #define __FUNCT__ "DMPlexPreallocateOperator" 457 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 458 { 459 DM_Plex *mesh = (DM_Plex*) dm->data; 460 MPI_Comm comm; 461 PetscSF sf, sfDof, sfAdj; 462 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 463 PetscInt nleaves, l, p; 464 const PetscInt *leaves; 465 const PetscSFNode *remotes; 466 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 467 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 468 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 469 PetscLayout rLayout; 470 PetscInt locRows, rStart, rEnd, r; 471 PetscMPIInt size; 472 PetscBool useClosure, debug = PETSC_FALSE; 473 PetscErrorCode ierr; 474 475 PetscFunctionBegin; 476 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 477 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 478 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 479 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 480 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 481 /* Create dof SF based on point SF */ 482 if (debug) { 483 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 487 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 488 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 489 } 490 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 491 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 492 if (debug) { 493 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 494 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 495 } 496 /* Create section for dof adjacency (dof ==> # adj dof) */ 497 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 498 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 499 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 500 if (mesh->preallocCenterDim == dim) { 501 useClosure = PETSC_FALSE; 502 } else if (mesh->preallocCenterDim == 0) { 503 useClosure = PETSC_TRUE; 504 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 505 506 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 507 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 510 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 511 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 512 /* Fill in the ghost dofs on the interface */ 513 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 514 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 515 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 516 517 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 518 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 519 520 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 521 522 /* 523 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 524 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 525 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 526 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 527 Create sfAdj connecting rootSectionAdj and leafSectionAdj 528 3. Visit unowned points on interface, write adjacencies to adj 529 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 530 4. Visit owned points on interface, write adjacencies to rootAdj 531 Remove redundancy in rootAdj 532 ** The last two traversals use transitive closure 533 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 534 Allocate memory addressed by sectionAdj (cols) 535 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 536 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 537 */ 538 539 for (l = 0; l < nleaves; ++l) { 540 PetscInt dof, off, d, q; 541 PetscInt p = leaves[l], numAdj = maxAdjSize; 542 543 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 544 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 545 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 546 for (q = 0; q < numAdj; ++q) { 547 const PetscInt padj = tmpAdj[q]; 548 PetscInt ndof, ncdof; 549 550 if ((padj < pStart) || (padj >= pEnd)) continue; 551 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 552 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 553 for (d = off; d < off+dof; ++d) { 554 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 555 } 556 } 557 } 558 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 559 if (debug) { 560 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 561 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 562 } 563 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 564 if (size > 1) { 565 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 566 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 567 } 568 if (debug) { 569 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 570 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 571 } 572 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 573 for (p = pStart; p < pEnd; ++p) { 574 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 575 576 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 577 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 578 if (!dof) continue; 579 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 580 if (adof <= 0) continue; 581 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 582 for (q = 0; q < numAdj; ++q) { 583 const PetscInt padj = tmpAdj[q]; 584 PetscInt ndof, ncdof; 585 586 if ((padj < pStart) || (padj >= pEnd)) continue; 587 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 588 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 589 for (d = off; d < off+dof; ++d) { 590 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 591 } 592 } 593 } 594 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 595 if (debug) { 596 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 597 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 598 } 599 /* Create adj SF based on dof SF */ 600 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 601 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 602 if (debug) { 603 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 604 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 605 } 606 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 607 /* Create leaf adjacency */ 608 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 609 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 610 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 611 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 612 for (l = 0; l < nleaves; ++l) { 613 PetscInt dof, off, d, q; 614 PetscInt p = leaves[l], numAdj = maxAdjSize; 615 616 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 617 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 618 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 619 for (d = off; d < off+dof; ++d) { 620 PetscInt aoff, i = 0; 621 622 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 623 for (q = 0; q < numAdj; ++q) { 624 const PetscInt padj = tmpAdj[q]; 625 PetscInt ndof, ncdof, ngoff, nd; 626 627 if ((padj < pStart) || (padj >= pEnd)) continue; 628 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 629 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 630 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 631 for (nd = 0; nd < ndof-ncdof; ++nd) { 632 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 633 ++i; 634 } 635 } 636 } 637 } 638 /* Debugging */ 639 if (debug) { 640 IS tmp; 641 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 642 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 643 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 644 } 645 /* Gather adjacenct indices to root */ 646 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 647 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 648 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 649 if (size > 1) { 650 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 651 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 652 } 653 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 654 ierr = PetscFree(adj);CHKERRQ(ierr); 655 /* Debugging */ 656 if (debug) { 657 IS tmp; 658 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 659 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 660 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 661 } 662 /* Add in local adjacency indices for owned dofs on interface (roots) */ 663 for (p = pStart; p < pEnd; ++p) { 664 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 665 666 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 667 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 668 if (!dof) continue; 669 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 670 if (adof <= 0) continue; 671 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 672 for (d = off; d < off+dof; ++d) { 673 PetscInt adof, aoff, i; 674 675 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 676 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 677 i = adof-1; 678 for (q = 0; q < numAdj; ++q) { 679 const PetscInt padj = tmpAdj[q]; 680 PetscInt ndof, ncdof, ngoff, nd; 681 682 if ((padj < pStart) || (padj >= pEnd)) continue; 683 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 684 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 685 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 686 for (nd = 0; nd < ndof-ncdof; ++nd) { 687 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 688 --i; 689 } 690 } 691 } 692 } 693 /* Debugging */ 694 if (debug) { 695 IS tmp; 696 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 697 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 698 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 699 } 700 /* Compress indices */ 701 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 702 for (p = pStart; p < pEnd; ++p) { 703 PetscInt dof, cdof, off, d; 704 PetscInt adof, aoff; 705 706 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 707 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 708 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 709 if (!dof) continue; 710 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 711 if (adof <= 0) continue; 712 for (d = off; d < off+dof-cdof; ++d) { 713 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 714 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 715 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 716 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 717 } 718 } 719 /* Debugging */ 720 if (debug) { 721 IS tmp; 722 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 723 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 724 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 725 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 726 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 727 } 728 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 729 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 730 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 731 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 732 for (p = pStart; p < pEnd; ++p) { 733 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 734 PetscBool found = PETSC_TRUE; 735 736 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 737 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 738 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 739 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 740 for (d = 0; d < dof-cdof; ++d) { 741 PetscInt ldof, rdof; 742 743 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 744 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 745 if (ldof > 0) { 746 /* We do not own this point */ 747 } else if (rdof > 0) { 748 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 749 } else { 750 found = PETSC_FALSE; 751 } 752 } 753 if (found) continue; 754 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 755 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 756 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 757 for (q = 0; q < numAdj; ++q) { 758 const PetscInt padj = tmpAdj[q]; 759 PetscInt ndof, ncdof, noff; 760 761 if ((padj < pStart) || (padj >= pEnd)) continue; 762 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 763 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 764 ierr = PetscSectionGetOffset(section, padj, &noff);CHKERRQ(ierr); 765 for (d = goff; d < goff+dof-cdof; ++d) { 766 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 767 } 768 } 769 } 770 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 771 if (debug) { 772 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 773 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 774 } 775 /* Get adjacent indices */ 776 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 777 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 778 for (p = pStart; p < pEnd; ++p) { 779 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 780 PetscBool found = PETSC_TRUE; 781 782 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 783 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 784 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 786 for (d = 0; d < dof-cdof; ++d) { 787 PetscInt ldof, rdof; 788 789 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 790 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 791 if (ldof > 0) { 792 /* We do not own this point */ 793 } else if (rdof > 0) { 794 PetscInt aoff, roff; 795 796 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 797 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 798 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 799 } else { 800 found = PETSC_FALSE; 801 } 802 } 803 if (found) continue; 804 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 805 for (d = goff; d < goff+dof-cdof; ++d) { 806 PetscInt adof, aoff, i = 0; 807 808 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 809 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 810 for (q = 0; q < numAdj; ++q) { 811 const PetscInt padj = tmpAdj[q]; 812 PetscInt ndof, ncdof, ngoff, nd; 813 const PetscInt *ncind; 814 815 /* Adjacent points may not be in the section chart */ 816 if ((padj < pStart) || (padj >= pEnd)) continue; 817 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 818 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 819 ierr = PetscSectionGetConstraintIndices(section, padj, &ncind);CHKERRQ(ierr); 820 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 821 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 822 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 823 } 824 } 825 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 826 } 827 } 828 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 829 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 830 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 831 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 832 /* Debugging */ 833 if (debug) { 834 IS tmp; 835 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 836 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 837 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 838 } 839 /* Create allocation vectors from adjacency graph */ 840 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 841 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr); 842 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 843 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 844 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 845 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 846 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 847 /* Only loop over blocks of rows */ 848 if (rStart%bs || rEnd%bs) SETERRQ3(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 849 for (r = rStart/bs; r < rEnd/bs; ++r) { 850 const PetscInt row = r*bs; 851 PetscInt numCols, cStart, c; 852 853 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 854 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 855 for (c = cStart; c < cStart+numCols; ++c) { 856 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 857 ++dnz[r-rStart]; 858 if (cols[c] >= row) ++dnzu[r-rStart]; 859 } else { 860 ++onz[r-rStart]; 861 if (cols[c] >= row) ++onzu[r-rStart]; 862 } 863 } 864 } 865 if (bs > 1) { 866 for (r = 0; r < locRows/bs; ++r) { 867 dnz[r] /= bs; 868 onz[r] /= bs; 869 dnzu[r] /= bs; 870 onzu[r] /= bs; 871 } 872 } 873 /* Set matrix pattern */ 874 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 875 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 876 /* Fill matrix with zeros */ 877 if (fillMatrix) { 878 PetscScalar *values; 879 PetscInt maxRowLen = 0; 880 881 for (r = rStart; r < rEnd; ++r) { 882 PetscInt len; 883 884 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 885 maxRowLen = PetscMax(maxRowLen, len); 886 } 887 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 888 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 889 for (r = rStart; r < rEnd; ++r) { 890 PetscInt numCols, cStart; 891 892 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 893 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 894 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 895 } 896 ierr = PetscFree(values);CHKERRQ(ierr); 897 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 898 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 899 } 900 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 901 ierr = PetscFree(cols);CHKERRQ(ierr); 902 PetscFunctionReturn(0); 903 } 904 905 #if 0 906 #undef __FUNCT__ 907 #define __FUNCT__ "DMPlexPreallocateOperator_2" 908 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 909 { 910 PetscInt *tmpClosure,*tmpAdj,*visits; 911 PetscInt c,cStart,cEnd,pStart,pEnd; 912 PetscErrorCode ierr; 913 914 PetscFunctionBegin; 915 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 916 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 917 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 918 919 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 920 921 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 922 npoints = pEnd - pStart; 923 924 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 925 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 926 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 927 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 928 for (c=cStart; c<cEnd; c++) { 929 PetscInt *support = tmpClosure; 930 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 931 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 932 } 933 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 934 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 935 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 936 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 937 938 ierr = PetscSFGetRanks();CHKERRQ(ierr); 939 940 941 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 942 for (c=cStart; c<cEnd; c++) { 943 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 944 /* 945 Depth-first walk of transitive closure. 946 At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 947 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 948 */ 949 } 950 951 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 952 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 953 PetscFunctionReturn(0); 954 } 955 #endif 956 957 #undef __FUNCT__ 958 #define __FUNCT__ "DMCreateMatrix_Plex" 959 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 960 { 961 PetscSection section, sectionGlobal; 962 PetscInt bs = -1; 963 PetscInt localSize; 964 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 965 PetscErrorCode ierr; 966 967 PetscFunctionBegin; 968 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 969 ierr = MatInitializePackage(NULL);CHKERRQ(ierr); 970 #endif 971 if (!mtype) mtype = MATAIJ; 972 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 973 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 974 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 975 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 976 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 977 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 978 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 979 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 980 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 981 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 982 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 983 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 984 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 985 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 986 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 987 /* Check for symmetric storage */ 988 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 989 if (isSymmetric) { 990 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 991 } 992 if (!isShell) { 993 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 994 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 995 996 if (bs < 0) { 997 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 998 PetscInt pStart, pEnd, p, dof, cdof; 999 1000 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1001 for (p = pStart; p < pEnd; ++p) { 1002 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1003 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 1004 if (dof-cdof) { 1005 if (bs < 0) { 1006 bs = dof-cdof; 1007 } else if (bs != dof-cdof) { 1008 /* Layout does not admit a pointwise block size */ 1009 bs = 1; 1010 break; 1011 } 1012 } 1013 } 1014 /* Must have same blocksize on all procs (some might have no points) */ 1015 bsLocal = bs; 1016 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1017 bsLocal = bs < 0 ? bsMax : bs; 1018 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1019 if (bsMin != bsMax) { 1020 bs = 1; 1021 } else { 1022 bs = bsMax; 1023 } 1024 } else { 1025 bs = 1; 1026 } 1027 } 1028 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1029 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1030 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1031 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1032 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1033 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1034 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1035 } 1036 PetscFunctionReturn(0); 1037 } 1038 1039 #undef __FUNCT__ 1040 #define __FUNCT__ "DMPlexGetDimension" 1041 /*@ 1042 DMPlexGetDimension - Return the topological mesh dimension 1043 1044 Not collective 1045 1046 Input Parameter: 1047 . mesh - The DMPlex 1048 1049 Output Parameter: 1050 . dim - The topological mesh dimension 1051 1052 Level: beginner 1053 1054 .seealso: DMPlexCreate() 1055 @*/ 1056 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1057 { 1058 DM_Plex *mesh = (DM_Plex*) dm->data; 1059 1060 PetscFunctionBegin; 1061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1062 PetscValidPointer(dim, 2); 1063 *dim = mesh->dim; 1064 PetscFunctionReturn(0); 1065 } 1066 1067 #undef __FUNCT__ 1068 #define __FUNCT__ "DMPlexSetDimension" 1069 /*@ 1070 DMPlexSetDimension - Set the topological mesh dimension 1071 1072 Collective on mesh 1073 1074 Input Parameters: 1075 + mesh - The DMPlex 1076 - dim - The topological mesh dimension 1077 1078 Level: beginner 1079 1080 .seealso: DMPlexCreate() 1081 @*/ 1082 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1083 { 1084 DM_Plex *mesh = (DM_Plex*) dm->data; 1085 1086 PetscFunctionBegin; 1087 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1088 PetscValidLogicalCollectiveInt(dm, dim, 2); 1089 mesh->dim = dim; 1090 mesh->preallocCenterDim = dim; 1091 PetscFunctionReturn(0); 1092 } 1093 1094 #undef __FUNCT__ 1095 #define __FUNCT__ "DMPlexGetChart" 1096 /*@ 1097 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1098 1099 Not collective 1100 1101 Input Parameter: 1102 . mesh - The DMPlex 1103 1104 Output Parameters: 1105 + pStart - The first mesh point 1106 - pEnd - The upper bound for mesh points 1107 1108 Level: beginner 1109 1110 .seealso: DMPlexCreate(), DMPlexSetChart() 1111 @*/ 1112 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1113 { 1114 DM_Plex *mesh = (DM_Plex*) dm->data; 1115 PetscErrorCode ierr; 1116 1117 PetscFunctionBegin; 1118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1119 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1120 PetscFunctionReturn(0); 1121 } 1122 1123 #undef __FUNCT__ 1124 #define __FUNCT__ "DMPlexSetChart" 1125 /*@ 1126 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1127 1128 Not collective 1129 1130 Input Parameters: 1131 + mesh - The DMPlex 1132 . pStart - The first mesh point 1133 - pEnd - The upper bound for mesh points 1134 1135 Output Parameters: 1136 1137 Level: beginner 1138 1139 .seealso: DMPlexCreate(), DMPlexGetChart() 1140 @*/ 1141 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1142 { 1143 DM_Plex *mesh = (DM_Plex*) dm->data; 1144 PetscErrorCode ierr; 1145 1146 PetscFunctionBegin; 1147 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1148 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1149 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1150 PetscFunctionReturn(0); 1151 } 1152 1153 #undef __FUNCT__ 1154 #define __FUNCT__ "DMPlexGetConeSize" 1155 /*@ 1156 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1157 1158 Not collective 1159 1160 Input Parameters: 1161 + mesh - The DMPlex 1162 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1163 1164 Output Parameter: 1165 . size - The cone size for point p 1166 1167 Level: beginner 1168 1169 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1170 @*/ 1171 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1172 { 1173 DM_Plex *mesh = (DM_Plex*) dm->data; 1174 PetscErrorCode ierr; 1175 1176 PetscFunctionBegin; 1177 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1178 PetscValidPointer(size, 3); 1179 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1180 PetscFunctionReturn(0); 1181 } 1182 1183 #undef __FUNCT__ 1184 #define __FUNCT__ "DMPlexSetConeSize" 1185 /*@ 1186 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1187 1188 Not collective 1189 1190 Input Parameters: 1191 + mesh - The DMPlex 1192 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1193 - size - The cone size for point p 1194 1195 Output Parameter: 1196 1197 Note: 1198 This should be called after DMPlexSetChart(). 1199 1200 Level: beginner 1201 1202 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1203 @*/ 1204 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1205 { 1206 DM_Plex *mesh = (DM_Plex*) dm->data; 1207 PetscErrorCode ierr; 1208 1209 PetscFunctionBegin; 1210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1211 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1212 1213 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1214 PetscFunctionReturn(0); 1215 } 1216 1217 #undef __FUNCT__ 1218 #define __FUNCT__ "DMPlexGetCone" 1219 /*@C 1220 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1221 1222 Not collective 1223 1224 Input Parameters: 1225 + mesh - The DMPlex 1226 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1227 1228 Output Parameter: 1229 . cone - An array of points which are on the in-edges for point p 1230 1231 Level: beginner 1232 1233 Note: 1234 This routine is not available in Fortran. 1235 1236 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1237 @*/ 1238 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1239 { 1240 DM_Plex *mesh = (DM_Plex*) dm->data; 1241 PetscInt off; 1242 PetscErrorCode ierr; 1243 1244 PetscFunctionBegin; 1245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1246 PetscValidPointer(cone, 3); 1247 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1248 *cone = &mesh->cones[off]; 1249 PetscFunctionReturn(0); 1250 } 1251 1252 #undef __FUNCT__ 1253 #define __FUNCT__ "DMPlexSetCone" 1254 /*@ 1255 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1256 1257 Not collective 1258 1259 Input Parameters: 1260 + mesh - The DMPlex 1261 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1262 - cone - An array of points which are on the in-edges for point p 1263 1264 Output Parameter: 1265 1266 Note: 1267 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1268 1269 Level: beginner 1270 1271 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1272 @*/ 1273 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1274 { 1275 DM_Plex *mesh = (DM_Plex*) dm->data; 1276 PetscInt pStart, pEnd; 1277 PetscInt dof, off, c; 1278 PetscErrorCode ierr; 1279 1280 PetscFunctionBegin; 1281 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1282 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1283 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1284 if (dof) PetscValidPointer(cone, 3); 1285 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1286 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1287 for (c = 0; c < dof; ++c) { 1288 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1289 mesh->cones[off+c] = cone[c]; 1290 } 1291 PetscFunctionReturn(0); 1292 } 1293 1294 #undef __FUNCT__ 1295 #define __FUNCT__ "DMPlexGetConeOrientation" 1296 /*@C 1297 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1298 1299 Not collective 1300 1301 Input Parameters: 1302 + mesh - The DMPlex 1303 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1304 1305 Output Parameter: 1306 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1307 integer giving the prescription for cone traversal. If it is negative, the cone is 1308 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1309 the index of the cone point on which to start. 1310 1311 Level: beginner 1312 1313 Note: 1314 This routine is not available in Fortran. 1315 1316 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1317 @*/ 1318 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1319 { 1320 DM_Plex *mesh = (DM_Plex*) dm->data; 1321 PetscInt off; 1322 PetscErrorCode ierr; 1323 1324 PetscFunctionBegin; 1325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1326 #if defined(PETSC_USE_DEBUG) 1327 { 1328 PetscInt dof; 1329 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1330 if (dof) PetscValidPointer(coneOrientation, 3); 1331 } 1332 #endif 1333 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1334 1335 *coneOrientation = &mesh->coneOrientations[off]; 1336 PetscFunctionReturn(0); 1337 } 1338 1339 #undef __FUNCT__ 1340 #define __FUNCT__ "DMPlexSetConeOrientation" 1341 /*@ 1342 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1343 1344 Not collective 1345 1346 Input Parameters: 1347 + mesh - The DMPlex 1348 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1349 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1350 integer giving the prescription for cone traversal. If it is negative, the cone is 1351 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1352 the index of the cone point on which to start. 1353 1354 Output Parameter: 1355 1356 Note: 1357 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1358 1359 Level: beginner 1360 1361 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1362 @*/ 1363 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1364 { 1365 DM_Plex *mesh = (DM_Plex*) dm->data; 1366 PetscInt pStart, pEnd; 1367 PetscInt dof, off, c; 1368 PetscErrorCode ierr; 1369 1370 PetscFunctionBegin; 1371 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1372 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1373 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1374 if (dof) PetscValidPointer(coneOrientation, 3); 1375 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1376 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1377 for (c = 0; c < dof; ++c) { 1378 PetscInt cdof, o = coneOrientation[c]; 1379 1380 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1381 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1382 mesh->coneOrientations[off+c] = o; 1383 } 1384 PetscFunctionReturn(0); 1385 } 1386 1387 #undef __FUNCT__ 1388 #define __FUNCT__ "DMPlexInsertCone" 1389 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1390 { 1391 DM_Plex *mesh = (DM_Plex*) dm->data; 1392 PetscInt pStart, pEnd; 1393 PetscInt dof, off; 1394 PetscErrorCode ierr; 1395 1396 PetscFunctionBegin; 1397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1398 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1399 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); 1400 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); 1401 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1402 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1403 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1404 mesh->cones[off+conePos] = conePoint; 1405 PetscFunctionReturn(0); 1406 } 1407 1408 #undef __FUNCT__ 1409 #define __FUNCT__ "DMPlexInsertConeOrientation" 1410 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 1411 { 1412 DM_Plex *mesh = (DM_Plex*) dm->data; 1413 PetscInt pStart, pEnd; 1414 PetscInt dof, off; 1415 PetscErrorCode ierr; 1416 1417 PetscFunctionBegin; 1418 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1419 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1420 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); 1421 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1422 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1423 if ((conePos < 0) || (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); 1424 mesh->coneOrientations[off+conePos] = coneOrientation; 1425 PetscFunctionReturn(0); 1426 } 1427 1428 #undef __FUNCT__ 1429 #define __FUNCT__ "DMPlexGetSupportSize" 1430 /*@ 1431 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1432 1433 Not collective 1434 1435 Input Parameters: 1436 + mesh - The DMPlex 1437 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1438 1439 Output Parameter: 1440 . size - The support size for point p 1441 1442 Level: beginner 1443 1444 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1445 @*/ 1446 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1447 { 1448 DM_Plex *mesh = (DM_Plex*) dm->data; 1449 PetscErrorCode ierr; 1450 1451 PetscFunctionBegin; 1452 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1453 PetscValidPointer(size, 3); 1454 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1455 PetscFunctionReturn(0); 1456 } 1457 1458 #undef __FUNCT__ 1459 #define __FUNCT__ "DMPlexSetSupportSize" 1460 /*@ 1461 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1462 1463 Not collective 1464 1465 Input Parameters: 1466 + mesh - The DMPlex 1467 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1468 - size - The support size for point p 1469 1470 Output Parameter: 1471 1472 Note: 1473 This should be called after DMPlexSetChart(). 1474 1475 Level: beginner 1476 1477 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1478 @*/ 1479 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1480 { 1481 DM_Plex *mesh = (DM_Plex*) dm->data; 1482 PetscErrorCode ierr; 1483 1484 PetscFunctionBegin; 1485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1486 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1487 1488 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1489 PetscFunctionReturn(0); 1490 } 1491 1492 #undef __FUNCT__ 1493 #define __FUNCT__ "DMPlexGetSupport" 1494 /*@C 1495 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1496 1497 Not collective 1498 1499 Input Parameters: 1500 + mesh - The DMPlex 1501 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1502 1503 Output Parameter: 1504 . support - An array of points which are on the out-edges for point p 1505 1506 Level: beginner 1507 1508 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1509 @*/ 1510 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1511 { 1512 DM_Plex *mesh = (DM_Plex*) dm->data; 1513 PetscInt off; 1514 PetscErrorCode ierr; 1515 1516 PetscFunctionBegin; 1517 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1518 PetscValidPointer(support, 3); 1519 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1520 *support = &mesh->supports[off]; 1521 PetscFunctionReturn(0); 1522 } 1523 1524 #undef __FUNCT__ 1525 #define __FUNCT__ "DMPlexSetSupport" 1526 /*@ 1527 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1528 1529 Not collective 1530 1531 Input Parameters: 1532 + mesh - The DMPlex 1533 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1534 - support - An array of points which are on the in-edges for point p 1535 1536 Output Parameter: 1537 1538 Note: 1539 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1540 1541 Level: beginner 1542 1543 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1544 @*/ 1545 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1546 { 1547 DM_Plex *mesh = (DM_Plex*) dm->data; 1548 PetscInt pStart, pEnd; 1549 PetscInt dof, off, c; 1550 PetscErrorCode ierr; 1551 1552 PetscFunctionBegin; 1553 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1554 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1555 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1556 if (dof) PetscValidPointer(support, 3); 1557 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1558 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); 1559 for (c = 0; c < dof; ++c) { 1560 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); 1561 mesh->supports[off+c] = support[c]; 1562 } 1563 PetscFunctionReturn(0); 1564 } 1565 1566 #undef __FUNCT__ 1567 #define __FUNCT__ "DMPlexInsertSupport" 1568 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1569 { 1570 DM_Plex *mesh = (DM_Plex*) dm->data; 1571 PetscInt pStart, pEnd; 1572 PetscInt dof, off; 1573 PetscErrorCode ierr; 1574 1575 PetscFunctionBegin; 1576 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1577 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1578 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1579 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1580 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); 1581 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); 1582 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); 1583 mesh->supports[off+supportPos] = supportPoint; 1584 PetscFunctionReturn(0); 1585 } 1586 1587 #undef __FUNCT__ 1588 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1589 /*@C 1590 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1591 1592 Not collective 1593 1594 Input Parameters: 1595 + mesh - The DMPlex 1596 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1597 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1598 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1599 1600 Output Parameters: 1601 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1602 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1603 1604 Note: 1605 If using internal storage (points is NULL on input), each call overwrites the last output. 1606 1607 Level: beginner 1608 1609 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1610 @*/ 1611 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1612 { 1613 DM_Plex *mesh = (DM_Plex*) dm->data; 1614 PetscInt *closure, *fifo; 1615 const PetscInt *tmp = NULL, *tmpO = NULL; 1616 PetscInt tmpSize, t; 1617 PetscInt depth = 0, maxSize; 1618 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1619 PetscErrorCode ierr; 1620 1621 PetscFunctionBegin; 1622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1623 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1624 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1625 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1626 if (*points) { 1627 closure = *points; 1628 } else { 1629 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1630 } 1631 closure[0] = p; closure[1] = 0; 1632 /* This is only 1-level */ 1633 if (useCone) { 1634 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1635 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1636 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1637 } else { 1638 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1639 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1640 } 1641 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1642 const PetscInt cp = tmp[t]; 1643 const PetscInt co = tmpO ? tmpO[t] : 0; 1644 1645 closure[closureSize] = cp; 1646 closure[closureSize+1] = co; 1647 fifo[fifoSize] = cp; 1648 fifo[fifoSize+1] = co; 1649 } 1650 while (fifoSize - fifoStart) { 1651 const PetscInt q = fifo[fifoStart]; 1652 const PetscInt o = fifo[fifoStart+1]; 1653 const PetscInt rev = o >= 0 ? 0 : 1; 1654 const PetscInt off = rev ? -(o+1) : o; 1655 1656 if (useCone) { 1657 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1658 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1659 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1660 } else { 1661 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1662 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1663 tmpO = NULL; 1664 } 1665 for (t = 0; t < tmpSize; ++t) { 1666 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1667 const PetscInt cp = tmp[i]; 1668 /* Must propogate orientation */ 1669 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1670 PetscInt c; 1671 1672 /* Check for duplicate */ 1673 for (c = 0; c < closureSize; c += 2) { 1674 if (closure[c] == cp) break; 1675 } 1676 if (c == closureSize) { 1677 closure[closureSize] = cp; 1678 closure[closureSize+1] = co; 1679 fifo[fifoSize] = cp; 1680 fifo[fifoSize+1] = co; 1681 closureSize += 2; 1682 fifoSize += 2; 1683 } 1684 } 1685 fifoStart += 2; 1686 } 1687 if (numPoints) *numPoints = closureSize/2; 1688 if (points) *points = closure; 1689 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1690 PetscFunctionReturn(0); 1691 } 1692 1693 #undef __FUNCT__ 1694 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1695 /*@C 1696 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1697 1698 Not collective 1699 1700 Input Parameters: 1701 + mesh - The DMPlex 1702 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1703 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1704 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1705 1706 Output Parameters: 1707 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1708 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1709 1710 Note: 1711 If not using internal storage (points is not NULL on input), this call is unnecessary 1712 1713 Level: beginner 1714 1715 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1716 @*/ 1717 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1718 { 1719 PetscErrorCode ierr; 1720 1721 PetscFunctionBegin; 1722 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1723 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1724 PetscFunctionReturn(0); 1725 } 1726 1727 #undef __FUNCT__ 1728 #define __FUNCT__ "DMPlexGetMaxSizes" 1729 /*@ 1730 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1731 1732 Not collective 1733 1734 Input Parameter: 1735 . mesh - The DMPlex 1736 1737 Output Parameters: 1738 + maxConeSize - The maximum number of in-edges 1739 - maxSupportSize - The maximum number of out-edges 1740 1741 Level: beginner 1742 1743 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1744 @*/ 1745 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1746 { 1747 DM_Plex *mesh = (DM_Plex*) dm->data; 1748 1749 PetscFunctionBegin; 1750 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1751 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1752 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1753 PetscFunctionReturn(0); 1754 } 1755 1756 #undef __FUNCT__ 1757 #define __FUNCT__ "DMSetUp_Plex" 1758 PetscErrorCode DMSetUp_Plex(DM dm) 1759 { 1760 DM_Plex *mesh = (DM_Plex*) dm->data; 1761 PetscInt size; 1762 PetscErrorCode ierr; 1763 1764 PetscFunctionBegin; 1765 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1766 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1767 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1768 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1769 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1770 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1771 if (mesh->maxSupportSize) { 1772 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1773 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1774 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1775 } 1776 PetscFunctionReturn(0); 1777 } 1778 1779 #undef __FUNCT__ 1780 #define __FUNCT__ "DMCreateSubDM_Plex" 1781 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1782 { 1783 PetscSection section, sectionGlobal; 1784 PetscInt *subIndices; 1785 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1786 PetscErrorCode ierr; 1787 1788 PetscFunctionBegin; 1789 if (!numFields) PetscFunctionReturn(0); 1790 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1791 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1792 if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1793 if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1794 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1795 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); 1796 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1797 for (p = pStart; p < pEnd; ++p) { 1798 PetscInt gdof; 1799 1800 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1801 if (gdof > 0) { 1802 for (f = 0; f < numFields; ++f) { 1803 PetscInt fdof, fcdof; 1804 1805 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1806 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1807 subSize += fdof-fcdof; 1808 } 1809 } 1810 } 1811 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1812 for (p = pStart; p < pEnd; ++p) { 1813 PetscInt gdof, goff; 1814 1815 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1816 if (gdof > 0) { 1817 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1818 for (f = 0; f < numFields; ++f) { 1819 PetscInt fdof, fcdof, fc, f2, poff = 0; 1820 1821 /* Can get rid of this loop by storing field information in the global section */ 1822 for (f2 = 0; f2 < fields[f]; ++f2) { 1823 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1824 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1825 poff += fdof-fcdof; 1826 } 1827 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1828 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1829 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1830 subIndices[subOff] = goff+poff+fc; 1831 } 1832 } 1833 } 1834 } 1835 if (is) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1836 if (subdm) { 1837 PetscSection subsection; 1838 PetscBool haveNull = PETSC_FALSE; 1839 PetscInt f, nf = 0; 1840 1841 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1842 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1843 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1844 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 1845 for (f = 0; f < numFields; ++f) { 1846 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1847 if ((*subdm)->nullspaceConstructors[f]) { 1848 haveNull = PETSC_TRUE; 1849 nf = f; 1850 } 1851 } 1852 if (haveNull) { 1853 MatNullSpace nullSpace; 1854 1855 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1856 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1857 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1858 } 1859 if (dm->fields) { 1860 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); 1861 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1862 for (f = 0; f < numFields; ++f) { 1863 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1864 } 1865 if (numFields == 1) { 1866 MatNullSpace space; 1867 Mat pmat; 1868 1869 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1870 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1871 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1872 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1873 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1874 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1875 } 1876 } 1877 } 1878 PetscFunctionReturn(0); 1879 } 1880 1881 #undef __FUNCT__ 1882 #define __FUNCT__ "DMPlexSymmetrize" 1883 /*@ 1884 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1885 1886 Not collective 1887 1888 Input Parameter: 1889 . mesh - The DMPlex 1890 1891 Output Parameter: 1892 1893 Note: 1894 This should be called after all calls to DMPlexSetCone() 1895 1896 Level: beginner 1897 1898 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1899 @*/ 1900 PetscErrorCode DMPlexSymmetrize(DM dm) 1901 { 1902 DM_Plex *mesh = (DM_Plex*) dm->data; 1903 PetscInt *offsets; 1904 PetscInt supportSize; 1905 PetscInt pStart, pEnd, p; 1906 PetscErrorCode ierr; 1907 1908 PetscFunctionBegin; 1909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1910 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1911 /* Calculate support sizes */ 1912 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1913 for (p = pStart; p < pEnd; ++p) { 1914 PetscInt dof, off, c; 1915 1916 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1917 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1918 for (c = off; c < off+dof; ++c) { 1919 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1920 } 1921 } 1922 for (p = pStart; p < pEnd; ++p) { 1923 PetscInt dof; 1924 1925 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1926 1927 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1928 } 1929 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1930 /* Calculate supports */ 1931 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1932 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1933 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1934 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1935 for (p = pStart; p < pEnd; ++p) { 1936 PetscInt dof, off, c; 1937 1938 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1939 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1940 for (c = off; c < off+dof; ++c) { 1941 const PetscInt q = mesh->cones[c]; 1942 PetscInt offS; 1943 1944 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1945 1946 mesh->supports[offS+offsets[q]] = p; 1947 ++offsets[q]; 1948 } 1949 } 1950 ierr = PetscFree(offsets);CHKERRQ(ierr); 1951 PetscFunctionReturn(0); 1952 } 1953 1954 #undef __FUNCT__ 1955 #define __FUNCT__ "DMPlexSetDepth_Private" 1956 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1957 { 1958 PetscInt d; 1959 PetscErrorCode ierr; 1960 1961 PetscFunctionBegin; 1962 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1963 if (d < 0) { 1964 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1965 const PetscInt *cone = NULL; 1966 PetscInt dCone; 1967 1968 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1969 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1970 d = dCone+1; 1971 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1972 } 1973 *depth = d; 1974 PetscFunctionReturn(0); 1975 } 1976 1977 #undef __FUNCT__ 1978 #define __FUNCT__ "DMPlexStratify" 1979 /*@ 1980 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 1981 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 1982 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 1983 the DAG. 1984 1985 Not collective 1986 1987 Input Parameter: 1988 . mesh - The DMPlex 1989 1990 Output Parameter: 1991 1992 Notes: 1993 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 1994 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 1995 1996 This should be called after all calls to DMPlexSymmetrize() 1997 1998 Level: beginner 1999 2000 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2001 @*/ 2002 PetscErrorCode DMPlexStratify(DM dm) 2003 { 2004 DM_Plex *mesh = (DM_Plex*) dm->data; 2005 PetscInt pStart, pEnd, p; 2006 PetscInt numRoots = 0, numLeaves = 0; 2007 PetscErrorCode ierr; 2008 2009 PetscFunctionBegin; 2010 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2011 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2012 /* Calculate depth */ 2013 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2014 /* Initialize roots and count leaves */ 2015 for (p = pStart; p < pEnd; ++p) { 2016 PetscInt coneSize, supportSize; 2017 2018 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2019 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2020 if (!coneSize && supportSize) { 2021 ++numRoots; 2022 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2023 } else if (!supportSize && coneSize) { 2024 ++numLeaves; 2025 } else if (!supportSize && !coneSize) { 2026 /* Isolated points */ 2027 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2028 } 2029 } 2030 if (numRoots + numLeaves == (pEnd - pStart)) { 2031 for (p = pStart; p < pEnd; ++p) { 2032 PetscInt coneSize, supportSize; 2033 2034 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2035 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2036 if (!supportSize && coneSize) { 2037 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2038 } 2039 } 2040 } else { 2041 /* This might be slow since lookup is not fast */ 2042 for (p = pStart; p < pEnd; ++p) { 2043 PetscInt depth; 2044 2045 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2046 } 2047 } 2048 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2049 PetscFunctionReturn(0); 2050 } 2051 2052 #undef __FUNCT__ 2053 #define __FUNCT__ "DMPlexGetJoin" 2054 /*@C 2055 DMPlexGetJoin - Get an array for the join of the set of points 2056 2057 Not Collective 2058 2059 Input Parameters: 2060 + dm - The DMPlex object 2061 . numPoints - The number of input points for the join 2062 - points - The input points 2063 2064 Output Parameters: 2065 + numCoveredPoints - The number of points in the join 2066 - coveredPoints - The points in the join 2067 2068 Level: intermediate 2069 2070 Note: Currently, this is restricted to a single level join 2071 2072 .keywords: mesh 2073 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2074 @*/ 2075 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2076 { 2077 DM_Plex *mesh = (DM_Plex*) dm->data; 2078 PetscInt *join[2]; 2079 PetscInt joinSize, i = 0; 2080 PetscInt dof, off, p, c, m; 2081 PetscErrorCode ierr; 2082 2083 PetscFunctionBegin; 2084 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2085 PetscValidPointer(points, 2); 2086 PetscValidPointer(numCoveredPoints, 3); 2087 PetscValidPointer(coveredPoints, 4); 2088 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2089 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2090 /* Copy in support of first point */ 2091 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2092 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2093 for (joinSize = 0; joinSize < dof; ++joinSize) { 2094 join[i][joinSize] = mesh->supports[off+joinSize]; 2095 } 2096 /* Check each successive support */ 2097 for (p = 1; p < numPoints; ++p) { 2098 PetscInt newJoinSize = 0; 2099 2100 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2101 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2102 for (c = 0; c < dof; ++c) { 2103 const PetscInt point = mesh->supports[off+c]; 2104 2105 for (m = 0; m < joinSize; ++m) { 2106 if (point == join[i][m]) { 2107 join[1-i][newJoinSize++] = point; 2108 break; 2109 } 2110 } 2111 } 2112 joinSize = newJoinSize; 2113 i = 1-i; 2114 } 2115 *numCoveredPoints = joinSize; 2116 *coveredPoints = join[i]; 2117 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2118 PetscFunctionReturn(0); 2119 } 2120 2121 #undef __FUNCT__ 2122 #define __FUNCT__ "DMPlexRestoreJoin" 2123 /*@C 2124 DMPlexRestoreJoin - Restore an array for the join of the set of points 2125 2126 Not Collective 2127 2128 Input Parameters: 2129 + dm - The DMPlex object 2130 . numPoints - The number of input points for the join 2131 - points - The input points 2132 2133 Output Parameters: 2134 + numCoveredPoints - The number of points in the join 2135 - coveredPoints - The points in the join 2136 2137 Level: intermediate 2138 2139 .keywords: mesh 2140 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2141 @*/ 2142 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2143 { 2144 PetscErrorCode ierr; 2145 2146 PetscFunctionBegin; 2147 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2148 PetscValidPointer(coveredPoints, 4); 2149 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2150 PetscFunctionReturn(0); 2151 } 2152 2153 #undef __FUNCT__ 2154 #define __FUNCT__ "DMPlexGetFullJoin" 2155 /*@C 2156 DMPlexGetFullJoin - Get an array for the join of the set of points 2157 2158 Not Collective 2159 2160 Input Parameters: 2161 + dm - The DMPlex object 2162 . numPoints - The number of input points for the join 2163 - points - The input points 2164 2165 Output Parameters: 2166 + numCoveredPoints - The number of points in the join 2167 - coveredPoints - The points in the join 2168 2169 Level: intermediate 2170 2171 .keywords: mesh 2172 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2173 @*/ 2174 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2175 { 2176 DM_Plex *mesh = (DM_Plex*) dm->data; 2177 PetscInt *offsets, **closures; 2178 PetscInt *join[2]; 2179 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2180 PetscInt p, d, c, m; 2181 PetscErrorCode ierr; 2182 2183 PetscFunctionBegin; 2184 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2185 PetscValidPointer(points, 2); 2186 PetscValidPointer(numCoveredPoints, 3); 2187 PetscValidPointer(coveredPoints, 4); 2188 2189 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2190 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2191 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2192 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2193 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2194 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2195 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2196 2197 for (p = 0; p < numPoints; ++p) { 2198 PetscInt closureSize; 2199 2200 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2201 2202 offsets[p*(depth+2)+0] = 0; 2203 for (d = 0; d < depth+1; ++d) { 2204 PetscInt pStart, pEnd, i; 2205 2206 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2207 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2208 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2209 offsets[p*(depth+2)+d+1] = i; 2210 break; 2211 } 2212 } 2213 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2214 } 2215 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); 2216 } 2217 for (d = 0; d < depth+1; ++d) { 2218 PetscInt dof; 2219 2220 /* Copy in support of first point */ 2221 dof = offsets[d+1] - offsets[d]; 2222 for (joinSize = 0; joinSize < dof; ++joinSize) { 2223 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2224 } 2225 /* Check each successive cone */ 2226 for (p = 1; p < numPoints && joinSize; ++p) { 2227 PetscInt newJoinSize = 0; 2228 2229 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2230 for (c = 0; c < dof; ++c) { 2231 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2232 2233 for (m = 0; m < joinSize; ++m) { 2234 if (point == join[i][m]) { 2235 join[1-i][newJoinSize++] = point; 2236 break; 2237 } 2238 } 2239 } 2240 joinSize = newJoinSize; 2241 i = 1-i; 2242 } 2243 if (joinSize) break; 2244 } 2245 *numCoveredPoints = joinSize; 2246 *coveredPoints = join[i]; 2247 for (p = 0; p < numPoints; ++p) { 2248 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2249 } 2250 ierr = PetscFree(closures);CHKERRQ(ierr); 2251 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2252 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2253 PetscFunctionReturn(0); 2254 } 2255 2256 #undef __FUNCT__ 2257 #define __FUNCT__ "DMPlexGetMeet" 2258 /*@C 2259 DMPlexGetMeet - Get an array for the meet of the set of points 2260 2261 Not Collective 2262 2263 Input Parameters: 2264 + dm - The DMPlex object 2265 . numPoints - The number of input points for the meet 2266 - points - The input points 2267 2268 Output Parameters: 2269 + numCoveredPoints - The number of points in the meet 2270 - coveredPoints - The points in the meet 2271 2272 Level: intermediate 2273 2274 Note: Currently, this is restricted to a single level meet 2275 2276 .keywords: mesh 2277 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2278 @*/ 2279 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2280 { 2281 DM_Plex *mesh = (DM_Plex*) dm->data; 2282 PetscInt *meet[2]; 2283 PetscInt meetSize, i = 0; 2284 PetscInt dof, off, p, c, m; 2285 PetscErrorCode ierr; 2286 2287 PetscFunctionBegin; 2288 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2289 PetscValidPointer(points, 2); 2290 PetscValidPointer(numCoveringPoints, 3); 2291 PetscValidPointer(coveringPoints, 4); 2292 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2293 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2294 /* Copy in cone of first point */ 2295 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2296 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2297 for (meetSize = 0; meetSize < dof; ++meetSize) { 2298 meet[i][meetSize] = mesh->cones[off+meetSize]; 2299 } 2300 /* Check each successive cone */ 2301 for (p = 1; p < numPoints; ++p) { 2302 PetscInt newMeetSize = 0; 2303 2304 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2305 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2306 for (c = 0; c < dof; ++c) { 2307 const PetscInt point = mesh->cones[off+c]; 2308 2309 for (m = 0; m < meetSize; ++m) { 2310 if (point == meet[i][m]) { 2311 meet[1-i][newMeetSize++] = point; 2312 break; 2313 } 2314 } 2315 } 2316 meetSize = newMeetSize; 2317 i = 1-i; 2318 } 2319 *numCoveringPoints = meetSize; 2320 *coveringPoints = meet[i]; 2321 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2322 PetscFunctionReturn(0); 2323 } 2324 2325 #undef __FUNCT__ 2326 #define __FUNCT__ "DMPlexRestoreMeet" 2327 /*@C 2328 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2329 2330 Not Collective 2331 2332 Input Parameters: 2333 + dm - The DMPlex object 2334 . numPoints - The number of input points for the meet 2335 - points - The input points 2336 2337 Output Parameters: 2338 + numCoveredPoints - The number of points in the meet 2339 - coveredPoints - The points in the meet 2340 2341 Level: intermediate 2342 2343 .keywords: mesh 2344 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2345 @*/ 2346 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2347 { 2348 PetscErrorCode ierr; 2349 2350 PetscFunctionBegin; 2351 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2352 PetscValidPointer(coveredPoints, 4); 2353 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2354 PetscFunctionReturn(0); 2355 } 2356 2357 #undef __FUNCT__ 2358 #define __FUNCT__ "DMPlexGetFullMeet" 2359 /*@C 2360 DMPlexGetFullMeet - Get an array for the meet of the set of points 2361 2362 Not Collective 2363 2364 Input Parameters: 2365 + dm - The DMPlex object 2366 . numPoints - The number of input points for the meet 2367 - points - The input points 2368 2369 Output Parameters: 2370 + numCoveredPoints - The number of points in the meet 2371 - coveredPoints - The points in the meet 2372 2373 Level: intermediate 2374 2375 .keywords: mesh 2376 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2377 @*/ 2378 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2379 { 2380 DM_Plex *mesh = (DM_Plex*) dm->data; 2381 PetscInt *offsets, **closures; 2382 PetscInt *meet[2]; 2383 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2384 PetscInt p, h, c, m; 2385 PetscErrorCode ierr; 2386 2387 PetscFunctionBegin; 2388 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2389 PetscValidPointer(points, 2); 2390 PetscValidPointer(numCoveredPoints, 3); 2391 PetscValidPointer(coveredPoints, 4); 2392 2393 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2394 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2395 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2396 maxSize = PetscPowInt(mesh->maxConeSize,height); 2397 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2398 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2399 2400 for (p = 0; p < numPoints; ++p) { 2401 PetscInt closureSize; 2402 2403 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2404 2405 offsets[p*(height+2)+0] = 0; 2406 for (h = 0; h < height+1; ++h) { 2407 PetscInt pStart, pEnd, i; 2408 2409 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2410 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2411 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2412 offsets[p*(height+2)+h+1] = i; 2413 break; 2414 } 2415 } 2416 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2417 } 2418 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); 2419 } 2420 for (h = 0; h < height+1; ++h) { 2421 PetscInt dof; 2422 2423 /* Copy in cone of first point */ 2424 dof = offsets[h+1] - offsets[h]; 2425 for (meetSize = 0; meetSize < dof; ++meetSize) { 2426 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2427 } 2428 /* Check each successive cone */ 2429 for (p = 1; p < numPoints && meetSize; ++p) { 2430 PetscInt newMeetSize = 0; 2431 2432 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2433 for (c = 0; c < dof; ++c) { 2434 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2435 2436 for (m = 0; m < meetSize; ++m) { 2437 if (point == meet[i][m]) { 2438 meet[1-i][newMeetSize++] = point; 2439 break; 2440 } 2441 } 2442 } 2443 meetSize = newMeetSize; 2444 i = 1-i; 2445 } 2446 if (meetSize) break; 2447 } 2448 *numCoveredPoints = meetSize; 2449 *coveredPoints = meet[i]; 2450 for (p = 0; p < numPoints; ++p) { 2451 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2452 } 2453 ierr = PetscFree(closures);CHKERRQ(ierr); 2454 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2455 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2456 PetscFunctionReturn(0); 2457 } 2458 2459 #undef __FUNCT__ 2460 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2461 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2462 { 2463 MPI_Comm comm; 2464 PetscErrorCode ierr; 2465 2466 PetscFunctionBegin; 2467 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2468 PetscValidPointer(numFaceVertices,3); 2469 switch (cellDim) { 2470 case 0: 2471 *numFaceVertices = 0; 2472 break; 2473 case 1: 2474 *numFaceVertices = 1; 2475 break; 2476 case 2: 2477 switch (numCorners) { 2478 case 3: /* triangle */ 2479 *numFaceVertices = 2; /* Edge has 2 vertices */ 2480 break; 2481 case 4: /* quadrilateral */ 2482 *numFaceVertices = 2; /* Edge has 2 vertices */ 2483 break; 2484 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2485 *numFaceVertices = 3; /* Edge has 3 vertices */ 2486 break; 2487 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2488 *numFaceVertices = 3; /* Edge has 3 vertices */ 2489 break; 2490 default: 2491 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2492 } 2493 break; 2494 case 3: 2495 switch (numCorners) { 2496 case 4: /* tetradehdron */ 2497 *numFaceVertices = 3; /* Face has 3 vertices */ 2498 break; 2499 case 6: /* tet cohesive cells */ 2500 *numFaceVertices = 4; /* Face has 4 vertices */ 2501 break; 2502 case 8: /* hexahedron */ 2503 *numFaceVertices = 4; /* Face has 4 vertices */ 2504 break; 2505 case 9: /* tet cohesive Lagrange cells */ 2506 *numFaceVertices = 6; /* Face has 6 vertices */ 2507 break; 2508 case 10: /* quadratic tetrahedron */ 2509 *numFaceVertices = 6; /* Face has 6 vertices */ 2510 break; 2511 case 12: /* hex cohesive Lagrange cells */ 2512 *numFaceVertices = 6; /* Face has 6 vertices */ 2513 break; 2514 case 18: /* quadratic tet cohesive Lagrange cells */ 2515 *numFaceVertices = 6; /* Face has 6 vertices */ 2516 break; 2517 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2518 *numFaceVertices = 9; /* Face has 9 vertices */ 2519 break; 2520 default: 2521 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2522 } 2523 break; 2524 default: 2525 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2526 } 2527 PetscFunctionReturn(0); 2528 } 2529 2530 #undef __FUNCT__ 2531 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2532 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2533 { 2534 const PetscInt maxFaceCases = 30; 2535 PetscInt numFaceCases = 0; 2536 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2537 PetscInt *off, *adj; 2538 PetscInt *neighborCells, *tmpClosure; 2539 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2540 PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 2541 PetscErrorCode ierr; 2542 2543 PetscFunctionBegin; 2544 /* For parallel partitioning, I think you have to communicate supports */ 2545 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2546 cellDim = dim - cellHeight; 2547 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2548 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 2549 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2550 if (cEnd - cStart == 0) { 2551 if (numVertices) *numVertices = 0; 2552 if (offsets) *offsets = NULL; 2553 if (adjacency) *adjacency = NULL; 2554 PetscFunctionReturn(0); 2555 } 2556 numCells = cEnd - cStart; 2557 faceDepth = depth - cellHeight; 2558 /* Setup face recognition */ 2559 if (faceDepth == 1) { 2560 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 */ 2561 2562 for (c = cStart; c < cEnd; ++c) { 2563 PetscInt corners; 2564 2565 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2566 if (!cornersSeen[corners]) { 2567 PetscInt nFV; 2568 2569 if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2570 cornersSeen[corners] = 1; 2571 2572 ierr = DMPlexGetNumFaceVertices_Internal(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 2573 2574 numFaceVertices[numFaceCases++] = nFV; 2575 } 2576 } 2577 } 2578 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2579 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2580 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2581 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2582 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2583 /* Count neighboring cells */ 2584 for (cell = cStart; cell < cEnd; ++cell) { 2585 PetscInt numNeighbors = maxNeighbors, n; 2586 2587 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2588 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2589 for (n = 0; n < numNeighbors; ++n) { 2590 PetscInt cellPair[2]; 2591 PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 2592 PetscInt meetSize = 0; 2593 const PetscInt *meet = NULL; 2594 2595 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2596 if (cellPair[0] == cellPair[1]) continue; 2597 if (!found) { 2598 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2599 if (meetSize) { 2600 PetscInt f; 2601 2602 for (f = 0; f < numFaceCases; ++f) { 2603 if (numFaceVertices[f] == meetSize) { 2604 found = PETSC_TRUE; 2605 break; 2606 } 2607 } 2608 } 2609 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2610 } 2611 if (found) ++off[cell-cStart+1]; 2612 } 2613 } 2614 /* Prefix sum */ 2615 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2616 2617 if (adjacency) { 2618 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2619 /* Get neighboring cells */ 2620 for (cell = cStart; cell < cEnd; ++cell) { 2621 PetscInt numNeighbors = maxNeighbors, n; 2622 PetscInt cellOffset = 0; 2623 2624 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2625 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2626 for (n = 0; n < numNeighbors; ++n) { 2627 PetscInt cellPair[2]; 2628 PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 2629 PetscInt meetSize = 0; 2630 const PetscInt *meet = NULL; 2631 2632 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2633 if (cellPair[0] == cellPair[1]) continue; 2634 if (!found) { 2635 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2636 if (meetSize) { 2637 PetscInt f; 2638 2639 for (f = 0; f < numFaceCases; ++f) { 2640 if (numFaceVertices[f] == meetSize) { 2641 found = PETSC_TRUE; 2642 break; 2643 } 2644 } 2645 } 2646 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2647 } 2648 if (found) { 2649 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2650 ++cellOffset; 2651 } 2652 } 2653 } 2654 } 2655 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2656 if (numVertices) *numVertices = numCells; 2657 if (offsets) *offsets = off; 2658 if (adjacency) *adjacency = adj; 2659 PetscFunctionReturn(0); 2660 } 2661 2662 #if defined(PETSC_HAVE_CHACO) 2663 #if defined(PETSC_HAVE_UNISTD_H) 2664 #include <unistd.h> 2665 #endif 2666 /* Chaco does not have an include file */ 2667 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2668 float *ewgts, float *x, float *y, float *z, char *outassignname, 2669 char *outfilename, short *assignment, int architecture, int ndims_tot, 2670 int mesh_dims[3], double *goal, int global_method, int local_method, 2671 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2672 2673 extern int FREE_GRAPH; 2674 2675 #undef __FUNCT__ 2676 #define __FUNCT__ "DMPlexPartition_Chaco" 2677 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2678 { 2679 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2680 MPI_Comm comm; 2681 int nvtxs = numVertices; /* number of vertices in full graph */ 2682 int *vwgts = NULL; /* weights for all vertices */ 2683 float *ewgts = NULL; /* weights for all edges */ 2684 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2685 char *outassignname = NULL; /* name of assignment output file */ 2686 char *outfilename = NULL; /* output file name */ 2687 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2688 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2689 int mesh_dims[3]; /* dimensions of mesh of processors */ 2690 double *goal = NULL; /* desired set sizes for each set */ 2691 int global_method = 1; /* global partitioning algorithm */ 2692 int local_method = 1; /* local partitioning algorithm */ 2693 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2694 int vmax = 200; /* how many vertices to coarsen down to? */ 2695 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2696 double eigtol = 0.001; /* tolerance on eigenvectors */ 2697 long seed = 123636512; /* for random graph mutations */ 2698 short int *assignment; /* Output partition */ 2699 int fd_stdout, fd_pipe[2]; 2700 PetscInt *points; 2701 PetscMPIInt commSize; 2702 int i, v, p; 2703 PetscErrorCode ierr; 2704 2705 PetscFunctionBegin; 2706 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2707 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2708 if (!numVertices) { 2709 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2710 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2711 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2712 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2713 PetscFunctionReturn(0); 2714 } 2715 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2716 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2717 2718 if (global_method == INERTIAL_METHOD) { 2719 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2720 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2721 } 2722 mesh_dims[0] = commSize; 2723 mesh_dims[1] = 1; 2724 mesh_dims[2] = 1; 2725 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2726 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2727 /* TODO: check error codes for UNIX calls */ 2728 #if defined(PETSC_HAVE_UNISTD_H) 2729 { 2730 int piperet; 2731 piperet = pipe(fd_pipe); 2732 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2733 fd_stdout = dup(1); 2734 close(1); 2735 dup2(fd_pipe[1], 1); 2736 } 2737 #endif 2738 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2739 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2740 vmax, ndims, eigtol, seed); 2741 #if defined(PETSC_HAVE_UNISTD_H) 2742 { 2743 char msgLog[10000]; 2744 int count; 2745 2746 fflush(stdout); 2747 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2748 if (count < 0) count = 0; 2749 msgLog[count] = 0; 2750 close(1); 2751 dup2(fd_stdout, 1); 2752 close(fd_stdout); 2753 close(fd_pipe[0]); 2754 close(fd_pipe[1]); 2755 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2756 } 2757 #endif 2758 /* Convert to PetscSection+IS */ 2759 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2760 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2761 for (v = 0; v < nvtxs; ++v) { 2762 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2763 } 2764 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2765 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2766 for (p = 0, i = 0; p < commSize; ++p) { 2767 for (v = 0; v < nvtxs; ++v) { 2768 if (assignment[v] == p) points[i++] = v; 2769 } 2770 } 2771 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2772 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2773 if (global_method == INERTIAL_METHOD) { 2774 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2775 } 2776 ierr = PetscFree(assignment);CHKERRQ(ierr); 2777 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2778 PetscFunctionReturn(0); 2779 } 2780 #endif 2781 2782 #if defined(PETSC_HAVE_PARMETIS) 2783 #undef __FUNCT__ 2784 #define __FUNCT__ "DMPlexPartition_ParMetis" 2785 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2786 { 2787 PetscFunctionBegin; 2788 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ParMetis not yet supported"); 2789 PetscFunctionReturn(0); 2790 } 2791 #endif 2792 2793 #undef __FUNCT__ 2794 #define __FUNCT__ "DMPlexEnlargePartition" 2795 /* Expand the partition by BFS on the adjacency graph */ 2796 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2797 { 2798 PetscHashI h; 2799 const PetscInt *points; 2800 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2801 PetscInt pStart, pEnd, part, q; 2802 PetscErrorCode ierr; 2803 2804 PetscFunctionBegin; 2805 PetscHashICreate(h); 2806 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2807 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2808 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2809 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2810 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2811 for (part = pStart; part < pEnd; ++part) { 2812 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2813 2814 PetscHashIClear(h); 2815 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2816 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2817 /* Add all existing points to h */ 2818 for (p = 0; p < numPoints; ++p) { 2819 const PetscInt point = points[off+p]; 2820 PetscHashIAdd(h, point, 1); 2821 } 2822 PetscHashISize(h, nP); 2823 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2824 /* Add all points in next BFS level */ 2825 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2826 for (p = 0; p < numPoints; ++p) { 2827 const PetscInt point = points[off+p]; 2828 PetscInt s = start[point], e = start[point+1], a; 2829 2830 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2831 } 2832 PetscHashISize(h, numNewPoints); 2833 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2834 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2835 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2836 totPoints += numNewPoints; 2837 } 2838 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2839 PetscHashIDestroy(h); 2840 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2841 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2842 for (part = pStart, q = 0; part < pEnd; ++part) { 2843 PetscInt numPoints, p; 2844 2845 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2846 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2847 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2848 } 2849 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2850 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2851 PetscFunctionReturn(0); 2852 } 2853 2854 #undef __FUNCT__ 2855 #define __FUNCT__ "DMPlexCreatePartition" 2856 /* 2857 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2858 2859 Collective on DM 2860 2861 Input Parameters: 2862 + dm - The DM 2863 . height - The height for points in the partition 2864 - enlarge - Expand each partition with neighbors 2865 2866 Output Parameters: 2867 + partSection - The PetscSection giving the division of points by partition 2868 . partition - The list of points by partition 2869 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2870 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2871 2872 Level: developer 2873 2874 .seealso DMPlexDistribute() 2875 */ 2876 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2877 { 2878 PetscMPIInt size; 2879 PetscErrorCode ierr; 2880 2881 PetscFunctionBegin; 2882 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2883 2884 *origPartSection = NULL; 2885 *origPartition = NULL; 2886 if (size == 1) { 2887 PetscInt *points; 2888 PetscInt cStart, cEnd, c; 2889 2890 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2891 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2892 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2893 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2894 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2895 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2896 for (c = cStart; c < cEnd; ++c) points[c] = c; 2897 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2898 PetscFunctionReturn(0); 2899 } 2900 if (height == 0) { 2901 PetscInt numVertices; 2902 PetscInt *start = NULL; 2903 PetscInt *adjacency = NULL; 2904 2905 ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2906 if (1) { 2907 #if defined(PETSC_HAVE_CHACO) 2908 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2909 #endif 2910 } else { 2911 #if defined(PETSC_HAVE_PARMETIS) 2912 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2913 #endif 2914 } 2915 if (enlarge) { 2916 *origPartSection = *partSection; 2917 *origPartition = *partition; 2918 2919 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2920 } 2921 ierr = PetscFree(start);CHKERRQ(ierr); 2922 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2923 # if 0 2924 } else if (height == 1) { 2925 /* Build the dual graph for faces and partition the hypergraph */ 2926 PetscInt numEdges; 2927 2928 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2929 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2930 destroyCSR(numEdges, start, adjacency); 2931 #endif 2932 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2933 PetscFunctionReturn(0); 2934 } 2935 2936 #undef __FUNCT__ 2937 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2938 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2939 { 2940 /* const PetscInt height = 0; */ 2941 const PetscInt *partArray; 2942 PetscInt *allPoints, *partPoints = NULL; 2943 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2944 PetscErrorCode ierr; 2945 2946 PetscFunctionBegin; 2947 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2948 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2949 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2950 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2951 for (rank = rStart; rank < rEnd; ++rank) { 2952 PetscInt partSize = 0; 2953 PetscInt numPoints, offset, p; 2954 2955 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2956 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2957 for (p = 0; p < numPoints; ++p) { 2958 PetscInt point = partArray[offset+p], closureSize, c; 2959 PetscInt *closure = NULL; 2960 2961 /* TODO Include support for height > 0 case */ 2962 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2963 /* Merge into existing points */ 2964 if (partSize+closureSize > maxPartSize) { 2965 PetscInt *tmpPoints; 2966 2967 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2968 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2969 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2970 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2971 2972 partPoints = tmpPoints; 2973 } 2974 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 2975 partSize += closureSize; 2976 2977 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 2978 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2979 } 2980 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 2981 } 2982 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2983 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 2984 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 2985 2986 for (rank = rStart; rank < rEnd; ++rank) { 2987 PetscInt partSize = 0, newOffset; 2988 PetscInt numPoints, offset, p; 2989 2990 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2991 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2992 for (p = 0; p < numPoints; ++p) { 2993 PetscInt point = partArray[offset+p], closureSize, c; 2994 PetscInt *closure = NULL; 2995 2996 /* TODO Include support for height > 0 case */ 2997 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2998 /* Merge into existing points */ 2999 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3000 partSize += closureSize; 3001 3002 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3003 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3004 } 3005 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3006 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3007 } 3008 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3009 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3010 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3011 PetscFunctionReturn(0); 3012 } 3013 3014 #undef __FUNCT__ 3015 #define __FUNCT__ "DMPlexDistributeField" 3016 /* 3017 Input Parameters: 3018 . originalSection 3019 , originalVec 3020 3021 Output Parameters: 3022 . newSection 3023 . newVec 3024 */ 3025 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3026 { 3027 PetscSF fieldSF; 3028 PetscInt *remoteOffsets, fieldSize; 3029 PetscScalar *originalValues, *newValues; 3030 PetscErrorCode ierr; 3031 3032 PetscFunctionBegin; 3033 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3034 3035 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3036 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3037 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3038 3039 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3040 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3041 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3042 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3043 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3044 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3045 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3046 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3047 PetscFunctionReturn(0); 3048 } 3049 3050 #undef __FUNCT__ 3051 #define __FUNCT__ "DMPlexDistribute" 3052 /*@C 3053 DMPlexDistribute - Distributes the mesh and any associated sections. 3054 3055 Not Collective 3056 3057 Input Parameter: 3058 + dm - The original DMPlex object 3059 . partitioner - The partitioning package, or NULL for the default 3060 - overlap - The overlap of partitions, 0 is the default 3061 3062 Output Parameter: 3063 . parallelMesh - The distributed DMPlex object, or NULL 3064 3065 Note: If the mesh was not distributed, the return value is NULL 3066 3067 Level: intermediate 3068 3069 .keywords: mesh, elements 3070 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3071 @*/ 3072 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3073 { 3074 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3075 MPI_Comm comm; 3076 const PetscInt height = 0; 3077 PetscInt dim, numRemoteRanks; 3078 IS origCellPart, cellPart, part; 3079 PetscSection origCellPartSection, cellPartSection, partSection; 3080 PetscSFNode *remoteRanks; 3081 PetscSF partSF, pointSF, coneSF; 3082 ISLocalToGlobalMapping renumbering; 3083 PetscSection originalConeSection, newConeSection; 3084 PetscInt *remoteOffsets; 3085 PetscInt *cones, *newCones, newConesSize; 3086 PetscBool flg; 3087 PetscMPIInt rank, numProcs, p; 3088 PetscErrorCode ierr; 3089 3090 PetscFunctionBegin; 3091 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3092 PetscValidPointer(dmParallel,4); 3093 3094 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3095 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3096 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3097 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3098 3099 *dmParallel = NULL; 3100 if (numProcs == 1) PetscFunctionReturn(0); 3101 3102 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3103 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3104 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3105 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3106 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3107 if (!rank) numRemoteRanks = numProcs; 3108 else numRemoteRanks = 0; 3109 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3110 for (p = 0; p < numRemoteRanks; ++p) { 3111 remoteRanks[p].rank = p; 3112 remoteRanks[p].index = 0; 3113 } 3114 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3115 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3116 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3117 if (flg) { 3118 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3119 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3120 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3121 if (origCellPart) { 3122 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3123 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3124 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3125 } 3126 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3127 } 3128 /* Close the partition over the mesh */ 3129 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3130 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3131 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3132 /* Create new mesh */ 3133 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3134 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3135 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3136 pmesh = (DM_Plex*) (*dmParallel)->data; 3137 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3138 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3139 if (flg) { 3140 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3141 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3142 ierr = ISView(part, NULL);CHKERRQ(ierr); 3143 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3144 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3145 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3146 } 3147 /* Distribute cone section */ 3148 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3149 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3150 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3151 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3152 { 3153 PetscInt pStart, pEnd, p; 3154 3155 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3156 for (p = pStart; p < pEnd; ++p) { 3157 PetscInt coneSize; 3158 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3159 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3160 } 3161 } 3162 /* Communicate and renumber cones */ 3163 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3164 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3165 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3166 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3167 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3168 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3169 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3170 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3171 if (flg) { 3172 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3173 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3174 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3175 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3176 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3177 } 3178 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3179 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3180 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3181 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3182 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3183 /* Create supports and stratify sieve */ 3184 { 3185 PetscInt pStart, pEnd; 3186 3187 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3188 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3189 } 3190 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3191 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3192 /* Distribute Coordinates */ 3193 { 3194 PetscSection originalCoordSection, newCoordSection; 3195 Vec originalCoordinates, newCoordinates; 3196 const char *name; 3197 3198 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3199 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3200 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3201 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3202 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3203 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3204 3205 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3206 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3207 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3208 } 3209 /* Distribute labels */ 3210 { 3211 DMLabel next = mesh->labels, newNext = pmesh->labels; 3212 PetscInt numLabels = 0, l; 3213 3214 /* Bcast number of labels */ 3215 while (next) { 3216 ++numLabels; next = next->next; 3217 } 3218 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3219 next = mesh->labels; 3220 for (l = 0; l < numLabels; ++l) { 3221 DMLabel newLabel; 3222 const PetscInt *partArray; 3223 char *name; 3224 PetscInt *stratumSizes = NULL, *points = NULL; 3225 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3226 PetscInt nameSize, s, p; 3227 PetscBool isdepth; 3228 size_t len = 0; 3229 3230 /* Bcast name (could filter for no points) */ 3231 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3232 nameSize = len; 3233 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3234 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3235 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3236 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3237 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3238 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3239 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3240 newLabel->name = name; 3241 /* Bcast numStrata (could filter for no points in stratum) */ 3242 if (!rank) newLabel->numStrata = next->numStrata; 3243 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3244 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3245 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3246 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3247 /* Bcast stratumValues (could filter for no points in stratum) */ 3248 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3249 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3250 /* Find size on each process and Scatter */ 3251 if (!rank) { 3252 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3253 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3254 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3255 for (s = 0; s < next->numStrata; ++s) { 3256 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3257 const PetscInt point = next->points[p]; 3258 PetscInt proc; 3259 3260 for (proc = 0; proc < numProcs; ++proc) { 3261 PetscInt dof, off, pPart; 3262 3263 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3264 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3265 for (pPart = off; pPart < off+dof; ++pPart) { 3266 if (partArray[pPart] == point) { 3267 ++stratumSizes[proc*next->numStrata+s]; 3268 break; 3269 } 3270 } 3271 } 3272 } 3273 } 3274 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3275 } 3276 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3277 /* Calculate stratumOffsets */ 3278 newLabel->stratumOffsets[0] = 0; 3279 for (s = 0; s < newLabel->numStrata; ++s) { 3280 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3281 } 3282 /* Pack points and Scatter */ 3283 if (!rank) { 3284 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3285 displs[0] = 0; 3286 for (p = 0; p < numProcs; ++p) { 3287 sendcnts[p] = 0; 3288 for (s = 0; s < next->numStrata; ++s) { 3289 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3290 } 3291 offsets[p] = displs[p]; 3292 displs[p+1] = displs[p] + sendcnts[p]; 3293 } 3294 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3295 for (s = 0; s < next->numStrata; ++s) { 3296 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3297 const PetscInt point = next->points[p]; 3298 PetscInt proc; 3299 3300 for (proc = 0; proc < numProcs; ++proc) { 3301 PetscInt dof, off, pPart; 3302 3303 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3304 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3305 for (pPart = off; pPart < off+dof; ++pPart) { 3306 if (partArray[pPart] == point) { 3307 points[offsets[proc]++] = point; 3308 break; 3309 } 3310 } 3311 } 3312 } 3313 } 3314 } 3315 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3316 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3317 ierr = PetscFree(points);CHKERRQ(ierr); 3318 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3319 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3320 /* Renumber points */ 3321 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3322 /* Sort points */ 3323 for (s = 0; s < newLabel->numStrata; ++s) { 3324 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3325 } 3326 /* Insert into list */ 3327 if (newNext) newNext->next = newLabel; 3328 else pmesh->labels = newLabel; 3329 newNext = newLabel; 3330 if (!rank) next = next->next; 3331 } 3332 } 3333 /* Cleanup Partition */ 3334 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3335 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3336 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3337 ierr = ISDestroy(&part);CHKERRQ(ierr); 3338 /* Create point SF for parallel mesh */ 3339 { 3340 const PetscInt *leaves; 3341 PetscSFNode *remotePoints, *rowners, *lowners; 3342 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3343 PetscInt pStart, pEnd; 3344 3345 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3346 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3347 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3348 for (p=0; p<numRoots; p++) { 3349 rowners[p].rank = -1; 3350 rowners[p].index = -1; 3351 } 3352 if (origCellPart) { 3353 /* Make sure cells in the original partition are not assigned to other procs */ 3354 const PetscInt *origCells; 3355 3356 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3357 for (p = 0; p < numProcs; ++p) { 3358 PetscInt dof, off, d; 3359 3360 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3361 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3362 for (d = off; d < off+dof; ++d) { 3363 rowners[origCells[d]].rank = p; 3364 } 3365 } 3366 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3367 } 3368 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3369 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3370 3371 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3372 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3373 for (p = 0; p < numLeaves; ++p) { 3374 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3375 lowners[p].rank = rank; 3376 lowners[p].index = leaves ? leaves[p] : p; 3377 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3378 lowners[p].rank = -2; 3379 lowners[p].index = -2; 3380 } 3381 } 3382 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3383 rowners[p].rank = -3; 3384 rowners[p].index = -3; 3385 } 3386 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3387 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3388 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3389 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3390 for (p = 0; p < numLeaves; ++p) { 3391 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3392 if (lowners[p].rank != rank) ++numGhostPoints; 3393 } 3394 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3395 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3396 for (p = 0, gp = 0; p < numLeaves; ++p) { 3397 if (lowners[p].rank != rank) { 3398 ghostPoints[gp] = leaves ? leaves[p] : p; 3399 remotePoints[gp].rank = lowners[p].rank; 3400 remotePoints[gp].index = lowners[p].index; 3401 ++gp; 3402 } 3403 } 3404 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3405 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3406 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3407 } 3408 /* Cleanup */ 3409 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3410 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3411 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3412 PetscFunctionReturn(0); 3413 } 3414 3415 #undef __FUNCT__ 3416 #define __FUNCT__ "DMPlexRenumber_Private" 3417 /* 3418 Reasons to renumber: 3419 3420 1) Permute points, e.g. bandwidth reduction (Renumber) 3421 3422 a) Must not mix strata 3423 3424 2) Shift numbers for point insertion (Shift) 3425 3426 a) Want operation brken into parts so that insertion can be interleaved 3427 3428 renumbering - An IS which provides the new numbering 3429 */ 3430 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3431 { 3432 PetscFunctionBegin; 3433 PetscFunctionReturn(0); 3434 } 3435 3436 #undef __FUNCT__ 3437 #define __FUNCT__ "DMPlexShiftPoint_Private" 3438 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3439 { 3440 if (depth < 0) return p; 3441 /* Cells */ if (p < depthEnd[depth]) return p; 3442 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3443 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3444 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3445 } 3446 3447 #undef __FUNCT__ 3448 #define __FUNCT__ "DMPlexShiftSizes_Private" 3449 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3450 { 3451 PetscInt *depthEnd; 3452 PetscInt depth = 0, d, pStart, pEnd, p; 3453 PetscErrorCode ierr; 3454 3455 PetscFunctionBegin; 3456 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3457 if (depth < 0) PetscFunctionReturn(0); 3458 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3459 /* Step 1: Expand chart */ 3460 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3461 for (d = 0; d <= depth; ++d) { 3462 pEnd += depthShift[d]; 3463 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3464 } 3465 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3466 /* Step 2: Set cone and support sizes */ 3467 for (d = 0; d <= depth; ++d) { 3468 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3469 for (p = pStart; p < pEnd; ++p) { 3470 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3471 PetscInt size; 3472 3473 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3474 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3475 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3476 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3477 } 3478 } 3479 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3480 PetscFunctionReturn(0); 3481 } 3482 3483 #undef __FUNCT__ 3484 #define __FUNCT__ "DMPlexShiftPoints_Private" 3485 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3486 { 3487 PetscInt *depthEnd, *newpoints; 3488 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3489 PetscErrorCode ierr; 3490 3491 PetscFunctionBegin; 3492 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3493 if (depth < 0) PetscFunctionReturn(0); 3494 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3495 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3496 for (d = 0; d <= depth; ++d) { 3497 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3498 } 3499 /* Step 5: Set cones and supports */ 3500 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3501 for (p = pStart; p < pEnd; ++p) { 3502 const PetscInt *points = NULL, *orientations = NULL; 3503 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3504 3505 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3506 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3507 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3508 for (i = 0; i < size; ++i) { 3509 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3510 } 3511 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3512 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3513 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3514 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3515 for (i = 0; i < size; ++i) { 3516 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3517 } 3518 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3519 } 3520 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3521 PetscFunctionReturn(0); 3522 } 3523 3524 #undef __FUNCT__ 3525 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3526 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3527 { 3528 PetscSection coordSection, newCoordSection; 3529 Vec coordinates, newCoordinates; 3530 PetscScalar *coords, *newCoords; 3531 PetscInt *depthEnd, coordSize; 3532 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3533 PetscErrorCode ierr; 3534 3535 PetscFunctionBegin; 3536 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3537 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3538 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3539 for (d = 0; d <= depth; ++d) { 3540 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3541 } 3542 /* Step 8: Convert coordinates */ 3543 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3544 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3545 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3546 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);CHKERRQ(ierr); 3547 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3548 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3549 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3550 for (v = vStartNew; v < vEndNew; ++v) { 3551 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3552 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3553 } 3554 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3555 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3556 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3557 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &newCoordinates);CHKERRQ(ierr); 3558 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3559 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3560 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3561 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3562 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3563 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3564 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3565 for (v = vStart; v < vEnd; ++v) { 3566 PetscInt dof, off, noff, d; 3567 3568 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3569 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3570 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3571 for (d = 0; d < dof; ++d) { 3572 newCoords[noff+d] = coords[off+d]; 3573 } 3574 } 3575 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3576 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3577 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3578 ierr = PetscSectionDestroy(&newCoordSection);CHKERRQ(ierr); 3579 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3580 PetscFunctionReturn(0); 3581 } 3582 3583 #undef __FUNCT__ 3584 #define __FUNCT__ "DMPlexShiftSF_Private" 3585 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3586 { 3587 PetscInt *depthEnd; 3588 PetscInt depth = 0, d; 3589 PetscSF sfPoint, sfPointNew; 3590 const PetscSFNode *remotePoints; 3591 PetscSFNode *gremotePoints; 3592 const PetscInt *localPoints; 3593 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3594 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3595 PetscMPIInt numProcs; 3596 PetscErrorCode ierr; 3597 3598 PetscFunctionBegin; 3599 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3600 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3601 for (d = 0; d <= depth; ++d) { 3602 totShift += depthShift[d]; 3603 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3604 } 3605 /* Step 9: Convert pointSF */ 3606 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 3607 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3608 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3609 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3610 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3611 if (numRoots >= 0) { 3612 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3613 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3614 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3615 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3616 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3617 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3618 for (l = 0; l < numLeaves; ++l) { 3619 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3620 gremotePoints[l].rank = remotePoints[l].rank; 3621 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3622 } 3623 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3624 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3625 } 3626 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3627 PetscFunctionReturn(0); 3628 } 3629 3630 #undef __FUNCT__ 3631 #define __FUNCT__ "DMPlexShiftLabels_Private" 3632 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3633 { 3634 PetscSF sfPoint; 3635 DMLabel vtkLabel, ghostLabel; 3636 PetscInt *depthEnd; 3637 const PetscSFNode *leafRemote; 3638 const PetscInt *leafLocal; 3639 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3640 PetscMPIInt rank; 3641 PetscErrorCode ierr; 3642 3643 PetscFunctionBegin; 3644 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3645 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3646 for (d = 0; d <= depth; ++d) { 3647 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3648 } 3649 /* Step 10: Convert labels */ 3650 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3651 for (l = 0; l < numLabels; ++l) { 3652 DMLabel label, newlabel; 3653 const char *lname; 3654 PetscBool isDepth; 3655 IS valueIS; 3656 const PetscInt *values; 3657 PetscInt numValues, val; 3658 3659 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3660 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3661 if (isDepth) continue; 3662 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3663 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3664 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3665 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3666 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3667 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3668 for (val = 0; val < numValues; ++val) { 3669 IS pointIS; 3670 const PetscInt *points; 3671 PetscInt numPoints, p; 3672 3673 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3674 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3675 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3676 for (p = 0; p < numPoints; ++p) { 3677 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3678 3679 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3680 } 3681 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3682 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3683 } 3684 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3685 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3686 } 3687 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3688 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3689 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 3690 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3691 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3692 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3693 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3694 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3695 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3696 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3697 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3698 for (; c < leafLocal[l] && c < cEnd; ++c) { 3699 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3700 } 3701 if (leafLocal[l] >= cEnd) break; 3702 if (leafRemote[l].rank == rank) { 3703 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3704 } else { 3705 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3706 } 3707 } 3708 for (; c < cEnd; ++c) { 3709 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3710 } 3711 if (0) { 3712 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3713 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3714 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3715 } 3716 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3717 for (f = fStart; f < fEnd; ++f) { 3718 PetscInt numCells; 3719 3720 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3721 if (numCells < 2) { 3722 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3723 } else { 3724 const PetscInt *cells = NULL; 3725 PetscInt vA, vB; 3726 3727 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3728 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3729 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3730 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3731 } 3732 } 3733 if (0) { 3734 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3735 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3736 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3737 } 3738 PetscFunctionReturn(0); 3739 } 3740 3741 #undef __FUNCT__ 3742 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3743 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3744 { 3745 DMLabel label; 3746 IS valueIS; 3747 const PetscInt *values; 3748 PetscInt *depthShift; 3749 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3750 PetscErrorCode ierr; 3751 3752 PetscFunctionBegin; 3753 /* Count ghost cells */ 3754 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3755 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3756 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3757 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3758 3759 *numGhostCells = 0; 3760 for (fs = 0; fs < numFS; ++fs) { 3761 PetscInt numBdFaces; 3762 3763 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3764 3765 *numGhostCells += numBdFaces; 3766 } 3767 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3768 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3769 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3770 if (depth >= 0) depthShift[depth] = *numGhostCells; 3771 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3772 /* Step 3: Set cone/support sizes for new points */ 3773 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3774 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3775 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3776 } 3777 for (fs = 0; fs < numFS; ++fs) { 3778 IS faceIS; 3779 const PetscInt *faces; 3780 PetscInt numFaces, f; 3781 3782 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3783 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3784 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3785 for (f = 0; f < numFaces; ++f) { 3786 PetscInt size; 3787 3788 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3789 if (size != 1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3790 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3791 } 3792 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3793 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3794 } 3795 /* Step 4: Setup ghosted DM */ 3796 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3797 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3798 /* Step 6: Set cones and supports for new points */ 3799 ghostCell = cEnd; 3800 for (fs = 0; fs < numFS; ++fs) { 3801 IS faceIS; 3802 const PetscInt *faces; 3803 PetscInt numFaces, f; 3804 3805 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3806 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3807 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3808 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3809 PetscInt newFace = faces[f] + *numGhostCells; 3810 3811 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3812 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3813 } 3814 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3815 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3816 } 3817 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3818 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3819 /* Step 7: Stratify */ 3820 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3821 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3822 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3823 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3824 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3825 PetscFunctionReturn(0); 3826 } 3827 3828 #undef __FUNCT__ 3829 #define __FUNCT__ "DMPlexConstructGhostCells" 3830 /*@C 3831 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3832 3833 Collective on dm 3834 3835 Input Parameters: 3836 + dm - The original DM 3837 - labelName - The label specifying the boundary faces (this could be auto-generated) 3838 3839 Output Parameters: 3840 + numGhostCells - The number of ghost cells added to the DM 3841 - dmGhosted - The new DM 3842 3843 Level: developer 3844 3845 .seealso: DMCreate() 3846 */ 3847 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3848 { 3849 DM gdm; 3850 PetscInt dim; 3851 PetscErrorCode ierr; 3852 3853 PetscFunctionBegin; 3854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3855 PetscValidPointer(numGhostCells, 3); 3856 PetscValidPointer(dmGhosted, 4); 3857 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &gdm);CHKERRQ(ierr); 3858 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3859 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3860 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3861 switch (dim) { 3862 case 2: 3863 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3864 break; 3865 default: 3866 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3867 } 3868 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3869 *dmGhosted = gdm; 3870 PetscFunctionReturn(0); 3871 } 3872 3873 #undef __FUNCT__ 3874 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3875 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3876 { 3877 MPI_Comm comm; 3878 IS valueIS, *pointIS; 3879 const PetscInt *values, **splitPoints; 3880 PetscSection coordSection; 3881 Vec coordinates; 3882 PetscScalar *coords; 3883 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3884 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3885 PetscErrorCode ierr; 3886 3887 PetscFunctionBegin; 3888 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3889 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3890 /* Count split points and add cohesive cells */ 3891 if (label) { 3892 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3893 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3894 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3895 } 3896 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3897 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3898 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3899 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3900 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3901 for (d = 0; d <= depth; ++d) { 3902 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3903 numSplitPoints[d] = 0; 3904 splitPoints[d] = NULL; 3905 pointIS[d] = NULL; 3906 } 3907 for (sp = 0; sp < numSP; ++sp) { 3908 const PetscInt dep = values[sp]; 3909 3910 if ((dep < 0) || (dep > depth)) continue; 3911 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3912 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3913 if (pointIS[dep]) { 3914 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3915 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3916 } 3917 } 3918 if (depth >= 0) { 3919 /* Calculate number of additional points */ 3920 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3921 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3922 /* Calculate hybrid bound for each dimension */ 3923 pMaxNew[0] += depthShift[depth]; 3924 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3925 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3926 3927 /* Calculate point offset for each dimension */ 3928 depthOffset[depth] = 0; 3929 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3930 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3931 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3932 } 3933 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3934 /* Step 3: Set cone/support sizes for new points */ 3935 for (dep = 0; dep <= depth; ++dep) { 3936 for (p = 0; p < numSplitPoints[dep]; ++p) { 3937 const PetscInt oldp = splitPoints[dep][p]; 3938 const PetscInt newp = depthOffset[dep] + oldp; 3939 const PetscInt splitp = pMaxNew[dep] + p; 3940 const PetscInt *support; 3941 PetscInt coneSize, supportSize, q, e; 3942 3943 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3944 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3945 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3946 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3947 if (dep == depth-1) { 3948 const PetscInt ccell = pMaxNew[depth] + p; 3949 /* Add cohesive cells, they are prisms */ 3950 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3951 } else if (dep == 0) { 3952 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3953 3954 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3955 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3956 for (e = 0, q = 0; e < supportSize; ++e) { 3957 PetscInt val; 3958 3959 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3960 if ((val == 1) || (val == (shift + 1))) ++q; 3961 } 3962 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3963 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3964 for (e = 0, q = 0; e < supportSize; ++e) { 3965 PetscInt val; 3966 3967 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3968 if ((val == 1) || (val == -(shift + 1))) ++q; 3969 } 3970 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3971 /* Add cohesive edges */ 3972 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3973 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3974 } else if (dep == dim-2) { 3975 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3976 /* Split old edge: Faces in positive side cells and old split faces */ 3977 for (e = 0, q = 0; e < supportSize; ++e) { 3978 PetscInt val; 3979 3980 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3981 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 3982 } 3983 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 3984 /* Split new edge: Faces in negative side cells and new split faces */ 3985 for (e = 0, q = 0; e < supportSize; ++e) { 3986 PetscInt val; 3987 3988 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3989 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 3990 } 3991 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 3992 } 3993 } 3994 } 3995 /* Step 4: Setup split DM */ 3996 ierr = DMSetUp(sdm);CHKERRQ(ierr); 3997 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3998 /* Step 6: Set cones and supports for new points */ 3999 for (dep = 0; dep <= depth; ++dep) { 4000 for (p = 0; p < numSplitPoints[dep]; ++p) { 4001 const PetscInt oldp = splitPoints[dep][p]; 4002 const PetscInt newp = depthOffset[dep] + oldp; 4003 const PetscInt splitp = pMaxNew[dep] + p; 4004 const PetscInt *cone, *support, *ornt; 4005 PetscInt coneSize, supportSize, q, v, e, s; 4006 4007 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4008 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4009 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4010 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4011 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4012 if (dep == depth-1) { 4013 const PetscInt ccell = pMaxNew[depth] + p; 4014 const PetscInt *supportF; 4015 4016 /* Split face: copy in old face to new face to start */ 4017 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4018 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4019 /* Split old face: old vertices/edges in cone so no change */ 4020 /* Split new face: new vertices/edges in cone */ 4021 for (q = 0; q < coneSize; ++q) { 4022 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4023 4024 coneNew[2+q] = pMaxNew[dim-2] + v; 4025 } 4026 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4027 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4028 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4029 coneNew[0] = newp; 4030 coneNew[1] = splitp; 4031 for (q = 0; q < coneSize; ++q) { 4032 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4033 } 4034 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4035 4036 4037 for (s = 0; s < supportSize; ++s) { 4038 PetscInt val; 4039 4040 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4041 if (val < 0) { 4042 /* Split old face: Replace negative side cell with cohesive cell */ 4043 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4044 } else { 4045 /* Split new face: Replace positive side cell with cohesive cell */ 4046 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4047 } 4048 } 4049 } else if (dep == 0) { 4050 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4051 4052 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4053 for (e = 0, q = 0; e < supportSize; ++e) { 4054 PetscInt val; 4055 4056 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4057 if ((val == 1) || (val == (shift + 1))) { 4058 supportNew[q++] = depthOffset[1] + support[e]; 4059 } 4060 } 4061 supportNew[q] = cedge; 4062 4063 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4064 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4065 for (e = 0, q = 0; e < supportSize; ++e) { 4066 PetscInt val, edge; 4067 4068 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4069 if (val == 1) { 4070 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4071 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4072 supportNew[q++] = pMaxNew[1] + edge; 4073 } else if (val == -(shift + 1)) { 4074 supportNew[q++] = depthOffset[1] + support[e]; 4075 } 4076 } 4077 supportNew[q] = cedge; 4078 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4079 /* Cohesive edge: Old and new split vertex, punting on support */ 4080 coneNew[0] = newp; 4081 coneNew[1] = splitp; 4082 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4083 } else if (dep == dim-2) { 4084 /* Split old edge: old vertices in cone so no change */ 4085 /* Split new edge: new vertices in cone */ 4086 for (q = 0; q < coneSize; ++q) { 4087 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4088 4089 coneNew[q] = pMaxNew[dim-3] + v; 4090 } 4091 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4092 /* Split old edge: Faces in positive side cells and old split faces */ 4093 for (e = 0, q = 0; e < supportSize; ++e) { 4094 PetscInt val; 4095 4096 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4097 if ((val == dim-1) || (val == (shift + dim-1))) { 4098 supportNew[q++] = depthOffset[dim-1] + support[e]; 4099 } 4100 } 4101 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4102 /* Split new edge: Faces in negative side cells and new split faces */ 4103 for (e = 0, q = 0; e < supportSize; ++e) { 4104 PetscInt val, face; 4105 4106 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4107 if (val == dim-1) { 4108 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4109 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4110 supportNew[q++] = pMaxNew[dim-1] + face; 4111 } else if (val == -(shift + dim-1)) { 4112 supportNew[q++] = depthOffset[dim-1] + support[e]; 4113 } 4114 } 4115 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4116 } 4117 } 4118 } 4119 /* Step 6b: Replace split points in negative side cones */ 4120 for (sp = 0; sp < numSP; ++sp) { 4121 PetscInt dep = values[sp]; 4122 IS pIS; 4123 PetscInt numPoints; 4124 const PetscInt *points; 4125 4126 if (dep >= 0) continue; 4127 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4128 if (!pIS) continue; 4129 dep = -dep - shift; 4130 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4131 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4132 for (p = 0; p < numPoints; ++p) { 4133 const PetscInt oldp = points[p]; 4134 const PetscInt newp = depthOffset[dep] + oldp; 4135 const PetscInt *cone; 4136 PetscInt coneSize, c; 4137 PetscBool replaced = PETSC_FALSE; 4138 4139 /* Negative edge: replace split vertex */ 4140 /* Negative cell: replace split face */ 4141 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4142 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4143 for (c = 0; c < coneSize; ++c) { 4144 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4145 PetscInt csplitp, cp, val; 4146 4147 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4148 if (val == dep-1) { 4149 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4150 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4151 csplitp = pMaxNew[dep-1] + cp; 4152 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4153 replaced = PETSC_TRUE; 4154 } 4155 } 4156 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4157 } 4158 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4159 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4160 } 4161 /* Step 7: Stratify */ 4162 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4163 /* Step 8: Coordinates */ 4164 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4165 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4166 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4167 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4168 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4169 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4170 const PetscInt splitp = pMaxNew[0] + v; 4171 PetscInt dof, off, soff, d; 4172 4173 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4174 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4175 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4176 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4177 } 4178 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4179 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4180 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4181 /* Step 10: Labels */ 4182 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4183 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4184 for (dep = 0; dep <= depth; ++dep) { 4185 for (p = 0; p < numSplitPoints[dep]; ++p) { 4186 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4187 const PetscInt splitp = pMaxNew[dep] + p; 4188 PetscInt l; 4189 4190 for (l = 0; l < numLabels; ++l) { 4191 DMLabel mlabel; 4192 const char *lname; 4193 PetscInt val; 4194 4195 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4196 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4197 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4198 if (val >= 0) { 4199 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4200 if (dep == 0) { 4201 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4202 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4203 } 4204 } 4205 } 4206 } 4207 } 4208 for (sp = 0; sp < numSP; ++sp) { 4209 const PetscInt dep = values[sp]; 4210 4211 if ((dep < 0) || (dep > depth)) continue; 4212 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4213 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4214 } 4215 if (label) { 4216 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4217 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4218 } 4219 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4220 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4221 PetscFunctionReturn(0); 4222 } 4223 4224 #undef __FUNCT__ 4225 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4226 /*@C 4227 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4228 4229 Collective on dm 4230 4231 Input Parameters: 4232 + dm - The original DM 4233 - labelName - The label specifying the boundary faces (this could be auto-generated) 4234 4235 Output Parameters: 4236 - dmSplit - The new DM 4237 4238 Level: developer 4239 4240 .seealso: DMCreate() 4241 */ 4242 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4243 { 4244 DM sdm; 4245 PetscInt dim; 4246 PetscErrorCode ierr; 4247 4248 PetscFunctionBegin; 4249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4250 PetscValidPointer(dmSplit, 4); 4251 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 4252 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4253 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4254 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4255 switch (dim) { 4256 case 2: 4257 case 3: 4258 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4259 break; 4260 default: 4261 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4262 } 4263 *dmSplit = sdm; 4264 PetscFunctionReturn(0); 4265 } 4266 4267 #undef __FUNCT__ 4268 #define __FUNCT__ "DMLabelCohesiveComplete" 4269 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4270 { 4271 IS dimIS; 4272 const PetscInt *points; 4273 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4274 PetscErrorCode ierr; 4275 4276 PetscFunctionBegin; 4277 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4278 /* Cell orientation for face gives the side of the fault */ 4279 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4280 if (!dimIS) PetscFunctionReturn(0); 4281 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4282 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4283 for (p = 0; p < numPoints; ++p) { 4284 const PetscInt *support; 4285 PetscInt supportSize, s; 4286 4287 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4288 if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4289 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4290 for (s = 0; s < supportSize; ++s) { 4291 const PetscInt *cone, *ornt; 4292 PetscInt coneSize, c; 4293 PetscBool pos = PETSC_TRUE; 4294 4295 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4296 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4297 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4298 for (c = 0; c < coneSize; ++c) { 4299 if (cone[c] == points[p]) { 4300 if (ornt[c] >= 0) { 4301 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4302 } else { 4303 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4304 pos = PETSC_FALSE; 4305 } 4306 break; 4307 } 4308 } 4309 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]); 4310 /* Put faces touching the fault in the label */ 4311 for (c = 0; c < coneSize; ++c) { 4312 const PetscInt point = cone[c]; 4313 4314 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4315 if (val == -1) { 4316 PetscInt *closure = NULL; 4317 PetscInt closureSize, cl; 4318 4319 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4320 for (cl = 0; cl < closureSize*2; cl += 2) { 4321 const PetscInt clp = closure[cl]; 4322 4323 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4324 if ((val >= 0) && (val < dim-1)) { 4325 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4326 break; 4327 } 4328 } 4329 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4330 } 4331 } 4332 } 4333 } 4334 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4335 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4336 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4337 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4338 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4339 if (!dimIS) PetscFunctionReturn(0); 4340 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4341 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4342 for (p = 0; p < numPoints; ++p) { 4343 PetscInt *star = NULL; 4344 PetscInt starSize, s; 4345 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4346 4347 /* First mark cells connected to the fault */ 4348 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4349 while (again) { 4350 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4351 again = 0; 4352 for (s = 0; s < starSize*2; s += 2) { 4353 const PetscInt point = star[s]; 4354 const PetscInt *cone; 4355 PetscInt coneSize, c; 4356 4357 if ((point < cStart) || (point >= cEnd)) continue; 4358 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4359 if (val != -1) continue; 4360 again = 2; 4361 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4362 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4363 for (c = 0; c < coneSize; ++c) { 4364 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4365 if (val != -1) { 4366 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); 4367 if (val > 0) { 4368 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4369 } else { 4370 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4371 } 4372 again = 1; 4373 break; 4374 } 4375 } 4376 } 4377 } 4378 /* Classify the rest by cell membership */ 4379 for (s = 0; s < starSize*2; s += 2) { 4380 const PetscInt point = star[s]; 4381 4382 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4383 if (val == -1) { 4384 PetscInt *sstar = NULL; 4385 PetscInt sstarSize, ss; 4386 PetscBool marked = PETSC_FALSE; 4387 4388 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4389 for (ss = 0; ss < sstarSize*2; ss += 2) { 4390 const PetscInt spoint = sstar[ss]; 4391 4392 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4393 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4394 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4395 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4396 if (val > 0) { 4397 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4398 } else { 4399 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4400 } 4401 marked = PETSC_TRUE; 4402 break; 4403 } 4404 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4405 if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 4406 } 4407 } 4408 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4409 } 4410 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4411 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4412 PetscFunctionReturn(0); 4413 } 4414 4415 #undef __FUNCT__ 4416 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4417 /* 4418 This takes as input the common mesh generator output, a list of the vertices for each cell 4419 */ 4420 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4421 { 4422 PetscInt *cone, c, p; 4423 PetscErrorCode ierr; 4424 4425 PetscFunctionBegin; 4426 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4427 for (c = 0; c < numCells; ++c) { 4428 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4429 } 4430 ierr = DMSetUp(dm);CHKERRQ(ierr); 4431 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4432 for (c = 0; c < numCells; ++c) { 4433 for (p = 0; p < numCorners; ++p) { 4434 cone[p] = cells[c*numCorners+p]+numCells; 4435 } 4436 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4437 } 4438 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4439 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4440 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4441 PetscFunctionReturn(0); 4442 } 4443 4444 #undef __FUNCT__ 4445 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4446 /* 4447 This takes as input the coordinates for each vertex 4448 */ 4449 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4450 { 4451 PetscSection coordSection; 4452 Vec coordinates; 4453 PetscScalar *coords; 4454 PetscInt coordSize, v, d; 4455 PetscErrorCode ierr; 4456 4457 PetscFunctionBegin; 4458 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4459 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4460 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4461 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4462 for (v = numCells; v < numCells+numVertices; ++v) { 4463 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4464 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4465 } 4466 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4467 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4468 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4469 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4470 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4471 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4472 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4473 for (v = 0; v < numVertices; ++v) { 4474 for (d = 0; d < spaceDim; ++d) { 4475 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4476 } 4477 } 4478 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4479 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4480 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4481 PetscFunctionReturn(0); 4482 } 4483 4484 #undef __FUNCT__ 4485 #define __FUNCT__ "DMPlexCreateFromCellList" 4486 /* 4487 This takes as input the common mesh generator output, a list of the vertices for each cell 4488 */ 4489 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], PetscInt spaceDim, const double vertexCoords[], DM *dm) 4490 { 4491 PetscErrorCode ierr; 4492 4493 PetscFunctionBegin; 4494 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4495 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4496 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4497 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4498 if (interpolate) { 4499 DM idm; 4500 4501 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 4502 ierr = DMDestroy(dm);CHKERRQ(ierr); 4503 *dm = idm; 4504 } 4505 ierr = DMPlexBuildCoordinates_Private(*dm, spaceDim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4506 PetscFunctionReturn(0); 4507 } 4508 4509 #undef __FUNCT__ 4510 #define __FUNCT__ "DMPlexCreateFromDAG" 4511 /* 4512 This takes as input the raw Hasse Diagram data 4513 */ 4514 PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 4515 { 4516 Vec coordinates; 4517 PetscSection coordSection; 4518 PetscScalar *coords; 4519 PetscInt coordSize, firstVertex = numPoints[depth], pStart = 0, pEnd = 0, p, v, dim, d, off; 4520 PetscErrorCode ierr; 4521 4522 PetscFunctionBegin; 4523 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4524 for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 4525 ierr = DMPlexSetChart(dm, pStart, pEnd);CHKERRQ(ierr); 4526 for (p = pStart; p < pEnd; ++p) { 4527 ierr = DMPlexSetConeSize(dm, p, coneSize[p-pStart]);CHKERRQ(ierr); 4528 } 4529 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 4530 for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) { 4531 ierr = DMPlexSetCone(dm, p, &cones[off]);CHKERRQ(ierr); 4532 ierr = DMPlexSetConeOrientation(dm, p, &coneOrientations[off]);CHKERRQ(ierr); 4533 } 4534 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4535 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4536 /* Build coordinates */ 4537 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4538 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4539 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 4540 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);CHKERRQ(ierr); 4541 for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 4542 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 4543 } 4544 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4545 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4546 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 4547 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4548 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4549 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4550 for (v = 0; v < numPoints[0]; ++v) { 4551 PetscInt off; 4552 4553 ierr = PetscSectionGetOffset(coordSection, v+firstVertex, &off);CHKERRQ(ierr); 4554 for (d = 0; d < dim; ++d) { 4555 coords[off+d] = vertexCoords[v*dim+d]; 4556 } 4557 } 4558 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4559 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4560 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4561 PetscFunctionReturn(0); 4562 } 4563 4564 #if defined(PETSC_HAVE_TRIANGLE) 4565 #include <triangle.h> 4566 4567 #undef __FUNCT__ 4568 #define __FUNCT__ "InitInput_Triangle" 4569 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4570 { 4571 PetscFunctionBegin; 4572 inputCtx->numberofpoints = 0; 4573 inputCtx->numberofpointattributes = 0; 4574 inputCtx->pointlist = NULL; 4575 inputCtx->pointattributelist = NULL; 4576 inputCtx->pointmarkerlist = NULL; 4577 inputCtx->numberofsegments = 0; 4578 inputCtx->segmentlist = NULL; 4579 inputCtx->segmentmarkerlist = NULL; 4580 inputCtx->numberoftriangleattributes = 0; 4581 inputCtx->trianglelist = NULL; 4582 inputCtx->numberofholes = 0; 4583 inputCtx->holelist = NULL; 4584 inputCtx->numberofregions = 0; 4585 inputCtx->regionlist = NULL; 4586 PetscFunctionReturn(0); 4587 } 4588 4589 #undef __FUNCT__ 4590 #define __FUNCT__ "InitOutput_Triangle" 4591 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4592 { 4593 PetscFunctionBegin; 4594 outputCtx->numberofpoints = 0; 4595 outputCtx->pointlist = NULL; 4596 outputCtx->pointattributelist = NULL; 4597 outputCtx->pointmarkerlist = NULL; 4598 outputCtx->numberoftriangles = 0; 4599 outputCtx->trianglelist = NULL; 4600 outputCtx->triangleattributelist = NULL; 4601 outputCtx->neighborlist = NULL; 4602 outputCtx->segmentlist = NULL; 4603 outputCtx->segmentmarkerlist = NULL; 4604 outputCtx->numberofedges = 0; 4605 outputCtx->edgelist = NULL; 4606 outputCtx->edgemarkerlist = NULL; 4607 PetscFunctionReturn(0); 4608 } 4609 4610 #undef __FUNCT__ 4611 #define __FUNCT__ "FiniOutput_Triangle" 4612 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4613 { 4614 PetscFunctionBegin; 4615 free(outputCtx->pointmarkerlist); 4616 free(outputCtx->edgelist); 4617 free(outputCtx->edgemarkerlist); 4618 free(outputCtx->trianglelist); 4619 free(outputCtx->neighborlist); 4620 PetscFunctionReturn(0); 4621 } 4622 4623 #undef __FUNCT__ 4624 #define __FUNCT__ "DMPlexGenerate_Triangle" 4625 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4626 { 4627 MPI_Comm comm; 4628 PetscInt dim = 2; 4629 const PetscBool createConvexHull = PETSC_FALSE; 4630 const PetscBool constrained = PETSC_FALSE; 4631 struct triangulateio in; 4632 struct triangulateio out; 4633 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4634 PetscMPIInt rank; 4635 PetscErrorCode ierr; 4636 4637 PetscFunctionBegin; 4638 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4639 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4640 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4641 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4642 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4643 4644 in.numberofpoints = vEnd - vStart; 4645 if (in.numberofpoints > 0) { 4646 PetscSection coordSection; 4647 Vec coordinates; 4648 PetscScalar *array; 4649 4650 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4651 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4652 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4653 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4654 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4655 for (v = vStart; v < vEnd; ++v) { 4656 const PetscInt idx = v - vStart; 4657 PetscInt off, d; 4658 4659 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4660 for (d = 0; d < dim; ++d) { 4661 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4662 } 4663 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4664 } 4665 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4666 } 4667 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4668 in.numberofsegments = eEnd - eStart; 4669 if (in.numberofsegments > 0) { 4670 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4671 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4672 for (e = eStart; e < eEnd; ++e) { 4673 const PetscInt idx = e - eStart; 4674 const PetscInt *cone; 4675 4676 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4677 4678 in.segmentlist[idx*2+0] = cone[0] - vStart; 4679 in.segmentlist[idx*2+1] = cone[1] - vStart; 4680 4681 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4682 } 4683 } 4684 #if 0 /* Do not currently support holes */ 4685 PetscReal *holeCoords; 4686 PetscInt h, d; 4687 4688 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4689 if (in.numberofholes > 0) { 4690 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4691 for (h = 0; h < in.numberofholes; ++h) { 4692 for (d = 0; d < dim; ++d) { 4693 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4694 } 4695 } 4696 } 4697 #endif 4698 if (!rank) { 4699 char args[32]; 4700 4701 /* Take away 'Q' for verbose output */ 4702 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4703 if (createConvexHull) { 4704 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4705 } 4706 if (constrained) { 4707 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4708 } 4709 triangulate(args, &in, &out, NULL); 4710 } 4711 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4712 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4713 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4714 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4715 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4716 4717 { 4718 const PetscInt numCorners = 3; 4719 const PetscInt numCells = out.numberoftriangles; 4720 const PetscInt numVertices = out.numberofpoints; 4721 const int *cells = out.trianglelist; 4722 const double *meshCoords = out.pointlist; 4723 4724 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4725 /* Set labels */ 4726 for (v = 0; v < numVertices; ++v) { 4727 if (out.pointmarkerlist[v]) { 4728 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4729 } 4730 } 4731 if (interpolate) { 4732 for (e = 0; e < out.numberofedges; e++) { 4733 if (out.edgemarkerlist[e]) { 4734 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4735 const PetscInt *edges; 4736 PetscInt numEdges; 4737 4738 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4739 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4740 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4741 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4742 } 4743 } 4744 } 4745 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4746 } 4747 #if 0 /* Do not currently support holes */ 4748 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4749 #endif 4750 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4751 PetscFunctionReturn(0); 4752 } 4753 4754 #undef __FUNCT__ 4755 #define __FUNCT__ "DMPlexRefine_Triangle" 4756 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4757 { 4758 MPI_Comm comm; 4759 PetscInt dim = 2; 4760 struct triangulateio in; 4761 struct triangulateio out; 4762 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4763 PetscMPIInt rank; 4764 PetscErrorCode ierr; 4765 4766 PetscFunctionBegin; 4767 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4768 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4769 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4770 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4771 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4772 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4773 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4774 4775 in.numberofpoints = vEnd - vStart; 4776 if (in.numberofpoints > 0) { 4777 PetscSection coordSection; 4778 Vec coordinates; 4779 PetscScalar *array; 4780 4781 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4782 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4783 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4784 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4785 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4786 for (v = vStart; v < vEnd; ++v) { 4787 const PetscInt idx = v - vStart; 4788 PetscInt off, d; 4789 4790 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4791 for (d = 0; d < dim; ++d) { 4792 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4793 } 4794 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4795 } 4796 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4797 } 4798 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4799 4800 in.numberofcorners = 3; 4801 in.numberoftriangles = cEnd - cStart; 4802 4803 in.trianglearealist = (double*) maxVolumes; 4804 if (in.numberoftriangles > 0) { 4805 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4806 for (c = cStart; c < cEnd; ++c) { 4807 const PetscInt idx = c - cStart; 4808 PetscInt *closure = NULL; 4809 PetscInt closureSize; 4810 4811 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4812 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4813 for (v = 0; v < 3; ++v) { 4814 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4815 } 4816 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4817 } 4818 } 4819 /* TODO: Segment markers are missing on input */ 4820 #if 0 /* Do not currently support holes */ 4821 PetscReal *holeCoords; 4822 PetscInt h, d; 4823 4824 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4825 if (in.numberofholes > 0) { 4826 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4827 for (h = 0; h < in.numberofholes; ++h) { 4828 for (d = 0; d < dim; ++d) { 4829 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4830 } 4831 } 4832 } 4833 #endif 4834 if (!rank) { 4835 char args[32]; 4836 4837 /* Take away 'Q' for verbose output */ 4838 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4839 triangulate(args, &in, &out, NULL); 4840 } 4841 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4842 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4843 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4844 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4845 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4846 4847 { 4848 const PetscInt numCorners = 3; 4849 const PetscInt numCells = out.numberoftriangles; 4850 const PetscInt numVertices = out.numberofpoints; 4851 const int *cells = out.trianglelist; 4852 const double *meshCoords = out.pointlist; 4853 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4854 4855 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4856 /* Set labels */ 4857 for (v = 0; v < numVertices; ++v) { 4858 if (out.pointmarkerlist[v]) { 4859 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4860 } 4861 } 4862 if (interpolate) { 4863 PetscInt e; 4864 4865 for (e = 0; e < out.numberofedges; e++) { 4866 if (out.edgemarkerlist[e]) { 4867 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4868 const PetscInt *edges; 4869 PetscInt numEdges; 4870 4871 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4872 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4873 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4874 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4875 } 4876 } 4877 } 4878 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4879 } 4880 #if 0 /* Do not currently support holes */ 4881 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4882 #endif 4883 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4884 PetscFunctionReturn(0); 4885 } 4886 #endif 4887 4888 #if defined(PETSC_HAVE_TETGEN) 4889 #include <tetgen.h> 4890 #undef __FUNCT__ 4891 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4892 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4893 { 4894 MPI_Comm comm; 4895 const PetscInt dim = 3; 4896 ::tetgenio in; 4897 ::tetgenio out; 4898 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4899 PetscMPIInt rank; 4900 PetscErrorCode ierr; 4901 4902 PetscFunctionBegin; 4903 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4904 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4905 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4906 in.numberofpoints = vEnd - vStart; 4907 if (in.numberofpoints > 0) { 4908 PetscSection coordSection; 4909 Vec coordinates; 4910 PetscScalar *array; 4911 4912 in.pointlist = new double[in.numberofpoints*dim]; 4913 in.pointmarkerlist = new int[in.numberofpoints]; 4914 4915 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4916 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4917 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4918 for (v = vStart; v < vEnd; ++v) { 4919 const PetscInt idx = v - vStart; 4920 PetscInt off, d; 4921 4922 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4923 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4924 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4925 } 4926 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4927 } 4928 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4929 4930 in.numberoffacets = fEnd - fStart; 4931 if (in.numberoffacets > 0) { 4932 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4933 in.facetmarkerlist = new int[in.numberoffacets]; 4934 for (f = fStart; f < fEnd; ++f) { 4935 const PetscInt idx = f - fStart; 4936 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 4937 4938 in.facetlist[idx].numberofpolygons = 1; 4939 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4940 in.facetlist[idx].numberofholes = 0; 4941 in.facetlist[idx].holelist = NULL; 4942 4943 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4944 for (p = 0; p < numPoints*2; p += 2) { 4945 const PetscInt point = points[p]; 4946 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 4947 } 4948 4949 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4950 poly->numberofvertices = numVertices; 4951 poly->vertexlist = new int[poly->numberofvertices]; 4952 for (v = 0; v < numVertices; ++v) { 4953 const PetscInt vIdx = points[v] - vStart; 4954 poly->vertexlist[v] = vIdx; 4955 } 4956 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4957 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4958 } 4959 } 4960 if (!rank) { 4961 char args[32]; 4962 4963 /* Take away 'Q' for verbose output */ 4964 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4965 ::tetrahedralize(args, &in, &out); 4966 } 4967 { 4968 const PetscInt numCorners = 4; 4969 const PetscInt numCells = out.numberoftetrahedra; 4970 const PetscInt numVertices = out.numberofpoints; 4971 const int *cells = out.tetrahedronlist; 4972 const double *meshCoords = out.pointlist; 4973 4974 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4975 /* Set labels */ 4976 for (v = 0; v < numVertices; ++v) { 4977 if (out.pointmarkerlist[v]) { 4978 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4979 } 4980 } 4981 if (interpolate) { 4982 PetscInt e; 4983 4984 for (e = 0; e < out.numberofedges; e++) { 4985 if (out.edgemarkerlist[e]) { 4986 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4987 const PetscInt *edges; 4988 PetscInt numEdges; 4989 4990 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4991 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4992 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4993 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4994 } 4995 } 4996 for (f = 0; f < out.numberoftrifaces; f++) { 4997 if (out.trifacemarkerlist[f]) { 4998 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4999 const PetscInt *faces; 5000 PetscInt numFaces; 5001 5002 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5003 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5004 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5005 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5006 } 5007 } 5008 } 5009 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5010 } 5011 PetscFunctionReturn(0); 5012 } 5013 5014 #undef __FUNCT__ 5015 #define __FUNCT__ "DMPlexRefine_Tetgen" 5016 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5017 { 5018 MPI_Comm comm; 5019 const PetscInt dim = 3; 5020 ::tetgenio in; 5021 ::tetgenio out; 5022 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5023 PetscMPIInt rank; 5024 PetscErrorCode ierr; 5025 5026 PetscFunctionBegin; 5027 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5028 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5029 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5030 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5031 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5032 5033 in.numberofpoints = vEnd - vStart; 5034 if (in.numberofpoints > 0) { 5035 PetscSection coordSection; 5036 Vec coordinates; 5037 PetscScalar *array; 5038 5039 in.pointlist = new double[in.numberofpoints*dim]; 5040 in.pointmarkerlist = new int[in.numberofpoints]; 5041 5042 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5043 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5044 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5045 for (v = vStart; v < vEnd; ++v) { 5046 const PetscInt idx = v - vStart; 5047 PetscInt off, d; 5048 5049 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5050 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5051 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5052 } 5053 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5054 } 5055 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5056 5057 in.numberofcorners = 4; 5058 in.numberoftetrahedra = cEnd - cStart; 5059 in.tetrahedronvolumelist = (double*) maxVolumes; 5060 if (in.numberoftetrahedra > 0) { 5061 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5062 for (c = cStart; c < cEnd; ++c) { 5063 const PetscInt idx = c - cStart; 5064 PetscInt *closure = NULL; 5065 PetscInt closureSize; 5066 5067 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5068 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5069 for (v = 0; v < 4; ++v) { 5070 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5071 } 5072 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5073 } 5074 } 5075 /* TODO: Put in boundary faces with markers */ 5076 if (!rank) { 5077 char args[32]; 5078 5079 /* Take away 'Q' for verbose output */ 5080 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5081 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5082 ::tetrahedralize(args, &in, &out); 5083 } 5084 in.tetrahedronvolumelist = NULL; 5085 5086 { 5087 const PetscInt numCorners = 4; 5088 const PetscInt numCells = out.numberoftetrahedra; 5089 const PetscInt numVertices = out.numberofpoints; 5090 const int *cells = out.tetrahedronlist; 5091 const double *meshCoords = out.pointlist; 5092 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5093 5094 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 5095 /* Set labels */ 5096 for (v = 0; v < numVertices; ++v) { 5097 if (out.pointmarkerlist[v]) { 5098 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5099 } 5100 } 5101 if (interpolate) { 5102 PetscInt e, f; 5103 5104 for (e = 0; e < out.numberofedges; e++) { 5105 if (out.edgemarkerlist[e]) { 5106 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5107 const PetscInt *edges; 5108 PetscInt numEdges; 5109 5110 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5111 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5112 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5113 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5114 } 5115 } 5116 for (f = 0; f < out.numberoftrifaces; f++) { 5117 if (out.trifacemarkerlist[f]) { 5118 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5119 const PetscInt *faces; 5120 PetscInt numFaces; 5121 5122 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5123 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5124 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5125 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5126 } 5127 } 5128 } 5129 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5130 } 5131 PetscFunctionReturn(0); 5132 } 5133 #endif 5134 5135 #if defined(PETSC_HAVE_CTETGEN) 5136 #include "ctetgen.h" 5137 5138 #undef __FUNCT__ 5139 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5140 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5141 { 5142 MPI_Comm comm; 5143 const PetscInt dim = 3; 5144 PLC *in, *out; 5145 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5146 PetscMPIInt rank; 5147 PetscErrorCode ierr; 5148 5149 PetscFunctionBegin; 5150 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5151 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5152 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5153 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5154 ierr = PLCCreate(&in);CHKERRQ(ierr); 5155 ierr = PLCCreate(&out);CHKERRQ(ierr); 5156 5157 in->numberofpoints = vEnd - vStart; 5158 if (in->numberofpoints > 0) { 5159 PetscSection coordSection; 5160 Vec coordinates; 5161 PetscScalar *array; 5162 5163 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5164 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5165 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5166 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5167 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5168 for (v = vStart; v < vEnd; ++v) { 5169 const PetscInt idx = v - vStart; 5170 PetscInt off, d, m; 5171 5172 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5173 for (d = 0; d < dim; ++d) { 5174 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5175 } 5176 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5177 5178 in->pointmarkerlist[idx] = (int) m; 5179 } 5180 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5181 } 5182 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5183 5184 in->numberoffacets = fEnd - fStart; 5185 if (in->numberoffacets > 0) { 5186 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5187 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5188 for (f = fStart; f < fEnd; ++f) { 5189 const PetscInt idx = f - fStart; 5190 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5191 polygon *poly; 5192 5193 in->facetlist[idx].numberofpolygons = 1; 5194 5195 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5196 5197 in->facetlist[idx].numberofholes = 0; 5198 in->facetlist[idx].holelist = NULL; 5199 5200 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5201 for (p = 0; p < numPoints*2; p += 2) { 5202 const PetscInt point = points[p]; 5203 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5204 } 5205 5206 poly = in->facetlist[idx].polygonlist; 5207 poly->numberofvertices = numVertices; 5208 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5209 for (v = 0; v < numVertices; ++v) { 5210 const PetscInt vIdx = points[v] - vStart; 5211 poly->vertexlist[v] = vIdx; 5212 } 5213 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5214 in->facetmarkerlist[idx] = (int) m; 5215 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5216 } 5217 } 5218 if (!rank) { 5219 TetGenOpts t; 5220 5221 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5222 t.in = boundary; /* Should go away */ 5223 t.plc = 1; 5224 t.quality = 1; 5225 t.edgesout = 1; 5226 t.zeroindex = 1; 5227 t.quiet = 1; 5228 t.verbose = verbose; 5229 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5230 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5231 } 5232 { 5233 const PetscInt numCorners = 4; 5234 const PetscInt numCells = out->numberoftetrahedra; 5235 const PetscInt numVertices = out->numberofpoints; 5236 const int *cells = out->tetrahedronlist; 5237 const double *meshCoords = out->pointlist; 5238 5239 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 5240 /* Set labels */ 5241 for (v = 0; v < numVertices; ++v) { 5242 if (out->pointmarkerlist[v]) { 5243 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5244 } 5245 } 5246 if (interpolate) { 5247 PetscInt e; 5248 5249 for (e = 0; e < out->numberofedges; e++) { 5250 if (out->edgemarkerlist[e]) { 5251 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5252 const PetscInt *edges; 5253 PetscInt numEdges; 5254 5255 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5256 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5257 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5258 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5259 } 5260 } 5261 for (f = 0; f < out->numberoftrifaces; f++) { 5262 if (out->trifacemarkerlist[f]) { 5263 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5264 const PetscInt *faces; 5265 PetscInt numFaces; 5266 5267 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5268 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5269 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5270 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5271 } 5272 } 5273 } 5274 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5275 } 5276 5277 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5278 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5279 PetscFunctionReturn(0); 5280 } 5281 5282 #undef __FUNCT__ 5283 #define __FUNCT__ "DMPlexRefine_CTetgen" 5284 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5285 { 5286 MPI_Comm comm; 5287 const PetscInt dim = 3; 5288 PLC *in, *out; 5289 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5290 PetscMPIInt rank; 5291 PetscErrorCode ierr; 5292 5293 PetscFunctionBegin; 5294 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5295 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5296 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5297 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5298 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5299 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5300 ierr = PLCCreate(&in);CHKERRQ(ierr); 5301 ierr = PLCCreate(&out);CHKERRQ(ierr); 5302 5303 in->numberofpoints = vEnd - vStart; 5304 if (in->numberofpoints > 0) { 5305 PetscSection coordSection; 5306 Vec coordinates; 5307 PetscScalar *array; 5308 5309 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5310 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5311 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5312 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5313 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5314 for (v = vStart; v < vEnd; ++v) { 5315 const PetscInt idx = v - vStart; 5316 PetscInt off, d, m; 5317 5318 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5319 for (d = 0; d < dim; ++d) { 5320 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5321 } 5322 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5323 5324 in->pointmarkerlist[idx] = (int) m; 5325 } 5326 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5327 } 5328 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5329 5330 in->numberofcorners = 4; 5331 in->numberoftetrahedra = cEnd - cStart; 5332 in->tetrahedronvolumelist = maxVolumes; 5333 if (in->numberoftetrahedra > 0) { 5334 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5335 for (c = cStart; c < cEnd; ++c) { 5336 const PetscInt idx = c - cStart; 5337 PetscInt *closure = NULL; 5338 PetscInt closureSize; 5339 5340 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5341 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5342 for (v = 0; v < 4; ++v) { 5343 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5344 } 5345 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5346 } 5347 } 5348 if (!rank) { 5349 TetGenOpts t; 5350 5351 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5352 5353 t.in = dm; /* Should go away */ 5354 t.refine = 1; 5355 t.varvolume = 1; 5356 t.quality = 1; 5357 t.edgesout = 1; 5358 t.zeroindex = 1; 5359 t.quiet = 1; 5360 t.verbose = verbose; /* Change this */ 5361 5362 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5363 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5364 } 5365 { 5366 const PetscInt numCorners = 4; 5367 const PetscInt numCells = out->numberoftetrahedra; 5368 const PetscInt numVertices = out->numberofpoints; 5369 const int *cells = out->tetrahedronlist; 5370 const double *meshCoords = out->pointlist; 5371 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5372 5373 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 5374 /* Set labels */ 5375 for (v = 0; v < numVertices; ++v) { 5376 if (out->pointmarkerlist[v]) { 5377 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5378 } 5379 } 5380 if (interpolate) { 5381 PetscInt e, f; 5382 5383 for (e = 0; e < out->numberofedges; e++) { 5384 if (out->edgemarkerlist[e]) { 5385 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5386 const PetscInt *edges; 5387 PetscInt numEdges; 5388 5389 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5390 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5391 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5392 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5393 } 5394 } 5395 for (f = 0; f < out->numberoftrifaces; f++) { 5396 if (out->trifacemarkerlist[f]) { 5397 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5398 const PetscInt *faces; 5399 PetscInt numFaces; 5400 5401 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5402 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5403 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5404 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5405 } 5406 } 5407 } 5408 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5409 } 5410 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5411 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5412 PetscFunctionReturn(0); 5413 } 5414 #endif 5415 5416 #undef __FUNCT__ 5417 #define __FUNCT__ "DMPlexGenerate" 5418 /*@C 5419 DMPlexGenerate - Generates a mesh. 5420 5421 Not Collective 5422 5423 Input Parameters: 5424 + boundary - The DMPlex boundary object 5425 . name - The mesh generation package name 5426 - interpolate - Flag to create intermediate mesh elements 5427 5428 Output Parameter: 5429 . mesh - The DMPlex object 5430 5431 Level: intermediate 5432 5433 .keywords: mesh, elements 5434 .seealso: DMPlexCreate(), DMRefine() 5435 @*/ 5436 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5437 { 5438 PetscInt dim; 5439 char genname[1024]; 5440 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5441 PetscErrorCode ierr; 5442 5443 PetscFunctionBegin; 5444 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5445 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5446 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5447 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5448 if (flg) name = genname; 5449 if (name) { 5450 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5451 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5452 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5453 } 5454 switch (dim) { 5455 case 1: 5456 if (!name || isTriangle) { 5457 #if defined(PETSC_HAVE_TRIANGLE) 5458 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5459 #else 5460 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5461 #endif 5462 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5463 break; 5464 case 2: 5465 if (!name || isCTetgen) { 5466 #if defined(PETSC_HAVE_CTETGEN) 5467 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5468 #else 5469 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5470 #endif 5471 } else if (isTetgen) { 5472 #if defined(PETSC_HAVE_TETGEN) 5473 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5474 #else 5475 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5476 #endif 5477 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5478 break; 5479 default: 5480 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5481 } 5482 PetscFunctionReturn(0); 5483 } 5484 5485 typedef PetscInt CellRefiner; 5486 5487 #undef __FUNCT__ 5488 #define __FUNCT__ "GetDepthStart_Private" 5489 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5490 { 5491 PetscFunctionBegin; 5492 if (cStart) *cStart = 0; 5493 if (vStart) *vStart = depthSize[depth]; 5494 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5495 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5496 PetscFunctionReturn(0); 5497 } 5498 5499 #undef __FUNCT__ 5500 #define __FUNCT__ "GetDepthEnd_Private" 5501 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5502 { 5503 PetscFunctionBegin; 5504 if (cEnd) *cEnd = depthSize[depth]; 5505 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5506 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5507 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5508 PetscFunctionReturn(0); 5509 } 5510 5511 #undef __FUNCT__ 5512 #define __FUNCT__ "CellRefinerGetSizes" 5513 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5514 { 5515 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5516 PetscErrorCode ierr; 5517 5518 PetscFunctionBegin; 5519 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5520 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5521 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5522 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5523 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5524 switch (refiner) { 5525 case 1: 5526 /* Simplicial 2D */ 5527 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5528 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5529 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5530 break; 5531 case 3: 5532 /* Hybrid 2D */ 5533 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5534 cMax = PetscMin(cEnd, cMax); 5535 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5536 fMax = PetscMin(fEnd, fMax); 5537 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5538 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 */ 5539 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5540 break; 5541 case 2: 5542 /* Hex 2D */ 5543 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5544 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5545 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5546 break; 5547 default: 5548 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5549 } 5550 PetscFunctionReturn(0); 5551 } 5552 5553 #undef __FUNCT__ 5554 #define __FUNCT__ "CellRefinerSetConeSizes" 5555 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5556 { 5557 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5558 PetscErrorCode ierr; 5559 5560 PetscFunctionBegin; 5561 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5562 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5563 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5564 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5565 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5566 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5567 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5568 switch (refiner) { 5569 case 1: 5570 /* Simplicial 2D */ 5571 /* All cells have 3 faces */ 5572 for (c = cStart; c < cEnd; ++c) { 5573 for (r = 0; r < 4; ++r) { 5574 const PetscInt newp = (c - cStart)*4 + r; 5575 5576 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5577 } 5578 } 5579 /* Split faces have 2 vertices and the same cells as the parent */ 5580 for (f = fStart; f < fEnd; ++f) { 5581 for (r = 0; r < 2; ++r) { 5582 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5583 PetscInt size; 5584 5585 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5586 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5587 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5588 } 5589 } 5590 /* Interior faces have 2 vertices and 2 cells */ 5591 for (c = cStart; c < cEnd; ++c) { 5592 for (r = 0; r < 3; ++r) { 5593 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5594 5595 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5596 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5597 } 5598 } 5599 /* Old vertices have identical supports */ 5600 for (v = vStart; v < vEnd; ++v) { 5601 const PetscInt newp = vStartNew + (v - vStart); 5602 PetscInt size; 5603 5604 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5605 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5606 } 5607 /* Face vertices have 2 + cells*2 supports */ 5608 for (f = fStart; f < fEnd; ++f) { 5609 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5610 PetscInt size; 5611 5612 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5613 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5614 } 5615 break; 5616 case 2: 5617 /* Hex 2D */ 5618 /* All cells have 4 faces */ 5619 for (c = cStart; c < cEnd; ++c) { 5620 for (r = 0; r < 4; ++r) { 5621 const PetscInt newp = (c - cStart)*4 + r; 5622 5623 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5624 } 5625 } 5626 /* Split faces have 2 vertices and the same cells as the parent */ 5627 for (f = fStart; f < fEnd; ++f) { 5628 for (r = 0; r < 2; ++r) { 5629 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5630 PetscInt size; 5631 5632 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5633 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5634 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5635 } 5636 } 5637 /* Interior faces have 2 vertices and 2 cells */ 5638 for (c = cStart; c < cEnd; ++c) { 5639 for (r = 0; r < 4; ++r) { 5640 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5641 5642 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5643 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5644 } 5645 } 5646 /* Old vertices have identical supports */ 5647 for (v = vStart; v < vEnd; ++v) { 5648 const PetscInt newp = vStartNew + (v - vStart); 5649 PetscInt size; 5650 5651 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5652 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5653 } 5654 /* Face vertices have 2 + cells supports */ 5655 for (f = fStart; f < fEnd; ++f) { 5656 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5657 PetscInt size; 5658 5659 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5660 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5661 } 5662 /* Cell vertices have 4 supports */ 5663 for (c = cStart; c < cEnd; ++c) { 5664 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5665 5666 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5667 } 5668 break; 5669 case 3: 5670 /* Hybrid 2D */ 5671 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5672 cMax = PetscMin(cEnd, cMax); 5673 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5674 fMax = PetscMin(fEnd, fMax); 5675 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5676 /* Interior cells have 3 faces */ 5677 for (c = cStart; c < cMax; ++c) { 5678 for (r = 0; r < 4; ++r) { 5679 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5680 5681 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5682 } 5683 } 5684 /* Hybrid cells have 4 faces */ 5685 for (c = cMax; c < cEnd; ++c) { 5686 for (r = 0; r < 2; ++r) { 5687 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5688 5689 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5690 } 5691 } 5692 /* Interior split faces have 2 vertices and the same cells as the parent */ 5693 for (f = fStart; f < fMax; ++f) { 5694 for (r = 0; r < 2; ++r) { 5695 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5696 PetscInt size; 5697 5698 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5699 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5700 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5701 } 5702 } 5703 /* Interior cell faces have 2 vertices and 2 cells */ 5704 for (c = cStart; c < cMax; ++c) { 5705 for (r = 0; r < 3; ++r) { 5706 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5707 5708 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5709 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5710 } 5711 } 5712 /* Hybrid faces have 2 vertices and the same cells */ 5713 for (f = fMax; f < fEnd; ++f) { 5714 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5715 PetscInt size; 5716 5717 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5718 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5719 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5720 } 5721 /* Hybrid cell faces have 2 vertices and 2 cells */ 5722 for (c = cMax; c < cEnd; ++c) { 5723 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5724 5725 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5726 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5727 } 5728 /* Old vertices have identical supports */ 5729 for (v = vStart; v < vEnd; ++v) { 5730 const PetscInt newp = vStartNew + (v - vStart); 5731 PetscInt size; 5732 5733 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5734 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5735 } 5736 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5737 for (f = fStart; f < fMax; ++f) { 5738 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5739 const PetscInt *support; 5740 PetscInt size, newSize = 2, s; 5741 5742 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5743 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5744 for (s = 0; s < size; ++s) { 5745 if (support[s] >= cMax) newSize += 1; 5746 else newSize += 2; 5747 } 5748 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5749 } 5750 break; 5751 default: 5752 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5753 } 5754 PetscFunctionReturn(0); 5755 } 5756 5757 #undef __FUNCT__ 5758 #define __FUNCT__ "CellRefinerSetCones" 5759 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5760 { 5761 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; 5762 PetscInt maxSupportSize, *supportRef; 5763 PetscErrorCode ierr; 5764 5765 PetscFunctionBegin; 5766 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5767 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5768 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5769 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5770 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5771 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5772 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5773 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5774 switch (refiner) { 5775 case 1: 5776 /* Simplicial 2D */ 5777 /* 5778 2 5779 |\ 5780 | \ 5781 | \ 5782 | \ 5783 | C \ 5784 | \ 5785 | \ 5786 2---1---1 5787 |\ D / \ 5788 | 2 0 \ 5789 |A \ / B \ 5790 0---0-------1 5791 */ 5792 /* All cells have 3 faces */ 5793 for (c = cStart; c < cEnd; ++c) { 5794 const PetscInt newp = cStartNew + (c - cStart)*4; 5795 const PetscInt *cone, *ornt; 5796 PetscInt coneNew[3], orntNew[3]; 5797 5798 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5799 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5800 /* A triangle */ 5801 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5802 orntNew[0] = ornt[0]; 5803 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5804 orntNew[1] = -2; 5805 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5806 orntNew[2] = ornt[2]; 5807 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5808 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5809 #if 1 5810 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); 5811 for (p = 0; p < 3; ++p) { 5812 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); 5813 } 5814 #endif 5815 /* B triangle */ 5816 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5817 orntNew[0] = ornt[0]; 5818 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5819 orntNew[1] = ornt[1]; 5820 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5821 orntNew[2] = -2; 5822 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5823 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5824 #if 1 5825 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); 5826 for (p = 0; p < 3; ++p) { 5827 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); 5828 } 5829 #endif 5830 /* C triangle */ 5831 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5832 orntNew[0] = -2; 5833 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5834 orntNew[1] = ornt[1]; 5835 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5836 orntNew[2] = ornt[2]; 5837 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5838 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5839 #if 1 5840 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); 5841 for (p = 0; p < 3; ++p) { 5842 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); 5843 } 5844 #endif 5845 /* D triangle */ 5846 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5847 orntNew[0] = 0; 5848 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5849 orntNew[1] = 0; 5850 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5851 orntNew[2] = 0; 5852 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5853 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5854 #if 1 5855 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); 5856 for (p = 0; p < 3; ++p) { 5857 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); 5858 } 5859 #endif 5860 } 5861 /* Split faces have 2 vertices and the same cells as the parent */ 5862 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5863 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5864 for (f = fStart; f < fEnd; ++f) { 5865 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5866 5867 for (r = 0; r < 2; ++r) { 5868 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5869 const PetscInt *cone, *support; 5870 PetscInt coneNew[2], coneSize, c, supportSize, s; 5871 5872 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5873 coneNew[0] = vStartNew + (cone[0] - vStart); 5874 coneNew[1] = vStartNew + (cone[1] - vStart); 5875 coneNew[(r+1)%2] = newv; 5876 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5877 #if 1 5878 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5879 for (p = 0; p < 2; ++p) { 5880 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); 5881 } 5882 #endif 5883 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5884 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5885 for (s = 0; s < supportSize; ++s) { 5886 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5887 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5888 for (c = 0; c < coneSize; ++c) { 5889 if (cone[c] == f) break; 5890 } 5891 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5892 } 5893 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5894 #if 1 5895 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5896 for (p = 0; p < supportSize; ++p) { 5897 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); 5898 } 5899 #endif 5900 } 5901 } 5902 /* Interior faces have 2 vertices and 2 cells */ 5903 for (c = cStart; c < cEnd; ++c) { 5904 const PetscInt *cone; 5905 5906 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5907 for (r = 0; r < 3; ++r) { 5908 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5909 PetscInt coneNew[2]; 5910 PetscInt supportNew[2]; 5911 5912 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5913 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5914 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5915 #if 1 5916 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5917 for (p = 0; p < 2; ++p) { 5918 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); 5919 } 5920 #endif 5921 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5922 supportNew[1] = (c - cStart)*4 + 3; 5923 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5924 #if 1 5925 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5926 for (p = 0; p < 2; ++p) { 5927 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); 5928 } 5929 #endif 5930 } 5931 } 5932 /* Old vertices have identical supports */ 5933 for (v = vStart; v < vEnd; ++v) { 5934 const PetscInt newp = vStartNew + (v - vStart); 5935 const PetscInt *support, *cone; 5936 PetscInt size, s; 5937 5938 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5939 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5940 for (s = 0; s < size; ++s) { 5941 PetscInt r = 0; 5942 5943 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5944 if (cone[1] == v) r = 1; 5945 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5946 } 5947 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5948 #if 1 5949 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5950 for (p = 0; p < size; ++p) { 5951 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); 5952 } 5953 #endif 5954 } 5955 /* Face vertices have 2 + cells*2 supports */ 5956 for (f = fStart; f < fEnd; ++f) { 5957 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5958 const PetscInt *cone, *support; 5959 PetscInt size, s; 5960 5961 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5962 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5963 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5964 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5965 for (s = 0; s < size; ++s) { 5966 PetscInt r = 0; 5967 5968 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5969 if (cone[1] == f) r = 1; 5970 else if (cone[2] == f) r = 2; 5971 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5972 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5973 } 5974 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5975 #if 1 5976 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5977 for (p = 0; p < 2+size*2; ++p) { 5978 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); 5979 } 5980 #endif 5981 } 5982 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5983 break; 5984 case 2: 5985 /* Hex 2D */ 5986 /* 5987 3---------2---------2 5988 | | | 5989 | D 2 C | 5990 | | | 5991 3----3----0----1----1 5992 | | | 5993 | A 0 B | 5994 | | | 5995 0---------0---------1 5996 */ 5997 /* All cells have 4 faces */ 5998 for (c = cStart; c < cEnd; ++c) { 5999 const PetscInt newp = (c - cStart)*4; 6000 const PetscInt *cone, *ornt; 6001 PetscInt coneNew[4], orntNew[4]; 6002 6003 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6004 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6005 /* A quad */ 6006 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6007 orntNew[0] = ornt[0]; 6008 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6009 orntNew[1] = 0; 6010 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6011 orntNew[2] = -2; 6012 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6013 orntNew[3] = ornt[3]; 6014 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6015 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6016 #if 1 6017 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); 6018 for (p = 0; p < 4; ++p) { 6019 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); 6020 } 6021 #endif 6022 /* B quad */ 6023 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6024 orntNew[0] = ornt[0]; 6025 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6026 orntNew[1] = ornt[1]; 6027 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6028 orntNew[2] = 0; 6029 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6030 orntNew[3] = -2; 6031 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6032 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6033 #if 1 6034 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); 6035 for (p = 0; p < 4; ++p) { 6036 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); 6037 } 6038 #endif 6039 /* C quad */ 6040 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6041 orntNew[0] = -2; 6042 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6043 orntNew[1] = ornt[1]; 6044 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6045 orntNew[2] = ornt[2]; 6046 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6047 orntNew[3] = 0; 6048 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6049 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6050 #if 1 6051 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); 6052 for (p = 0; p < 4; ++p) { 6053 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); 6054 } 6055 #endif 6056 /* D quad */ 6057 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6058 orntNew[0] = 0; 6059 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6060 orntNew[1] = -2; 6061 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6062 orntNew[2] = ornt[2]; 6063 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6064 orntNew[3] = ornt[3]; 6065 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6066 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6067 #if 1 6068 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); 6069 for (p = 0; p < 4; ++p) { 6070 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); 6071 } 6072 #endif 6073 } 6074 /* Split faces have 2 vertices and the same cells as the parent */ 6075 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6076 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6077 for (f = fStart; f < fEnd; ++f) { 6078 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6079 6080 for (r = 0; r < 2; ++r) { 6081 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6082 const PetscInt *cone, *support; 6083 PetscInt coneNew[2], coneSize, c, supportSize, s; 6084 6085 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6086 coneNew[0] = vStartNew + (cone[0] - vStart); 6087 coneNew[1] = vStartNew + (cone[1] - vStart); 6088 coneNew[(r+1)%2] = newv; 6089 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6090 #if 1 6091 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6092 for (p = 0; p < 2; ++p) { 6093 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); 6094 } 6095 #endif 6096 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6097 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6098 for (s = 0; s < supportSize; ++s) { 6099 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6100 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6101 for (c = 0; c < coneSize; ++c) { 6102 if (cone[c] == f) break; 6103 } 6104 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6105 } 6106 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6107 #if 1 6108 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6109 for (p = 0; p < supportSize; ++p) { 6110 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); 6111 } 6112 #endif 6113 } 6114 } 6115 /* Interior faces have 2 vertices and 2 cells */ 6116 for (c = cStart; c < cEnd; ++c) { 6117 const PetscInt *cone; 6118 PetscInt coneNew[2], supportNew[2]; 6119 6120 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6121 for (r = 0; r < 4; ++r) { 6122 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6123 6124 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6125 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6126 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6127 #if 1 6128 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6129 for (p = 0; p < 2; ++p) { 6130 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); 6131 } 6132 #endif 6133 supportNew[0] = (c - cStart)*4 + r; 6134 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6135 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6136 #if 1 6137 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6138 for (p = 0; p < 2; ++p) { 6139 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); 6140 } 6141 #endif 6142 } 6143 } 6144 /* Old vertices have identical supports */ 6145 for (v = vStart; v < vEnd; ++v) { 6146 const PetscInt newp = vStartNew + (v - vStart); 6147 const PetscInt *support, *cone; 6148 PetscInt size, s; 6149 6150 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6151 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6152 for (s = 0; s < size; ++s) { 6153 PetscInt r = 0; 6154 6155 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6156 if (cone[1] == v) r = 1; 6157 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6158 } 6159 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6160 #if 1 6161 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6162 for (p = 0; p < size; ++p) { 6163 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); 6164 } 6165 #endif 6166 } 6167 /* Face vertices have 2 + cells supports */ 6168 for (f = fStart; f < fEnd; ++f) { 6169 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6170 const PetscInt *cone, *support; 6171 PetscInt size, s; 6172 6173 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6174 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6175 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6176 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6177 for (s = 0; s < size; ++s) { 6178 PetscInt r = 0; 6179 6180 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6181 if (cone[1] == f) r = 1; 6182 else if (cone[2] == f) r = 2; 6183 else if (cone[3] == f) r = 3; 6184 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6185 } 6186 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6187 #if 1 6188 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6189 for (p = 0; p < 2+size; ++p) { 6190 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); 6191 } 6192 #endif 6193 } 6194 /* Cell vertices have 4 supports */ 6195 for (c = cStart; c < cEnd; ++c) { 6196 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6197 PetscInt supportNew[4]; 6198 6199 for (r = 0; r < 4; ++r) { 6200 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6201 } 6202 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6203 } 6204 break; 6205 case 3: 6206 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6207 cMax = PetscMin(cEnd, cMax); 6208 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6209 fMax = PetscMin(fEnd, fMax); 6210 /* Interior cells have 3 faces */ 6211 for (c = cStart; c < cMax; ++c) { 6212 const PetscInt newp = cStartNew + (c - cStart)*4; 6213 const PetscInt *cone, *ornt; 6214 PetscInt coneNew[3], orntNew[3]; 6215 6216 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6217 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6218 /* A triangle */ 6219 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6220 orntNew[0] = ornt[0]; 6221 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6222 orntNew[1] = -2; 6223 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6224 orntNew[2] = ornt[2]; 6225 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6226 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6227 #if 1 6228 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); 6229 for (p = 0; p < 3; ++p) { 6230 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); 6231 } 6232 #endif 6233 /* B triangle */ 6234 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6235 orntNew[0] = ornt[0]; 6236 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6237 orntNew[1] = ornt[1]; 6238 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6239 orntNew[2] = -2; 6240 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6241 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6242 #if 1 6243 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); 6244 for (p = 0; p < 3; ++p) { 6245 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); 6246 } 6247 #endif 6248 /* C triangle */ 6249 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6250 orntNew[0] = -2; 6251 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6252 orntNew[1] = ornt[1]; 6253 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6254 orntNew[2] = ornt[2]; 6255 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6256 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6257 #if 1 6258 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); 6259 for (p = 0; p < 3; ++p) { 6260 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); 6261 } 6262 #endif 6263 /* D triangle */ 6264 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6265 orntNew[0] = 0; 6266 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6267 orntNew[1] = 0; 6268 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6269 orntNew[2] = 0; 6270 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6271 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6272 #if 1 6273 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); 6274 for (p = 0; p < 3; ++p) { 6275 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); 6276 } 6277 #endif 6278 } 6279 /* 6280 2----3----3 6281 | | 6282 | B | 6283 | | 6284 0----4--- 1 6285 | | 6286 | A | 6287 | | 6288 0----2----1 6289 */ 6290 /* Hybrid cells have 4 faces */ 6291 for (c = cMax; c < cEnd; ++c) { 6292 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6293 const PetscInt *cone, *ornt; 6294 PetscInt coneNew[4], orntNew[4]; 6295 6296 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6297 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6298 /* A quad */ 6299 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6300 orntNew[0] = ornt[0]; 6301 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6302 orntNew[1] = ornt[1]; 6303 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6304 orntNew[2] = 0; 6305 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6306 orntNew[3] = 0; 6307 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6308 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6309 #if 1 6310 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); 6311 for (p = 0; p < 4; ++p) { 6312 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); 6313 } 6314 #endif 6315 /* B quad */ 6316 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6317 orntNew[0] = ornt[0]; 6318 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6319 orntNew[1] = ornt[1]; 6320 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6321 orntNew[2] = 0; 6322 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6323 orntNew[3] = 0; 6324 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6325 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6326 #if 1 6327 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); 6328 for (p = 0; p < 4; ++p) { 6329 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); 6330 } 6331 #endif 6332 } 6333 /* Interior split faces have 2 vertices and the same cells as the parent */ 6334 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6335 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6336 for (f = fStart; f < fMax; ++f) { 6337 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6338 6339 for (r = 0; r < 2; ++r) { 6340 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6341 const PetscInt *cone, *support; 6342 PetscInt coneNew[2], coneSize, c, supportSize, s; 6343 6344 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6345 coneNew[0] = vStartNew + (cone[0] - vStart); 6346 coneNew[1] = vStartNew + (cone[1] - vStart); 6347 coneNew[(r+1)%2] = newv; 6348 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6349 #if 1 6350 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6351 for (p = 0; p < 2; ++p) { 6352 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); 6353 } 6354 #endif 6355 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6356 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6357 for (s = 0; s < supportSize; ++s) { 6358 if (support[s] >= cMax) { 6359 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6360 } else { 6361 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6362 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6363 for (c = 0; c < coneSize; ++c) { 6364 if (cone[c] == f) break; 6365 } 6366 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6367 } 6368 } 6369 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6370 #if 1 6371 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6372 for (p = 0; p < supportSize; ++p) { 6373 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); 6374 } 6375 #endif 6376 } 6377 } 6378 /* Interior cell faces have 2 vertices and 2 cells */ 6379 for (c = cStart; c < cMax; ++c) { 6380 const PetscInt *cone; 6381 6382 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6383 for (r = 0; r < 3; ++r) { 6384 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6385 PetscInt coneNew[2]; 6386 PetscInt supportNew[2]; 6387 6388 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6389 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6390 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6391 #if 1 6392 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6393 for (p = 0; p < 2; ++p) { 6394 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); 6395 } 6396 #endif 6397 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6398 supportNew[1] = (c - cStart)*4 + 3; 6399 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6400 #if 1 6401 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6402 for (p = 0; p < 2; ++p) { 6403 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); 6404 } 6405 #endif 6406 } 6407 } 6408 /* Interior hybrid faces have 2 vertices and the same cells */ 6409 for (f = fMax; f < fEnd; ++f) { 6410 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6411 const PetscInt *cone; 6412 const PetscInt *support; 6413 PetscInt coneNew[2]; 6414 PetscInt supportNew[2]; 6415 PetscInt size, s, r; 6416 6417 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6418 coneNew[0] = vStartNew + (cone[0] - vStart); 6419 coneNew[1] = vStartNew + (cone[1] - vStart); 6420 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6421 #if 1 6422 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6423 for (p = 0; p < 2; ++p) { 6424 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); 6425 } 6426 #endif 6427 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6428 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6429 for (s = 0; s < size; ++s) { 6430 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6431 for (r = 0; r < 2; ++r) { 6432 if (cone[r+2] == f) break; 6433 } 6434 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6435 } 6436 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6437 #if 1 6438 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6439 for (p = 0; p < size; ++p) { 6440 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); 6441 } 6442 #endif 6443 } 6444 /* Cell hybrid faces have 2 vertices and 2 cells */ 6445 for (c = cMax; c < cEnd; ++c) { 6446 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6447 const PetscInt *cone; 6448 PetscInt coneNew[2]; 6449 PetscInt supportNew[2]; 6450 6451 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6452 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6453 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6454 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6455 #if 1 6456 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6457 for (p = 0; p < 2; ++p) { 6458 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); 6459 } 6460 #endif 6461 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6462 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6463 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6464 #if 1 6465 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6466 for (p = 0; p < 2; ++p) { 6467 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); 6468 } 6469 #endif 6470 } 6471 /* Old vertices have identical supports */ 6472 for (v = vStart; v < vEnd; ++v) { 6473 const PetscInt newp = vStartNew + (v - vStart); 6474 const PetscInt *support, *cone; 6475 PetscInt size, s; 6476 6477 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6478 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6479 for (s = 0; s < size; ++s) { 6480 if (support[s] >= fMax) { 6481 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6482 } else { 6483 PetscInt r = 0; 6484 6485 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6486 if (cone[1] == v) r = 1; 6487 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6488 } 6489 } 6490 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6491 #if 1 6492 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6493 for (p = 0; p < size; ++p) { 6494 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); 6495 } 6496 #endif 6497 } 6498 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6499 for (f = fStart; f < fMax; ++f) { 6500 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6501 const PetscInt *cone, *support; 6502 PetscInt size, newSize = 2, s; 6503 6504 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6505 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6506 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6507 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6508 for (s = 0; s < size; ++s) { 6509 PetscInt r = 0; 6510 6511 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6512 if (support[s] >= cMax) { 6513 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6514 6515 newSize += 1; 6516 } else { 6517 if (cone[1] == f) r = 1; 6518 else if (cone[2] == f) r = 2; 6519 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6520 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6521 6522 newSize += 2; 6523 } 6524 } 6525 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6526 #if 1 6527 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6528 for (p = 0; p < newSize; ++p) { 6529 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); 6530 } 6531 #endif 6532 } 6533 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6534 break; 6535 default: 6536 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6537 } 6538 PetscFunctionReturn(0); 6539 } 6540 6541 #undef __FUNCT__ 6542 #define __FUNCT__ "CellRefinerSetCoordinates" 6543 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6544 { 6545 PetscSection coordSection, coordSectionNew; 6546 Vec coordinates, coordinatesNew; 6547 PetscScalar *coords, *coordsNew; 6548 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6549 PetscErrorCode ierr; 6550 6551 PetscFunctionBegin; 6552 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6553 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6554 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6555 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6556 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6557 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6558 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6559 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6560 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6561 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6562 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6563 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6564 if (fMax < 0) fMax = fEnd; 6565 switch (refiner) { 6566 case 1: 6567 case 2: 6568 case 3: 6569 /* Simplicial and Hex 2D */ 6570 /* All vertices have the dim coordinates */ 6571 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6572 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6573 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6574 } 6575 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6576 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6577 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6578 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6579 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6580 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6581 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6582 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6583 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6584 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6585 /* Old vertices have the same coordinates */ 6586 for (v = vStart; v < vEnd; ++v) { 6587 const PetscInt newv = vStartNew + (v - vStart); 6588 PetscInt off, offnew, d; 6589 6590 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6591 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6592 for (d = 0; d < dim; ++d) { 6593 coordsNew[offnew+d] = coords[off+d]; 6594 } 6595 } 6596 /* Face vertices have the average of endpoint coordinates */ 6597 for (f = fStart; f < fMax; ++f) { 6598 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6599 const PetscInt *cone; 6600 PetscInt coneSize, offA, offB, offnew, d; 6601 6602 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6603 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6604 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6605 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6606 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6607 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6608 for (d = 0; d < dim; ++d) { 6609 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6610 } 6611 } 6612 /* Just Hex 2D */ 6613 if (refiner == 2) { 6614 /* Cell vertices have the average of corner coordinates */ 6615 for (c = cStart; c < cEnd; ++c) { 6616 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6617 PetscInt *cone = NULL; 6618 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6619 6620 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6621 for (p = 0; p < closureSize*2; p += 2) { 6622 const PetscInt point = cone[p]; 6623 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6624 } 6625 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6626 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6627 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6628 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6629 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6630 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6631 for (d = 0; d < dim; ++d) { 6632 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6633 } 6634 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6635 } 6636 } 6637 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6638 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6639 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6640 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6641 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 6642 break; 6643 default: 6644 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6645 } 6646 PetscFunctionReturn(0); 6647 } 6648 6649 #undef __FUNCT__ 6650 #define __FUNCT__ "DMPlexCreateProcessSF" 6651 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6652 { 6653 PetscInt numRoots, numLeaves, l; 6654 const PetscInt *localPoints; 6655 const PetscSFNode *remotePoints; 6656 PetscInt *localPointsNew; 6657 PetscSFNode *remotePointsNew; 6658 PetscInt *ranks, *ranksNew; 6659 PetscErrorCode ierr; 6660 6661 PetscFunctionBegin; 6662 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6663 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6664 for (l = 0; l < numLeaves; ++l) { 6665 ranks[l] = remotePoints[l].rank; 6666 } 6667 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6668 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6669 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6670 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6671 for (l = 0; l < numLeaves; ++l) { 6672 ranksNew[l] = ranks[l]; 6673 localPointsNew[l] = l; 6674 remotePointsNew[l].index = 0; 6675 remotePointsNew[l].rank = ranksNew[l]; 6676 } 6677 ierr = PetscFree(ranks);CHKERRQ(ierr); 6678 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6679 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 6680 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6681 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6682 PetscFunctionReturn(0); 6683 } 6684 6685 #undef __FUNCT__ 6686 #define __FUNCT__ "CellRefinerCreateSF" 6687 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6688 { 6689 PetscSF sf, sfNew, sfProcess; 6690 IS processRanks; 6691 MPI_Datatype depthType; 6692 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6693 const PetscInt *localPoints, *neighbors; 6694 const PetscSFNode *remotePoints; 6695 PetscInt *localPointsNew; 6696 PetscSFNode *remotePointsNew; 6697 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6698 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6699 PetscErrorCode ierr; 6700 6701 PetscFunctionBegin; 6702 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6703 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6704 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6705 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6706 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6707 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6708 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6709 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6710 switch (refiner) { 6711 case 3: 6712 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6713 cMax = PetscMin(cEnd, cMax); 6714 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6715 fMax = PetscMin(fEnd, fMax); 6716 } 6717 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6718 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6719 /* Caculate size of new SF */ 6720 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6721 if (numRoots < 0) PetscFunctionReturn(0); 6722 for (l = 0; l < numLeaves; ++l) { 6723 const PetscInt p = localPoints[l]; 6724 6725 switch (refiner) { 6726 case 1: 6727 /* Simplicial 2D */ 6728 if ((p >= vStart) && (p < vEnd)) { 6729 /* Old vertices stay the same */ 6730 ++numLeavesNew; 6731 } else if ((p >= fStart) && (p < fEnd)) { 6732 /* Old faces add new faces and vertex */ 6733 numLeavesNew += 1 + 2; 6734 } else if ((p >= cStart) && (p < cEnd)) { 6735 /* Old cells add new cells and interior faces */ 6736 numLeavesNew += 4 + 3; 6737 } 6738 break; 6739 case 2: 6740 /* Hex 2D */ 6741 if ((p >= vStart) && (p < vEnd)) { 6742 /* Old vertices stay the same */ 6743 ++numLeavesNew; 6744 } else if ((p >= fStart) && (p < fEnd)) { 6745 /* Old faces add new faces and vertex */ 6746 numLeavesNew += 1 + 2; 6747 } else if ((p >= cStart) && (p < cEnd)) { 6748 /* Old cells add new cells and interior faces */ 6749 numLeavesNew += 4 + 4; 6750 } 6751 break; 6752 default: 6753 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6754 } 6755 } 6756 /* Communicate depthSizes for each remote rank */ 6757 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6758 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6759 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6760 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); 6761 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6762 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6763 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6764 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6765 for (n = 0; n < numNeighbors; ++n) { 6766 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6767 } 6768 depthSizeOld[depth] = cMax; 6769 depthSizeOld[0] = vMax; 6770 depthSizeOld[depth-1] = fMax; 6771 depthSizeOld[1] = eMax; 6772 6773 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6774 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6775 6776 depthSizeOld[depth] = cEnd - cStart; 6777 depthSizeOld[0] = vEnd - vStart; 6778 depthSizeOld[depth-1] = fEnd - fStart; 6779 depthSizeOld[1] = eEnd - eStart; 6780 6781 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6782 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6783 for (n = 0; n < numNeighbors; ++n) { 6784 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6785 } 6786 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6787 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6788 /* Calculate new point SF */ 6789 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6790 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6791 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6792 for (l = 0, m = 0; l < numLeaves; ++l) { 6793 PetscInt p = localPoints[l]; 6794 PetscInt rp = remotePoints[l].index, n; 6795 PetscMPIInt rrank = remotePoints[l].rank; 6796 6797 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6798 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6799 switch (refiner) { 6800 case 1: 6801 /* Simplicial 2D */ 6802 if ((p >= vStart) && (p < vEnd)) { 6803 /* Old vertices stay the same */ 6804 localPointsNew[m] = vStartNew + (p - vStart); 6805 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6806 remotePointsNew[m].rank = rrank; 6807 ++m; 6808 } else if ((p >= fStart) && (p < fEnd)) { 6809 /* Old faces add new faces and vertex */ 6810 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6811 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6812 remotePointsNew[m].rank = rrank; 6813 ++m; 6814 for (r = 0; r < 2; ++r, ++m) { 6815 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6816 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6817 remotePointsNew[m].rank = rrank; 6818 } 6819 } else if ((p >= cStart) && (p < cEnd)) { 6820 /* Old cells add new cells and interior faces */ 6821 for (r = 0; r < 4; ++r, ++m) { 6822 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6823 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6824 remotePointsNew[m].rank = rrank; 6825 } 6826 for (r = 0; r < 3; ++r, ++m) { 6827 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6828 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6829 remotePointsNew[m].rank = rrank; 6830 } 6831 } 6832 break; 6833 case 2: 6834 /* Hex 2D */ 6835 if ((p >= vStart) && (p < vEnd)) { 6836 /* Old vertices stay the same */ 6837 localPointsNew[m] = vStartNew + (p - vStart); 6838 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6839 remotePointsNew[m].rank = rrank; 6840 ++m; 6841 } else if ((p >= fStart) && (p < fEnd)) { 6842 /* Old faces add new faces and vertex */ 6843 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6844 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6845 remotePointsNew[m].rank = rrank; 6846 ++m; 6847 for (r = 0; r < 2; ++r, ++m) { 6848 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6849 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6850 remotePointsNew[m].rank = rrank; 6851 } 6852 } else if ((p >= cStart) && (p < cEnd)) { 6853 /* Old cells add new cells and interior faces */ 6854 for (r = 0; r < 4; ++r, ++m) { 6855 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6856 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6857 remotePointsNew[m].rank = rrank; 6858 } 6859 for (r = 0; r < 4; ++r, ++m) { 6860 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6861 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6862 remotePointsNew[m].rank = rrank; 6863 } 6864 } 6865 break; 6866 case 3: 6867 /* Hybrid simplicial 2D */ 6868 if ((p >= vStart) && (p < vEnd)) { 6869 /* Old vertices stay the same */ 6870 localPointsNew[m] = vStartNew + (p - vStart); 6871 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6872 remotePointsNew[m].rank = rrank; 6873 ++m; 6874 } else if ((p >= fStart) && (p < fMax)) { 6875 /* Old interior faces add new faces and vertex */ 6876 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6877 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6878 remotePointsNew[m].rank = rrank; 6879 ++m; 6880 for (r = 0; r < 2; ++r, ++m) { 6881 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6882 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6883 remotePointsNew[m].rank = rrank; 6884 } 6885 } else if ((p >= fMax) && (p < fEnd)) { 6886 /* Old hybrid faces stay the same */ 6887 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6888 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6889 remotePointsNew[m].rank = rrank; 6890 ++m; 6891 } else if ((p >= cStart) && (p < cMax)) { 6892 /* Old interior cells add new cells and interior faces */ 6893 for (r = 0; r < 4; ++r, ++m) { 6894 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6895 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6896 remotePointsNew[m].rank = rrank; 6897 } 6898 for (r = 0; r < 3; ++r, ++m) { 6899 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6900 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6901 remotePointsNew[m].rank = rrank; 6902 } 6903 } else if ((p >= cStart) && (p < cMax)) { 6904 /* Old hybrid cells add new cells and hybrid face */ 6905 for (r = 0; r < 2; ++r, ++m) { 6906 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6907 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6908 remotePointsNew[m].rank = rrank; 6909 } 6910 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6911 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]); 6912 remotePointsNew[m].rank = rrank; 6913 ++m; 6914 } 6915 break; 6916 default: 6917 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6918 } 6919 } 6920 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6921 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6922 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6923 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6924 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6925 PetscFunctionReturn(0); 6926 } 6927 6928 #undef __FUNCT__ 6929 #define __FUNCT__ "CellRefinerCreateLabels" 6930 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6931 { 6932 PetscInt numLabels, l; 6933 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6934 PetscErrorCode ierr; 6935 6936 PetscFunctionBegin; 6937 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6938 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6939 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6940 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6941 6942 cStartNew = 0; 6943 vStartNew = depthSize[2]; 6944 fStartNew = depthSize[2] + depthSize[0]; 6945 6946 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6947 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6948 switch (refiner) { 6949 case 3: 6950 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6951 cMax = PetscMin(cEnd, cMax); 6952 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6953 fMax = PetscMin(fEnd, fMax); 6954 } 6955 for (l = 0; l < numLabels; ++l) { 6956 DMLabel label, labelNew; 6957 const char *lname; 6958 PetscBool isDepth; 6959 IS valueIS; 6960 const PetscInt *values; 6961 PetscInt numValues, val; 6962 6963 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6964 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6965 if (isDepth) continue; 6966 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6967 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6968 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6969 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6970 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6971 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6972 for (val = 0; val < numValues; ++val) { 6973 IS pointIS; 6974 const PetscInt *points; 6975 PetscInt numPoints, n; 6976 6977 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6978 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6979 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6980 for (n = 0; n < numPoints; ++n) { 6981 const PetscInt p = points[n]; 6982 switch (refiner) { 6983 case 1: 6984 /* Simplicial 2D */ 6985 if ((p >= vStart) && (p < vEnd)) { 6986 /* Old vertices stay the same */ 6987 newp = vStartNew + (p - vStart); 6988 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6989 } else if ((p >= fStart) && (p < fEnd)) { 6990 /* Old faces add new faces and vertex */ 6991 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6992 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6993 for (r = 0; r < 2; ++r) { 6994 newp = fStartNew + (p - fStart)*2 + r; 6995 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6996 } 6997 } else if ((p >= cStart) && (p < cEnd)) { 6998 /* Old cells add new cells and interior faces */ 6999 for (r = 0; r < 4; ++r) { 7000 newp = cStartNew + (p - cStart)*4 + r; 7001 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7002 } 7003 for (r = 0; r < 3; ++r) { 7004 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7005 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7006 } 7007 } 7008 break; 7009 case 2: 7010 /* Hex 2D */ 7011 if ((p >= vStart) && (p < vEnd)) { 7012 /* Old vertices stay the same */ 7013 newp = vStartNew + (p - vStart); 7014 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7015 } else if ((p >= fStart) && (p < fEnd)) { 7016 /* Old faces add new faces and vertex */ 7017 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7018 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7019 for (r = 0; r < 2; ++r) { 7020 newp = fStartNew + (p - fStart)*2 + r; 7021 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7022 } 7023 } else if ((p >= cStart) && (p < cEnd)) { 7024 /* Old cells add new cells and interior faces and vertex */ 7025 for (r = 0; r < 4; ++r) { 7026 newp = cStartNew + (p - cStart)*4 + r; 7027 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7028 } 7029 for (r = 0; r < 4; ++r) { 7030 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7031 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7032 } 7033 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7034 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7035 } 7036 break; 7037 case 3: 7038 /* Hybrid simplicial 2D */ 7039 if ((p >= vStart) && (p < vEnd)) { 7040 /* Old vertices stay the same */ 7041 newp = vStartNew + (p - vStart); 7042 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7043 } else if ((p >= fStart) && (p < fMax)) { 7044 /* Old interior faces add new faces and vertex */ 7045 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7046 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7047 for (r = 0; r < 2; ++r) { 7048 newp = fStartNew + (p - fStart)*2 + r; 7049 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7050 } 7051 } else if ((p >= fMax) && (p < fEnd)) { 7052 /* Old hybrid faces stay the same */ 7053 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7054 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7055 } else if ((p >= cStart) && (p < cMax)) { 7056 /* Old interior cells add new cells and interior faces */ 7057 for (r = 0; r < 4; ++r) { 7058 newp = cStartNew + (p - cStart)*4 + r; 7059 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7060 } 7061 for (r = 0; r < 3; ++r) { 7062 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7063 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7064 } 7065 } else if ((p >= cMax) && (p < cEnd)) { 7066 /* Old hybrid cells add new cells and hybrid face */ 7067 for (r = 0; r < 2; ++r) { 7068 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7069 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7070 } 7071 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7072 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7073 } 7074 break; 7075 default: 7076 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7077 } 7078 } 7079 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7080 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7081 } 7082 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7083 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7084 if (0) { 7085 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7086 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7087 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7088 } 7089 } 7090 PetscFunctionReturn(0); 7091 } 7092 7093 #undef __FUNCT__ 7094 #define __FUNCT__ "DMPlexRefine_Uniform" 7095 /* This will only work for interpolated meshes */ 7096 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7097 { 7098 DM rdm; 7099 PetscInt *depthSize; 7100 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7101 PetscErrorCode ierr; 7102 7103 PetscFunctionBegin; 7104 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 7105 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7106 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7107 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7108 /* Calculate number of new points of each depth */ 7109 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7110 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7111 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7112 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7113 /* Step 1: Set chart */ 7114 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7115 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7116 /* Step 2: Set cone/support sizes */ 7117 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7118 /* Step 3: Setup refined DM */ 7119 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7120 /* Step 4: Set cones and supports */ 7121 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7122 /* Step 5: Stratify */ 7123 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7124 /* Step 6: Set coordinates for vertices */ 7125 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7126 /* Step 7: Create pointSF */ 7127 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7128 /* Step 8: Create labels */ 7129 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7130 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7131 7132 *dmRefined = rdm; 7133 PetscFunctionReturn(0); 7134 } 7135 7136 #undef __FUNCT__ 7137 #define __FUNCT__ "DMPlexSetRefinementUniform" 7138 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7139 { 7140 DM_Plex *mesh = (DM_Plex*) dm->data; 7141 7142 PetscFunctionBegin; 7143 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7144 mesh->refinementUniform = refinementUniform; 7145 PetscFunctionReturn(0); 7146 } 7147 7148 #undef __FUNCT__ 7149 #define __FUNCT__ "DMPlexGetRefinementUniform" 7150 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7151 { 7152 DM_Plex *mesh = (DM_Plex*) dm->data; 7153 7154 PetscFunctionBegin; 7155 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7156 PetscValidPointer(refinementUniform, 2); 7157 *refinementUniform = mesh->refinementUniform; 7158 PetscFunctionReturn(0); 7159 } 7160 7161 #undef __FUNCT__ 7162 #define __FUNCT__ "DMPlexSetRefinementLimit" 7163 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7164 { 7165 DM_Plex *mesh = (DM_Plex*) dm->data; 7166 7167 PetscFunctionBegin; 7168 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7169 mesh->refinementLimit = refinementLimit; 7170 PetscFunctionReturn(0); 7171 } 7172 7173 #undef __FUNCT__ 7174 #define __FUNCT__ "DMPlexGetRefinementLimit" 7175 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7176 { 7177 DM_Plex *mesh = (DM_Plex*) dm->data; 7178 7179 PetscFunctionBegin; 7180 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7181 PetscValidPointer(refinementLimit, 2); 7182 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7183 *refinementLimit = mesh->refinementLimit; 7184 PetscFunctionReturn(0); 7185 } 7186 7187 #undef __FUNCT__ 7188 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7189 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7190 { 7191 PetscInt dim, cStart, coneSize, cMax; 7192 PetscErrorCode ierr; 7193 7194 PetscFunctionBegin; 7195 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7196 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7197 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7198 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7199 switch (dim) { 7200 case 2: 7201 switch (coneSize) { 7202 case 3: 7203 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7204 else *cellRefiner = 1; /* Triangular */ 7205 break; 7206 case 4: 7207 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7208 else *cellRefiner = 2; /* Quadrilateral */ 7209 break; 7210 default: 7211 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7212 } 7213 break; 7214 default: 7215 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7216 } 7217 PetscFunctionReturn(0); 7218 } 7219 7220 #undef __FUNCT__ 7221 #define __FUNCT__ "DMRefine_Plex" 7222 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7223 { 7224 PetscReal refinementLimit; 7225 PetscInt dim, cStart, cEnd; 7226 char genname[1024], *name = NULL; 7227 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7228 PetscErrorCode ierr; 7229 7230 PetscFunctionBegin; 7231 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7232 if (isUniform) { 7233 CellRefiner cellRefiner; 7234 7235 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7236 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7237 PetscFunctionReturn(0); 7238 } 7239 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7240 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7241 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7242 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7243 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7244 if (flg) name = genname; 7245 if (name) { 7246 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7247 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7248 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7249 } 7250 switch (dim) { 7251 case 2: 7252 if (!name || isTriangle) { 7253 #if defined(PETSC_HAVE_TRIANGLE) 7254 double *maxVolumes; 7255 PetscInt c; 7256 7257 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7258 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7259 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7260 #else 7261 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7262 #endif 7263 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7264 break; 7265 case 3: 7266 if (!name || isCTetgen) { 7267 #if defined(PETSC_HAVE_CTETGEN) 7268 PetscReal *maxVolumes; 7269 PetscInt c; 7270 7271 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7272 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7273 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7274 #else 7275 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7276 #endif 7277 } else if (isTetgen) { 7278 #if defined(PETSC_HAVE_TETGEN) 7279 double *maxVolumes; 7280 PetscInt c; 7281 7282 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7283 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7284 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7285 #else 7286 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7287 #endif 7288 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7289 break; 7290 default: 7291 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7292 } 7293 PetscFunctionReturn(0); 7294 } 7295 7296 #undef __FUNCT__ 7297 #define __FUNCT__ "DMPlexGetDepth" 7298 /*@ 7299 DMPlexGetDepth - get the number of strata 7300 7301 Not Collective 7302 7303 Input Parameters: 7304 . dm - The DMPlex object 7305 7306 Output Parameters: 7307 . depth - number of strata 7308 7309 Level: developer 7310 7311 Notes: 7312 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7313 7314 .keywords: mesh, points 7315 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7316 @*/ 7317 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7318 { 7319 PetscInt d; 7320 PetscErrorCode ierr; 7321 7322 PetscFunctionBegin; 7323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7324 PetscValidPointer(depth, 2); 7325 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7326 *depth = d-1; 7327 PetscFunctionReturn(0); 7328 } 7329 7330 #undef __FUNCT__ 7331 #define __FUNCT__ "DMPlexGetDepthStratum" 7332 /*@ 7333 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7334 7335 Not Collective 7336 7337 Input Parameters: 7338 + dm - The DMPlex object 7339 - stratumValue - The requested depth 7340 7341 Output Parameters: 7342 + start - The first point at this depth 7343 - end - One beyond the last point at this depth 7344 7345 Level: developer 7346 7347 .keywords: mesh, points 7348 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7349 @*/ 7350 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7351 { 7352 DM_Plex *mesh = (DM_Plex*) dm->data; 7353 DMLabel next = mesh->labels; 7354 PetscBool flg = PETSC_FALSE; 7355 PetscInt depth; 7356 PetscErrorCode ierr; 7357 7358 PetscFunctionBegin; 7359 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7360 if (stratumValue < 0) { 7361 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7362 PetscFunctionReturn(0); 7363 } else { 7364 PetscInt pStart, pEnd; 7365 7366 if (start) *start = 0; 7367 if (end) *end = 0; 7368 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7369 if (pStart == pEnd) PetscFunctionReturn(0); 7370 } 7371 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7372 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7373 /* We should have a generic GetLabel() and a Label class */ 7374 while (next) { 7375 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7376 if (flg) break; 7377 next = next->next; 7378 } 7379 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7380 depth = stratumValue; 7381 if ((depth < 0) || (depth >= next->numStrata)) { 7382 if (start) *start = 0; 7383 if (end) *end = 0; 7384 } else { 7385 if (start) *start = next->points[next->stratumOffsets[depth]]; 7386 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7387 } 7388 PetscFunctionReturn(0); 7389 } 7390 7391 #undef __FUNCT__ 7392 #define __FUNCT__ "DMPlexGetHeightStratum" 7393 /*@ 7394 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7395 7396 Not Collective 7397 7398 Input Parameters: 7399 + dm - The DMPlex object 7400 - stratumValue - The requested height 7401 7402 Output Parameters: 7403 + start - The first point at this height 7404 - end - One beyond the last point at this height 7405 7406 Level: developer 7407 7408 .keywords: mesh, points 7409 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7410 @*/ 7411 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7412 { 7413 DM_Plex *mesh = (DM_Plex*) dm->data; 7414 DMLabel next = mesh->labels; 7415 PetscBool flg = PETSC_FALSE; 7416 PetscInt depth; 7417 PetscErrorCode ierr; 7418 7419 PetscFunctionBegin; 7420 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7421 if (stratumValue < 0) { 7422 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7423 } else { 7424 PetscInt pStart, pEnd; 7425 7426 if (start) *start = 0; 7427 if (end) *end = 0; 7428 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7429 if (pStart == pEnd) PetscFunctionReturn(0); 7430 } 7431 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7432 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7433 /* We should have a generic GetLabel() and a Label class */ 7434 while (next) { 7435 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7436 if (flg) break; 7437 next = next->next; 7438 } 7439 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7440 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7441 if ((depth < 0) || (depth >= next->numStrata)) { 7442 if (start) *start = 0; 7443 if (end) *end = 0; 7444 } else { 7445 if (start) *start = next->points[next->stratumOffsets[depth]]; 7446 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7447 } 7448 PetscFunctionReturn(0); 7449 } 7450 7451 #undef __FUNCT__ 7452 #define __FUNCT__ "DMPlexCreateSectionInitial" 7453 /* Set the number of dof on each point and separate by fields */ 7454 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7455 { 7456 PetscInt *numDofTot; 7457 PetscInt pStart = 0, pEnd = 0; 7458 PetscInt p, d, f; 7459 PetscErrorCode ierr; 7460 7461 PetscFunctionBegin; 7462 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7463 for (d = 0; d <= dim; ++d) { 7464 numDofTot[d] = 0; 7465 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7466 } 7467 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7468 if (numFields > 0) { 7469 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7470 if (numComp) { 7471 for (f = 0; f < numFields; ++f) { 7472 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7473 } 7474 } 7475 } 7476 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7477 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7478 for (d = 0; d <= dim; ++d) { 7479 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7480 for (p = pStart; p < pEnd; ++p) { 7481 for (f = 0; f < numFields; ++f) { 7482 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7483 } 7484 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7485 } 7486 } 7487 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7488 PetscFunctionReturn(0); 7489 } 7490 7491 #undef __FUNCT__ 7492 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7493 /* Set the number of dof on each point and separate by fields 7494 If constDof is PETSC_DETERMINE, constrain every dof on the point 7495 */ 7496 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7497 { 7498 PetscInt numFields; 7499 PetscInt bc; 7500 PetscErrorCode ierr; 7501 7502 PetscFunctionBegin; 7503 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7504 for (bc = 0; bc < numBC; ++bc) { 7505 PetscInt field = 0; 7506 const PetscInt *idx; 7507 PetscInt n, i; 7508 7509 if (numFields) field = bcField[bc]; 7510 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7511 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7512 for (i = 0; i < n; ++i) { 7513 const PetscInt p = idx[i]; 7514 PetscInt numConst = constDof; 7515 7516 /* Constrain every dof on the point */ 7517 if (numConst < 0) { 7518 if (numFields) { 7519 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7520 } else { 7521 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7522 } 7523 } 7524 if (numFields) { 7525 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7526 } 7527 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7528 } 7529 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7530 } 7531 PetscFunctionReturn(0); 7532 } 7533 7534 #undef __FUNCT__ 7535 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7536 /* Set the constrained indices on each point and separate by fields */ 7537 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7538 { 7539 PetscInt *maxConstraints; 7540 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7541 PetscErrorCode ierr; 7542 7543 PetscFunctionBegin; 7544 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7545 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7546 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7547 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7548 for (p = pStart; p < pEnd; ++p) { 7549 PetscInt cdof; 7550 7551 if (numFields) { 7552 for (f = 0; f < numFields; ++f) { 7553 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7554 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7555 } 7556 } else { 7557 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7558 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7559 } 7560 } 7561 for (f = 0; f < numFields; ++f) { 7562 maxConstraints[numFields] += maxConstraints[f]; 7563 } 7564 if (maxConstraints[numFields]) { 7565 PetscInt *indices; 7566 7567 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7568 for (p = pStart; p < pEnd; ++p) { 7569 PetscInt cdof, d; 7570 7571 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7572 if (cdof) { 7573 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7574 if (numFields) { 7575 PetscInt numConst = 0, foff = 0; 7576 7577 for (f = 0; f < numFields; ++f) { 7578 PetscInt cfdof, fdof; 7579 7580 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7581 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7582 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7583 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7584 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7585 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7586 numConst += cfdof; 7587 foff += fdof; 7588 } 7589 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7590 } else { 7591 for (d = 0; d < cdof; ++d) indices[d] = d; 7592 } 7593 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7594 } 7595 } 7596 ierr = PetscFree(indices);CHKERRQ(ierr); 7597 } 7598 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7599 PetscFunctionReturn(0); 7600 } 7601 7602 #undef __FUNCT__ 7603 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7604 /* Set the constrained field indices on each point */ 7605 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7606 { 7607 const PetscInt *points, *indices; 7608 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7609 PetscErrorCode ierr; 7610 7611 PetscFunctionBegin; 7612 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7613 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7614 7615 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7616 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7617 if (!constraintIndices) { 7618 PetscInt *idx, i; 7619 7620 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7621 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7622 for (i = 0; i < maxDof; ++i) idx[i] = i; 7623 for (p = 0; p < numPoints; ++p) { 7624 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7625 } 7626 ierr = PetscFree(idx);CHKERRQ(ierr); 7627 } else { 7628 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7629 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7630 for (p = 0; p < numPoints; ++p) { 7631 PetscInt fcdof; 7632 7633 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7634 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); 7635 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7636 } 7637 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7638 } 7639 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7640 PetscFunctionReturn(0); 7641 } 7642 7643 #undef __FUNCT__ 7644 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7645 /* Set the constrained indices on each point and separate by fields */ 7646 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7647 { 7648 PetscInt *indices; 7649 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7650 PetscErrorCode ierr; 7651 7652 PetscFunctionBegin; 7653 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7654 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7655 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7656 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7657 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7658 for (p = pStart; p < pEnd; ++p) { 7659 PetscInt cdof, d; 7660 7661 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7662 if (cdof) { 7663 PetscInt numConst = 0, foff = 0; 7664 7665 for (f = 0; f < numFields; ++f) { 7666 const PetscInt *fcind; 7667 PetscInt fdof, fcdof; 7668 7669 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7670 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7671 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7672 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7673 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7674 foff += fdof; 7675 numConst += fcdof; 7676 } 7677 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7678 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7679 } 7680 } 7681 ierr = PetscFree(indices);CHKERRQ(ierr); 7682 PetscFunctionReturn(0); 7683 } 7684 7685 #undef __FUNCT__ 7686 #define __FUNCT__ "DMPlexCreateSection" 7687 /*@C 7688 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7689 7690 Not Collective 7691 7692 Input Parameters: 7693 + dm - The DMPlex object 7694 . dim - The spatial dimension of the problem 7695 . numFields - The number of fields in the problem 7696 . numComp - An array of size numFields that holds the number of components for each field 7697 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7698 . numBC - The number of boundary conditions 7699 . bcField - An array of size numBC giving the field number for each boundry condition 7700 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7701 7702 Output Parameter: 7703 . section - The PetscSection object 7704 7705 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 7706 nubmer of dof for field 0 on each edge. 7707 7708 Level: developer 7709 7710 .keywords: mesh, elements 7711 .seealso: DMPlexCreate(), PetscSectionCreate() 7712 @*/ 7713 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 7714 { 7715 PetscErrorCode ierr; 7716 7717 PetscFunctionBegin; 7718 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7719 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7720 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7721 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7722 { 7723 PetscBool view = PETSC_FALSE; 7724 7725 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7726 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7727 } 7728 PetscFunctionReturn(0); 7729 } 7730 7731 #undef __FUNCT__ 7732 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7733 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7734 { 7735 PetscSection section; 7736 PetscErrorCode ierr; 7737 7738 PetscFunctionBegin; 7739 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7740 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7741 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7742 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7743 PetscFunctionReturn(0); 7744 } 7745 7746 #undef __FUNCT__ 7747 #define __FUNCT__ "DMPlexGetCoordinateSection" 7748 /*@ 7749 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7750 7751 Not Collective 7752 7753 Input Parameter: 7754 . dm - The DMPlex object 7755 7756 Output Parameter: 7757 . section - The PetscSection object 7758 7759 Level: intermediate 7760 7761 .keywords: mesh, coordinates 7762 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7763 @*/ 7764 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7765 { 7766 DM cdm; 7767 PetscErrorCode ierr; 7768 7769 PetscFunctionBegin; 7770 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7771 PetscValidPointer(section, 2); 7772 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7773 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7774 PetscFunctionReturn(0); 7775 } 7776 7777 #undef __FUNCT__ 7778 #define __FUNCT__ "DMPlexSetCoordinateSection" 7779 /*@ 7780 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7781 7782 Not Collective 7783 7784 Input Parameters: 7785 + dm - The DMPlex object 7786 - section - The PetscSection object 7787 7788 Level: intermediate 7789 7790 .keywords: mesh, coordinates 7791 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7792 @*/ 7793 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7794 { 7795 DM cdm; 7796 PetscErrorCode ierr; 7797 7798 PetscFunctionBegin; 7799 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7800 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 7801 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7802 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7803 PetscFunctionReturn(0); 7804 } 7805 7806 #undef __FUNCT__ 7807 #define __FUNCT__ "DMPlexGetConeSection" 7808 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7809 { 7810 DM_Plex *mesh = (DM_Plex*) dm->data; 7811 7812 PetscFunctionBegin; 7813 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7814 if (section) *section = mesh->coneSection; 7815 PetscFunctionReturn(0); 7816 } 7817 7818 #undef __FUNCT__ 7819 #define __FUNCT__ "DMPlexGetCones" 7820 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 7821 { 7822 DM_Plex *mesh = (DM_Plex*) dm->data; 7823 7824 PetscFunctionBegin; 7825 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7826 if (cones) *cones = mesh->cones; 7827 PetscFunctionReturn(0); 7828 } 7829 7830 #undef __FUNCT__ 7831 #define __FUNCT__ "DMPlexGetConeOrientations" 7832 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 7833 { 7834 DM_Plex *mesh = (DM_Plex*) dm->data; 7835 7836 PetscFunctionBegin; 7837 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7838 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7839 PetscFunctionReturn(0); 7840 } 7841 7842 #undef __FUNCT__ 7843 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7844 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7845 { 7846 const PetscInt embedDim = 2; 7847 PetscReal x = PetscRealPart(point[0]); 7848 PetscReal y = PetscRealPart(point[1]); 7849 PetscReal v0[2], J[4], invJ[4], detJ; 7850 PetscReal xi, eta; 7851 PetscErrorCode ierr; 7852 7853 PetscFunctionBegin; 7854 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7855 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7856 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7857 7858 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 7859 else *cell = -1; 7860 PetscFunctionReturn(0); 7861 } 7862 7863 #undef __FUNCT__ 7864 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7865 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7866 { 7867 PetscSection coordSection; 7868 Vec coordsLocal; 7869 const PetscScalar *coords; 7870 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7871 PetscReal x = PetscRealPart(point[0]); 7872 PetscReal y = PetscRealPart(point[1]); 7873 PetscInt crossings = 0, f; 7874 PetscErrorCode ierr; 7875 7876 PetscFunctionBegin; 7877 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7878 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7879 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7880 for (f = 0; f < 4; ++f) { 7881 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7882 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7883 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7884 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7885 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7886 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7887 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7888 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7889 if ((cond1 || cond2) && above) ++crossings; 7890 } 7891 if (crossings % 2) *cell = c; 7892 else *cell = -1; 7893 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7894 PetscFunctionReturn(0); 7895 } 7896 7897 #undef __FUNCT__ 7898 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7899 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7900 { 7901 const PetscInt embedDim = 3; 7902 PetscReal v0[3], J[9], invJ[9], detJ; 7903 PetscReal x = PetscRealPart(point[0]); 7904 PetscReal y = PetscRealPart(point[1]); 7905 PetscReal z = PetscRealPart(point[2]); 7906 PetscReal xi, eta, zeta; 7907 PetscErrorCode ierr; 7908 7909 PetscFunctionBegin; 7910 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7911 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7912 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7913 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7914 7915 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 7916 else *cell = -1; 7917 PetscFunctionReturn(0); 7918 } 7919 7920 #undef __FUNCT__ 7921 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7922 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7923 { 7924 PetscSection coordSection; 7925 Vec coordsLocal; 7926 const PetscScalar *coords; 7927 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7928 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7929 PetscBool found = PETSC_TRUE; 7930 PetscInt f; 7931 PetscErrorCode ierr; 7932 7933 PetscFunctionBegin; 7934 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7935 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7936 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7937 for (f = 0; f < 6; ++f) { 7938 /* Check the point is under plane */ 7939 /* Get face normal */ 7940 PetscReal v_i[3]; 7941 PetscReal v_j[3]; 7942 PetscReal normal[3]; 7943 PetscReal pp[3]; 7944 PetscReal dot; 7945 7946 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 7947 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 7948 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 7949 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 7950 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 7951 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 7952 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 7953 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 7954 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 7955 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 7956 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 7957 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 7958 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7959 7960 /* Check that projected point is in face (2D location problem) */ 7961 if (dot < 0.0) { 7962 found = PETSC_FALSE; 7963 break; 7964 } 7965 } 7966 if (found) *cell = c; 7967 else *cell = -1; 7968 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7969 PetscFunctionReturn(0); 7970 } 7971 7972 #undef __FUNCT__ 7973 #define __FUNCT__ "DMLocatePoints_Plex" 7974 /* 7975 Need to implement using the guess 7976 */ 7977 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7978 { 7979 PetscInt cell = -1 /*, guess = -1*/; 7980 PetscInt bs, numPoints, p; 7981 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7982 PetscInt *cells; 7983 PetscScalar *a; 7984 PetscErrorCode ierr; 7985 7986 PetscFunctionBegin; 7987 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7988 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7989 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7990 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7991 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7992 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7993 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7994 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); 7995 numPoints /= bs; 7996 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7997 for (p = 0; p < numPoints; ++p) { 7998 const PetscScalar *point = &a[p*bs]; 7999 8000 switch (dim) { 8001 case 2: 8002 for (c = cStart; c < cEnd; ++c) { 8003 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8004 switch (coneSize) { 8005 case 3: 8006 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8007 break; 8008 case 4: 8009 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8010 break; 8011 default: 8012 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8013 } 8014 if (cell >= 0) break; 8015 } 8016 break; 8017 case 3: 8018 for (c = cStart; c < cEnd; ++c) { 8019 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8020 switch (coneSize) { 8021 case 4: 8022 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8023 break; 8024 case 8: 8025 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8026 break; 8027 default: 8028 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8029 } 8030 if (cell >= 0) break; 8031 } 8032 break; 8033 default: 8034 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8035 } 8036 cells[p] = cell; 8037 } 8038 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8039 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8040 PetscFunctionReturn(0); 8041 } 8042 8043 /******************************** FEM Support **********************************/ 8044 8045 #undef __FUNCT__ 8046 #define __FUNCT__ "DMPlexVecGetClosure" 8047 /*@C 8048 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8049 8050 Not collective 8051 8052 Input Parameters: 8053 + dm - The DM 8054 . section - The section describing the layout in v, or NULL to use the default section 8055 . v - The local vector 8056 - point - The sieve point in the DM 8057 8058 Output Parameters: 8059 + csize - The number of values in the closure, or NULL 8060 - values - The array of values, which is a borrowed array and should not be freed 8061 8062 Level: intermediate 8063 8064 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8065 @*/ 8066 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8067 { 8068 PetscScalar *array, *vArray; 8069 PetscInt *points = NULL; 8070 PetscInt offsets[32]; 8071 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8072 PetscErrorCode ierr; 8073 8074 PetscFunctionBegin; 8075 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8076 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8077 if (!section) { 8078 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8079 } 8080 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8081 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8082 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8083 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8084 /* Compress out points not in the section */ 8085 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8086 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8087 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8088 points[q*2] = points[p]; 8089 points[q*2+1] = points[p+1]; 8090 ++q; 8091 } 8092 } 8093 numPoints = q; 8094 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8095 PetscInt dof, fdof; 8096 8097 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8098 for (f = 0; f < numFields; ++f) { 8099 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8100 offsets[f+1] += fdof; 8101 } 8102 size += dof; 8103 } 8104 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8105 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8106 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8107 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8108 for (p = 0; p < numPoints*2; p += 2) { 8109 PetscInt o = points[p+1]; 8110 PetscInt dof, off, d; 8111 PetscScalar *varr; 8112 8113 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8114 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8115 varr = &vArray[off]; 8116 if (numFields) { 8117 PetscInt fdof, foff, fcomp, f, c; 8118 8119 for (f = 0, foff = 0; f < numFields; ++f) { 8120 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8121 if (o >= 0) { 8122 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8123 array[offsets[f]] = varr[foff+d]; 8124 } 8125 } else { 8126 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8127 for (d = fdof/fcomp-1; d >= 0; --d) { 8128 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8129 array[offsets[f]] = varr[foff+d*fcomp+c]; 8130 } 8131 } 8132 } 8133 foff += fdof; 8134 } 8135 } else { 8136 if (o >= 0) { 8137 for (d = 0; d < dof; ++d, ++offsets[0]) { 8138 array[offsets[0]] = varr[d]; 8139 } 8140 } else { 8141 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8142 array[offsets[0]] = varr[d]; 8143 } 8144 } 8145 } 8146 } 8147 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8148 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8149 if (csize) *csize = size; 8150 *values = array; 8151 PetscFunctionReturn(0); 8152 } 8153 8154 #undef __FUNCT__ 8155 #define __FUNCT__ "DMPlexVecRestoreClosure" 8156 /*@C 8157 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8158 8159 Not collective 8160 8161 Input Parameters: 8162 + dm - The DM 8163 . section - The section describing the layout in v, or NULL to use the default section 8164 . v - The local vector 8165 . point - The sieve point in the DM 8166 . csize - The number of values in the closure, or NULL 8167 - values - The array of values, which is a borrowed array and should not be freed 8168 8169 Level: intermediate 8170 8171 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8172 @*/ 8173 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8174 { 8175 PetscInt size = 0; 8176 PetscErrorCode ierr; 8177 8178 PetscFunctionBegin; 8179 /* Should work without recalculating size */ 8180 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8181 PetscFunctionReturn(0); 8182 } 8183 8184 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8185 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8186 8187 #undef __FUNCT__ 8188 #define __FUNCT__ "updatePoint_private" 8189 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8190 { 8191 PetscInt cdof; /* The number of constraints on this point */ 8192 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8193 PetscScalar *a; 8194 PetscInt off, cind = 0, k; 8195 PetscErrorCode ierr; 8196 8197 PetscFunctionBegin; 8198 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8199 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8200 a = &array[off]; 8201 if (!cdof || setBC) { 8202 if (orientation >= 0) { 8203 for (k = 0; k < dof; ++k) { 8204 fuse(&a[k], values[k]); 8205 } 8206 } else { 8207 for (k = 0; k < dof; ++k) { 8208 fuse(&a[k], values[dof-k-1]); 8209 } 8210 } 8211 } else { 8212 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8213 if (orientation >= 0) { 8214 for (k = 0; k < dof; ++k) { 8215 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8216 fuse(&a[k], values[k]); 8217 } 8218 } else { 8219 for (k = 0; k < dof; ++k) { 8220 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8221 fuse(&a[k], values[dof-k-1]); 8222 } 8223 } 8224 } 8225 PetscFunctionReturn(0); 8226 } 8227 8228 #undef __FUNCT__ 8229 #define __FUNCT__ "updatePointFields_private" 8230 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8231 { 8232 PetscScalar *a; 8233 PetscInt numFields, off, foff, f; 8234 PetscErrorCode ierr; 8235 8236 PetscFunctionBegin; 8237 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8238 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8239 a = &array[off]; 8240 for (f = 0, foff = 0; f < numFields; ++f) { 8241 PetscInt fdof, fcomp, fcdof; 8242 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8243 PetscInt cind = 0, k, c; 8244 8245 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8246 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8247 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8248 if (!fcdof || setBC) { 8249 if (orientation >= 0) { 8250 for (k = 0; k < fdof; ++k) { 8251 fuse(&a[foff+k], values[foffs[f]+k]); 8252 } 8253 } else { 8254 for (k = fdof/fcomp-1; k >= 0; --k) { 8255 for (c = 0; c < fcomp; ++c) { 8256 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8257 } 8258 } 8259 } 8260 } else { 8261 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8262 if (orientation >= 0) { 8263 for (k = 0; k < fdof; ++k) { 8264 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8265 fuse(&a[foff+k], values[foffs[f]+k]); 8266 } 8267 } else { 8268 for (k = fdof/fcomp-1; k >= 0; --k) { 8269 for (c = 0; c < fcomp; ++c) { 8270 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8271 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8272 } 8273 } 8274 } 8275 } 8276 foff += fdof; 8277 foffs[f] += fdof; 8278 } 8279 PetscFunctionReturn(0); 8280 } 8281 8282 #undef __FUNCT__ 8283 #define __FUNCT__ "DMPlexVecSetClosure" 8284 /*@C 8285 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8286 8287 Not collective 8288 8289 Input Parameters: 8290 + dm - The DM 8291 . section - The section describing the layout in v, or NULL to use the default sectionw 8292 . v - The local vector 8293 . point - The sieve point in the DM 8294 . values - The array of values, which is a borrowed array and should not be freed 8295 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8296 8297 Level: intermediate 8298 8299 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8300 @*/ 8301 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8302 { 8303 PetscScalar *array; 8304 PetscInt *points = NULL; 8305 PetscInt offsets[32]; 8306 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8307 PetscErrorCode ierr; 8308 8309 PetscFunctionBegin; 8310 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8311 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8312 if (!section) { 8313 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8314 } 8315 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8316 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8317 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8318 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8319 /* Compress out points not in the section */ 8320 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8321 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8322 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8323 points[q*2] = points[p]; 8324 points[q*2+1] = points[p+1]; 8325 ++q; 8326 } 8327 } 8328 numPoints = q; 8329 for (p = 0; p < numPoints*2; p += 2) { 8330 PetscInt fdof; 8331 8332 for (f = 0; f < numFields; ++f) { 8333 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8334 offsets[f+1] += fdof; 8335 } 8336 } 8337 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8338 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8339 if (numFields) { 8340 switch (mode) { 8341 case INSERT_VALUES: 8342 for (p = 0; p < numPoints*2; p += 2) { 8343 PetscInt o = points[p+1]; 8344 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8345 } break; 8346 case INSERT_ALL_VALUES: 8347 for (p = 0; p < numPoints*2; p += 2) { 8348 PetscInt o = points[p+1]; 8349 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8350 } break; 8351 case ADD_VALUES: 8352 for (p = 0; p < numPoints*2; p += 2) { 8353 PetscInt o = points[p+1]; 8354 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8355 } break; 8356 case ADD_ALL_VALUES: 8357 for (p = 0; p < numPoints*2; p += 2) { 8358 PetscInt o = points[p+1]; 8359 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8360 } break; 8361 default: 8362 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8363 } 8364 } else { 8365 switch (mode) { 8366 case INSERT_VALUES: 8367 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8368 PetscInt o = points[p+1]; 8369 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8370 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8371 } break; 8372 case INSERT_ALL_VALUES: 8373 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8374 PetscInt o = points[p+1]; 8375 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8376 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8377 } break; 8378 case ADD_VALUES: 8379 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8380 PetscInt o = points[p+1]; 8381 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8382 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8383 } break; 8384 case ADD_ALL_VALUES: 8385 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8386 PetscInt o = points[p+1]; 8387 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8388 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8389 } break; 8390 default: 8391 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8392 } 8393 } 8394 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8395 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8396 PetscFunctionReturn(0); 8397 } 8398 8399 #undef __FUNCT__ 8400 #define __FUNCT__ "DMPlexPrintMatSetValues" 8401 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8402 { 8403 PetscMPIInt rank; 8404 PetscInt i, j; 8405 PetscErrorCode ierr; 8406 8407 PetscFunctionBegin; 8408 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8409 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8410 for (i = 0; i < numIndices; i++) { 8411 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8412 } 8413 for (i = 0; i < numIndices; i++) { 8414 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8415 for (j = 0; j < numIndices; j++) { 8416 #if defined(PETSC_USE_COMPLEX) 8417 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8418 #else 8419 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8420 #endif 8421 } 8422 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8423 } 8424 PetscFunctionReturn(0); 8425 } 8426 8427 #undef __FUNCT__ 8428 #define __FUNCT__ "indicesPoint_private" 8429 /* . off - The global offset of this point */ 8430 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8431 { 8432 PetscInt dof; /* The number of unknowns on this point */ 8433 PetscInt cdof; /* The number of constraints on this point */ 8434 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8435 PetscInt cind = 0, k; 8436 PetscErrorCode ierr; 8437 8438 PetscFunctionBegin; 8439 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8440 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8441 if (!cdof || setBC) { 8442 if (orientation >= 0) { 8443 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8444 } else { 8445 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8446 } 8447 } else { 8448 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8449 if (orientation >= 0) { 8450 for (k = 0; k < dof; ++k) { 8451 if ((cind < cdof) && (k == cdofs[cind])) { 8452 /* Insert check for returning constrained indices */ 8453 indices[*loff+k] = -(off+k+1); 8454 ++cind; 8455 } else { 8456 indices[*loff+k] = off+k-cind; 8457 } 8458 } 8459 } else { 8460 for (k = 0; k < dof; ++k) { 8461 if ((cind < cdof) && (k == cdofs[cind])) { 8462 /* Insert check for returning constrained indices */ 8463 indices[*loff+dof-k-1] = -(off+k+1); 8464 ++cind; 8465 } else { 8466 indices[*loff+dof-k-1] = off+k-cind; 8467 } 8468 } 8469 } 8470 } 8471 *loff += dof; 8472 PetscFunctionReturn(0); 8473 } 8474 8475 #undef __FUNCT__ 8476 #define __FUNCT__ "indicesPointFields_private" 8477 /* . off - The global offset of this point */ 8478 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8479 { 8480 PetscInt numFields, foff, f; 8481 PetscErrorCode ierr; 8482 8483 PetscFunctionBegin; 8484 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8485 for (f = 0, foff = 0; f < numFields; ++f) { 8486 PetscInt fdof, fcomp, cfdof; 8487 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8488 PetscInt cind = 0, k, c; 8489 8490 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8491 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8492 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8493 if (!cfdof || setBC) { 8494 if (orientation >= 0) { 8495 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8496 } else { 8497 for (k = fdof/fcomp-1; k >= 0; --k) { 8498 for (c = 0; c < fcomp; ++c) { 8499 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8500 } 8501 } 8502 } 8503 } else { 8504 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8505 if (orientation >= 0) { 8506 for (k = 0; k < fdof; ++k) { 8507 if ((cind < cfdof) && (k == fcdofs[cind])) { 8508 indices[foffs[f]+k] = -(off+foff+k+1); 8509 ++cind; 8510 } else { 8511 indices[foffs[f]+k] = off+foff+k-cind; 8512 } 8513 } 8514 } else { 8515 for (k = fdof/fcomp-1; k >= 0; --k) { 8516 for (c = 0; c < fcomp; ++c) { 8517 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8518 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8519 ++cind; 8520 } else { 8521 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8522 } 8523 } 8524 } 8525 } 8526 } 8527 foff += fdof - cfdof; 8528 foffs[f] += fdof; 8529 } 8530 PetscFunctionReturn(0); 8531 } 8532 8533 #undef __FUNCT__ 8534 #define __FUNCT__ "DMPlexMatSetClosure" 8535 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8536 { 8537 DM_Plex *mesh = (DM_Plex*) dm->data; 8538 PetscInt *points = NULL; 8539 PetscInt *indices; 8540 PetscInt offsets[32]; 8541 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8542 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8543 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8544 PetscErrorCode ierr; 8545 8546 PetscFunctionBegin; 8547 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8548 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8549 if (useDefault) { 8550 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8551 } 8552 if (useGlobalDefault) { 8553 if (useDefault) { 8554 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8555 } else { 8556 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8557 } 8558 } 8559 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8560 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8561 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8562 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8563 /* Compress out points not in the section */ 8564 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8565 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8566 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8567 points[q*2] = points[p]; 8568 points[q*2+1] = points[p+1]; 8569 ++q; 8570 } 8571 } 8572 numPoints = q; 8573 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8574 PetscInt fdof; 8575 8576 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8577 for (f = 0; f < numFields; ++f) { 8578 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8579 offsets[f+1] += fdof; 8580 } 8581 numIndices += dof; 8582 } 8583 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8584 8585 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8586 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8587 if (numFields) { 8588 for (p = 0; p < numPoints*2; p += 2) { 8589 PetscInt o = points[p+1]; 8590 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8591 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8592 } 8593 } else { 8594 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8595 PetscInt o = points[p+1]; 8596 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8597 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8598 } 8599 } 8600 if (useGlobalDefault && !useDefault) { 8601 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8602 } 8603 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8604 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8605 if (ierr) { 8606 PetscMPIInt rank; 8607 PetscErrorCode ierr2; 8608 8609 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8610 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8611 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8612 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8613 CHKERRQ(ierr); 8614 } 8615 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8616 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8617 PetscFunctionReturn(0); 8618 } 8619 8620 #undef __FUNCT__ 8621 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8622 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8623 { 8624 PetscSection coordSection; 8625 Vec coordinates; 8626 const PetscScalar *coords; 8627 const PetscInt dim = 2; 8628 PetscInt d, f; 8629 PetscErrorCode ierr; 8630 8631 PetscFunctionBegin; 8632 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8633 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8634 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8635 if (v0) { 8636 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8637 } 8638 if (J) { 8639 for (d = 0; d < dim; d++) { 8640 for (f = 0; f < dim; f++) { 8641 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8642 } 8643 } 8644 *detJ = J[0]*J[3] - J[1]*J[2]; 8645 #if 0 8646 if (detJ < 0.0) { 8647 const PetscReal xLength = mesh->periodicity[0]; 8648 8649 if (xLength != 0.0) { 8650 PetscReal v0x = coords[0*dim+0]; 8651 8652 if (v0x == 0.0) v0x = v0[0] = xLength; 8653 for (f = 0; f < dim; f++) { 8654 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8655 8656 J[0*dim+f] = 0.5*(px - v0x); 8657 } 8658 } 8659 detJ = J[0]*J[3] - J[1]*J[2]; 8660 } 8661 #endif 8662 PetscLogFlops(8.0 + 3.0); 8663 } 8664 if (invJ) { 8665 const PetscReal invDet = 1.0/(*detJ); 8666 8667 invJ[0] = invDet*J[3]; 8668 invJ[1] = -invDet*J[1]; 8669 invJ[2] = -invDet*J[2]; 8670 invJ[3] = invDet*J[0]; 8671 PetscLogFlops(5.0); 8672 } 8673 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8674 PetscFunctionReturn(0); 8675 } 8676 8677 #undef __FUNCT__ 8678 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8679 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8680 { 8681 PetscSection coordSection; 8682 Vec coordinates; 8683 const PetscScalar *coords; 8684 const PetscInt dim = 2; 8685 PetscInt d, f; 8686 PetscErrorCode ierr; 8687 8688 PetscFunctionBegin; 8689 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8690 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8691 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8692 if (v0) { 8693 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8694 } 8695 if (J) { 8696 for (d = 0; d < dim; d++) { 8697 for (f = 0; f < dim; f++) { 8698 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8699 } 8700 } 8701 *detJ = J[0]*J[3] - J[1]*J[2]; 8702 PetscLogFlops(8.0 + 3.0); 8703 } 8704 if (invJ) { 8705 const PetscReal invDet = 1.0/(*detJ); 8706 8707 invJ[0] = invDet*J[3]; 8708 invJ[1] = -invDet*J[1]; 8709 invJ[2] = -invDet*J[2]; 8710 invJ[3] = invDet*J[0]; 8711 PetscLogFlops(5.0); 8712 } 8713 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8714 PetscFunctionReturn(0); 8715 } 8716 8717 #undef __FUNCT__ 8718 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8719 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8720 { 8721 PetscSection coordSection; 8722 Vec coordinates; 8723 const PetscScalar *coords; 8724 const PetscInt dim = 3; 8725 PetscInt d, f; 8726 PetscErrorCode ierr; 8727 8728 PetscFunctionBegin; 8729 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8730 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8731 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8732 if (v0) { 8733 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8734 } 8735 if (J) { 8736 for (d = 0; d < dim; d++) { 8737 for (f = 0; f < dim; f++) { 8738 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8739 } 8740 } 8741 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8742 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8743 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8744 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8745 PetscLogFlops(18.0 + 12.0); 8746 } 8747 if (invJ) { 8748 const PetscReal invDet = 1.0/(*detJ); 8749 8750 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8751 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8752 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8753 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8754 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8755 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8756 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8757 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8758 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8759 PetscLogFlops(37.0); 8760 } 8761 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8762 PetscFunctionReturn(0); 8763 } 8764 8765 #undef __FUNCT__ 8766 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8767 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8768 { 8769 PetscSection coordSection; 8770 Vec coordinates; 8771 const PetscScalar *coords; 8772 const PetscInt dim = 3; 8773 PetscInt d; 8774 PetscErrorCode ierr; 8775 8776 PetscFunctionBegin; 8777 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8778 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8779 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8780 if (v0) { 8781 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8782 } 8783 if (J) { 8784 for (d = 0; d < dim; d++) { 8785 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8786 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8787 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8788 } 8789 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8790 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8791 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8792 PetscLogFlops(18.0 + 12.0); 8793 } 8794 if (invJ) { 8795 const PetscReal invDet = -1.0/(*detJ); 8796 8797 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8798 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8799 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8800 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8801 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8802 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8803 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8804 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8805 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8806 PetscLogFlops(37.0); 8807 } 8808 *detJ *= 8.0; 8809 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8810 PetscFunctionReturn(0); 8811 } 8812 8813 #undef __FUNCT__ 8814 #define __FUNCT__ "DMPlexComputeCellGeometry" 8815 /*@C 8816 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8817 8818 Collective on DM 8819 8820 Input Arguments: 8821 + dm - the DM 8822 - cell - the cell 8823 8824 Output Arguments: 8825 + v0 - the translation part of this affine transform 8826 . J - the Jacobian of the transform to the reference element 8827 . invJ - the inverse of the Jacobian 8828 - detJ - the Jacobian determinant 8829 8830 Level: advanced 8831 8832 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8833 @*/ 8834 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8835 { 8836 PetscInt dim, coneSize; 8837 PetscErrorCode ierr; 8838 8839 PetscFunctionBegin; 8840 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8841 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8842 switch (dim) { 8843 case 2: 8844 switch (coneSize) { 8845 case 3: 8846 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8847 break; 8848 case 4: 8849 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8850 break; 8851 default: 8852 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8853 } 8854 break; 8855 case 3: 8856 switch (coneSize) { 8857 case 4: 8858 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8859 break; 8860 case 8: 8861 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8862 break; 8863 default: 8864 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8865 } 8866 break; 8867 default: 8868 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8869 } 8870 PetscFunctionReturn(0); 8871 } 8872 8873 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8874 { 8875 switch (i) { 8876 case 0: 8877 switch (j) { 8878 case 0: return 0; 8879 case 1: 8880 switch (k) { 8881 case 0: return 0; 8882 case 1: return 0; 8883 case 2: return 1; 8884 } 8885 case 2: 8886 switch (k) { 8887 case 0: return 0; 8888 case 1: return -1; 8889 case 2: return 0; 8890 } 8891 } 8892 case 1: 8893 switch (j) { 8894 case 0: 8895 switch (k) { 8896 case 0: return 0; 8897 case 1: return 0; 8898 case 2: return -1; 8899 } 8900 case 1: return 0; 8901 case 2: 8902 switch (k) { 8903 case 0: return 1; 8904 case 1: return 0; 8905 case 2: return 0; 8906 } 8907 } 8908 case 2: 8909 switch (j) { 8910 case 0: 8911 switch (k) { 8912 case 0: return 0; 8913 case 1: return 1; 8914 case 2: return 0; 8915 } 8916 case 1: 8917 switch (k) { 8918 case 0: return -1; 8919 case 1: return 0; 8920 case 2: return 0; 8921 } 8922 case 2: return 0; 8923 } 8924 } 8925 return 0; 8926 } 8927 8928 #undef __FUNCT__ 8929 #define __FUNCT__ "DMPlexCreateRigidBody" 8930 /*@C 8931 DMPlexCreateRigidBody - create rigid body modes from coordinates 8932 8933 Collective on DM 8934 8935 Input Arguments: 8936 + dm - the DM 8937 . section - the local section associated with the rigid field, or NULL for the default section 8938 - globalSection - the global section associated with the rigid field, or NULL for the default section 8939 8940 Output Argument: 8941 . sp - the null space 8942 8943 Note: This is necessary to take account of Dirichlet conditions on the displacements 8944 8945 Level: advanced 8946 8947 .seealso: MatNullSpaceCreate() 8948 @*/ 8949 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8950 { 8951 MPI_Comm comm; 8952 Vec coordinates, localMode, mode[6]; 8953 PetscSection coordSection; 8954 PetscScalar *coords; 8955 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8956 PetscErrorCode ierr; 8957 8958 PetscFunctionBegin; 8959 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 8960 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8961 if (dim == 1) { 8962 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 8963 PetscFunctionReturn(0); 8964 } 8965 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8966 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8967 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8968 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8969 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8970 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8971 m = (dim*(dim+1))/2; 8972 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8973 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8974 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8975 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8976 /* Assume P1 */ 8977 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8978 for (d = 0; d < dim; ++d) { 8979 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8980 8981 values[d] = 1.0; 8982 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8983 for (v = vStart; v < vEnd; ++v) { 8984 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8985 } 8986 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8987 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8988 } 8989 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8990 for (d = dim; d < dim*(dim+1)/2; ++d) { 8991 PetscInt i, j, k = dim > 2 ? d - dim : d; 8992 8993 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8994 for (v = vStart; v < vEnd; ++v) { 8995 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8996 PetscInt off; 8997 8998 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8999 for (i = 0; i < dim; ++i) { 9000 for (j = 0; j < dim; ++j) { 9001 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9002 } 9003 } 9004 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9005 } 9006 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9007 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9008 } 9009 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9010 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9011 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 9012 /* Orthonormalize system */ 9013 for (i = dim; i < m; ++i) { 9014 PetscScalar dots[6]; 9015 9016 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9017 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9018 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9019 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 9020 } 9021 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9022 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9023 PetscFunctionReturn(0); 9024 } 9025 9026 #undef __FUNCT__ 9027 #define __FUNCT__ "DMPlexGetHybridBounds" 9028 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9029 { 9030 DM_Plex *mesh = (DM_Plex*) dm->data; 9031 PetscInt dim; 9032 PetscErrorCode ierr; 9033 9034 PetscFunctionBegin; 9035 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9036 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9037 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9038 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9039 if (eMax) *eMax = mesh->hybridPointMax[1]; 9040 if (vMax) *vMax = mesh->hybridPointMax[0]; 9041 PetscFunctionReturn(0); 9042 } 9043 9044 #undef __FUNCT__ 9045 #define __FUNCT__ "DMPlexSetHybridBounds" 9046 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9047 { 9048 DM_Plex *mesh = (DM_Plex*) dm->data; 9049 PetscInt dim; 9050 PetscErrorCode ierr; 9051 9052 PetscFunctionBegin; 9053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9054 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9055 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9056 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9057 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9058 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9059 PetscFunctionReturn(0); 9060 } 9061 9062 #undef __FUNCT__ 9063 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9064 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9065 { 9066 DM_Plex *mesh = (DM_Plex*) dm->data; 9067 9068 PetscFunctionBegin; 9069 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9070 PetscValidPointer(cellHeight, 2); 9071 *cellHeight = mesh->vtkCellHeight; 9072 PetscFunctionReturn(0); 9073 } 9074 9075 #undef __FUNCT__ 9076 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9077 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9078 { 9079 DM_Plex *mesh = (DM_Plex*) dm->data; 9080 9081 PetscFunctionBegin; 9082 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9083 mesh->vtkCellHeight = cellHeight; 9084 PetscFunctionReturn(0); 9085 } 9086 9087 #undef __FUNCT__ 9088 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9089 /* We can easily have a form that takes an IS instead */ 9090 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9091 { 9092 PetscSection section, globalSection; 9093 PetscInt *numbers, p; 9094 PetscErrorCode ierr; 9095 9096 PetscFunctionBegin; 9097 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 9098 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9099 for (p = pStart; p < pEnd; ++p) { 9100 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9101 } 9102 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9103 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9104 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9105 for (p = pStart; p < pEnd; ++p) { 9106 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9107 } 9108 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9109 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9110 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9111 PetscFunctionReturn(0); 9112 } 9113 9114 #undef __FUNCT__ 9115 #define __FUNCT__ "DMPlexGetCellNumbering" 9116 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9117 { 9118 DM_Plex *mesh = (DM_Plex*) dm->data; 9119 PetscInt cellHeight, cStart, cEnd, cMax; 9120 PetscErrorCode ierr; 9121 9122 PetscFunctionBegin; 9123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9124 if (!mesh->globalCellNumbers) { 9125 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9126 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9127 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 9128 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9129 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9130 } 9131 *globalCellNumbers = mesh->globalCellNumbers; 9132 PetscFunctionReturn(0); 9133 } 9134 9135 #undef __FUNCT__ 9136 #define __FUNCT__ "DMPlexGetVertexNumbering" 9137 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9138 { 9139 DM_Plex *mesh = (DM_Plex*) dm->data; 9140 PetscInt vStart, vEnd, vMax; 9141 PetscErrorCode ierr; 9142 9143 PetscFunctionBegin; 9144 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9145 if (!mesh->globalVertexNumbers) { 9146 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9147 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9148 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9149 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9150 } 9151 *globalVertexNumbers = mesh->globalVertexNumbers; 9152 PetscFunctionReturn(0); 9153 } 9154 9155 #undef __FUNCT__ 9156 #define __FUNCT__ "DMPlexGetScale" 9157 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9158 { 9159 DM_Plex *mesh = (DM_Plex*) dm->data; 9160 9161 PetscFunctionBegin; 9162 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9163 PetscValidPointer(scale, 3); 9164 *scale = mesh->scale[unit]; 9165 PetscFunctionReturn(0); 9166 } 9167 9168 #undef __FUNCT__ 9169 #define __FUNCT__ "DMPlexSetScale" 9170 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9171 { 9172 DM_Plex *mesh = (DM_Plex*) dm->data; 9173 9174 PetscFunctionBegin; 9175 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9176 mesh->scale[unit] = scale; 9177 PetscFunctionReturn(0); 9178 } 9179 9180 9181 /******************************************************************************* 9182 This should be in a separate Discretization object, but I am not sure how to lay 9183 it out yet, so I am stuffing things here while I experiment. 9184 *******************************************************************************/ 9185 #undef __FUNCT__ 9186 #define __FUNCT__ "DMPlexSetFEMIntegration" 9187 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9188 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9189 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9190 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9191 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9192 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9193 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9194 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9195 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9196 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9197 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9198 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9199 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9200 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9201 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9202 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9203 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9204 { 9205 DM_Plex *mesh = (DM_Plex*) dm->data; 9206 9207 PetscFunctionBegin; 9208 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9209 mesh->integrateResidualFEM = integrateResidualFEM; 9210 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9211 mesh->integrateJacobianFEM = integrateJacobianFEM; 9212 PetscFunctionReturn(0); 9213 } 9214 9215 #undef __FUNCT__ 9216 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9217 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9218 { 9219 Vec coordinates; 9220 PetscSection section, cSection; 9221 PetscInt dim, vStart, vEnd, v, c, d; 9222 PetscScalar *values, *cArray; 9223 PetscReal *coords; 9224 PetscErrorCode ierr; 9225 9226 PetscFunctionBegin; 9227 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9228 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9229 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9230 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9231 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9232 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9233 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9234 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9235 for (v = vStart; v < vEnd; ++v) { 9236 PetscInt dof, off; 9237 9238 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9239 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9240 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9241 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9242 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9243 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9244 } 9245 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9246 /* Temporary, must be replaced by a projection on the finite element basis */ 9247 { 9248 PetscInt eStart = 0, eEnd = 0, e, depth; 9249 9250 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9251 --depth; 9252 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9253 for (e = eStart; e < eEnd; ++e) { 9254 const PetscInt *cone = NULL; 9255 PetscInt coneSize, d; 9256 PetscScalar *coordsA, *coordsB; 9257 9258 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9259 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9260 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9261 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9262 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9263 for (d = 0; d < dim; ++d) { 9264 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9265 } 9266 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9267 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9268 } 9269 } 9270 9271 ierr = PetscFree(coords);CHKERRQ(ierr); 9272 ierr = PetscFree(values);CHKERRQ(ierr); 9273 #if 0 9274 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9275 PetscReal detJ; 9276 9277 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9278 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9279 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9280 9281 for (PetscInt c = cStart; c < cEnd; ++c) { 9282 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9283 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9284 const int oSize = pV.getSize(); 9285 int v = 0; 9286 9287 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9288 for (PetscInt cl = 0; cl < oSize; ++cl) { 9289 const PetscInt fDim; 9290 9291 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9292 if (pointDim) { 9293 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9294 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9295 } 9296 } 9297 } 9298 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9299 pV.clear(); 9300 } 9301 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9302 ierr = PetscFree(values);CHKERRQ(ierr); 9303 #endif 9304 PetscFunctionReturn(0); 9305 } 9306 9307 #undef __FUNCT__ 9308 #define __FUNCT__ "DMPlexProjectFunction" 9309 /*@C 9310 DMPlexProjectFunction - This projects the given function into the function space provided. 9311 9312 Input Parameters: 9313 + dm - The DM 9314 . numComp - The number of components (functions) 9315 . funcs - The coordinate functions to evaluate 9316 - mode - The insertion mode for values 9317 9318 Output Parameter: 9319 . X - vector 9320 9321 Level: developer 9322 9323 Note: 9324 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9325 We will eventually fix it. 9326 9327 ,seealso: DMPlexComputeL2Diff() 9328 */ 9329 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9330 { 9331 Vec localX; 9332 PetscErrorCode ierr; 9333 9334 PetscFunctionBegin; 9335 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9336 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9337 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9338 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9339 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9340 PetscFunctionReturn(0); 9341 } 9342 9343 #undef __FUNCT__ 9344 #define __FUNCT__ "DMPlexComputeL2Diff" 9345 /*@C 9346 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9347 9348 Input Parameters: 9349 + dm - The DM 9350 . quad - The PetscQuadrature object for each field 9351 . funcs - The functions to evaluate for each field component 9352 - X - The coefficient vector u_h 9353 9354 Output Parameter: 9355 . diff - The diff ||u - u_h||_2 9356 9357 Level: developer 9358 9359 .seealso: DMPlexProjectFunction() 9360 */ 9361 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9362 { 9363 const PetscInt debug = 0; 9364 PetscSection section; 9365 Vec localX; 9366 PetscReal *coords, *v0, *J, *invJ, detJ; 9367 PetscReal localDiff = 0.0; 9368 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9369 PetscErrorCode ierr; 9370 9371 PetscFunctionBegin; 9372 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9373 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9374 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9375 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9376 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9377 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9378 for (field = 0; field < numFields; ++field) { 9379 numComponents += quad[field].numComponents; 9380 } 9381 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9382 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9383 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9384 for (c = cStart; c < cEnd; ++c) { 9385 const PetscScalar *x; 9386 PetscReal elemDiff = 0.0; 9387 9388 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9389 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9390 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9391 9392 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9393 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9394 const PetscReal *quadPoints = quad[field].quadPoints; 9395 const PetscReal *quadWeights = quad[field].quadWeights; 9396 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9397 const PetscInt numBasisComps = quad[field].numComponents; 9398 const PetscReal *basis = quad[field].basis; 9399 PetscInt q, d, e, fc, f; 9400 9401 if (debug) { 9402 char title[1024]; 9403 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9404 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9405 } 9406 for (q = 0; q < numQuadPoints; ++q) { 9407 for (d = 0; d < dim; d++) { 9408 coords[d] = v0[d]; 9409 for (e = 0; e < dim; e++) { 9410 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9411 } 9412 } 9413 for (fc = 0; fc < numBasisComps; ++fc) { 9414 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9415 PetscReal interpolant = 0.0; 9416 for (f = 0; f < numBasisFuncs; ++f) { 9417 const PetscInt fidx = f*numBasisComps+fc; 9418 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9419 } 9420 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9421 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9422 } 9423 } 9424 comp += numBasisComps; 9425 fieldOffset += numBasisFuncs*numBasisComps; 9426 } 9427 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9428 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9429 localDiff += elemDiff; 9430 } 9431 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9432 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9433 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9434 *diff = PetscSqrtReal(*diff); 9435 PetscFunctionReturn(0); 9436 } 9437 9438 #undef __FUNCT__ 9439 #define __FUNCT__ "DMPlexComputeResidualFEM" 9440 /*@ 9441 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9442 9443 Input Parameters: 9444 + dm - The mesh 9445 . X - Local input vector 9446 - user - The user context 9447 9448 Output Parameter: 9449 . F - Local output vector 9450 9451 Note: 9452 The second member of the user context must be an FEMContext. 9453 9454 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9455 like a GPU, or vectorize on a multicore machine. 9456 9457 .seealso: DMPlexComputeJacobianActionFEM() 9458 */ 9459 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9460 { 9461 DM_Plex *mesh = (DM_Plex*) dm->data; 9462 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9463 PetscQuadrature *quad = fem->quad; 9464 PetscSection section; 9465 PetscReal *v0, *J, *invJ, *detJ; 9466 PetscScalar *elemVec, *u; 9467 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9468 PetscInt cellDof = 0, numComponents = 0; 9469 PetscErrorCode ierr; 9470 9471 PetscFunctionBegin; 9472 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9473 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9474 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9475 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9476 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9477 numCells = cEnd - cStart; 9478 for (field = 0; field < numFields; ++field) { 9479 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9480 numComponents += quad[field].numComponents; 9481 } 9482 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9483 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9484 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); 9485 for (c = cStart; c < cEnd; ++c) { 9486 const PetscScalar *x; 9487 PetscInt i; 9488 9489 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9490 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9491 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9492 9493 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9494 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9495 } 9496 for (field = 0; field < numFields; ++field) { 9497 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9498 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9499 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9500 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9501 /* Conforming batches */ 9502 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9503 PetscInt numBlocks = 1; 9504 PetscInt batchSize = numBlocks * blockSize; 9505 PetscInt numBatches = numBatchesTmp; 9506 PetscInt numChunks = numCells / (numBatches*batchSize); 9507 /* Remainder */ 9508 PetscInt numRemainder = numCells % (numBatches * batchSize); 9509 PetscInt offset = numCells - numRemainder; 9510 9511 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9512 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9513 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9514 } 9515 for (c = cStart; c < cEnd; ++c) { 9516 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9517 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9518 } 9519 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9520 if (mesh->printFEM) { 9521 PetscMPIInt rank, numProcs; 9522 PetscInt p; 9523 9524 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9525 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9526 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9527 for (p = 0; p < numProcs; ++p) { 9528 if (p == rank) { 9529 Vec f; 9530 9531 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9532 ierr = VecCopy(F, f);CHKERRQ(ierr); 9533 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9534 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9535 ierr = VecDestroy(&f);CHKERRQ(ierr); 9536 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9537 } 9538 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9539 } 9540 } 9541 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9542 PetscFunctionReturn(0); 9543 } 9544 9545 #undef __FUNCT__ 9546 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9547 /*@C 9548 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9549 9550 Input Parameters: 9551 + dm - The mesh 9552 . J - The Jacobian shell matrix 9553 . X - Local input vector 9554 - user - The user context 9555 9556 Output Parameter: 9557 . F - Local output vector 9558 9559 Note: 9560 The second member of the user context must be an FEMContext. 9561 9562 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9563 like a GPU, or vectorize on a multicore machine. 9564 9565 .seealso: DMPlexComputeResidualFEM() 9566 */ 9567 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9568 { 9569 DM_Plex *mesh = (DM_Plex*) dm->data; 9570 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9571 PetscQuadrature *quad = fem->quad; 9572 PetscSection section; 9573 JacActionCtx *jctx; 9574 PetscReal *v0, *J, *invJ, *detJ; 9575 PetscScalar *elemVec, *u, *a; 9576 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9577 PetscInt cellDof = 0; 9578 PetscErrorCode ierr; 9579 9580 PetscFunctionBegin; 9581 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9582 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9583 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9584 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9585 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9586 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9587 numCells = cEnd - cStart; 9588 for (field = 0; field < numFields; ++field) { 9589 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9590 } 9591 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9592 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); 9593 for (c = cStart; c < cEnd; ++c) { 9594 const PetscScalar *x; 9595 PetscInt i; 9596 9597 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9598 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9599 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9600 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9601 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9602 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9603 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9604 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9605 } 9606 for (field = 0; field < numFields; ++field) { 9607 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9608 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9609 /* Conforming batches */ 9610 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9611 PetscInt numBlocks = 1; 9612 PetscInt batchSize = numBlocks * blockSize; 9613 PetscInt numBatches = numBatchesTmp; 9614 PetscInt numChunks = numCells / (numBatches*batchSize); 9615 /* Remainder */ 9616 PetscInt numRemainder = numCells % (numBatches * batchSize); 9617 PetscInt offset = numCells - numRemainder; 9618 9619 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); 9620 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], 9621 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9622 } 9623 for (c = cStart; c < cEnd; ++c) { 9624 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9625 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9626 } 9627 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9628 if (mesh->printFEM) { 9629 PetscMPIInt rank, numProcs; 9630 PetscInt p; 9631 9632 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9633 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9634 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9635 for (p = 0; p < numProcs; ++p) { 9636 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9637 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9638 } 9639 } 9640 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9641 PetscFunctionReturn(0); 9642 } 9643 9644 #undef __FUNCT__ 9645 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9646 /*@ 9647 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9648 9649 Input Parameters: 9650 + dm - The mesh 9651 . X - Local input vector 9652 - user - The user context 9653 9654 Output Parameter: 9655 . Jac - Jacobian matrix 9656 9657 Note: 9658 The second member of the user context must be an FEMContext. 9659 9660 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9661 like a GPU, or vectorize on a multicore machine. 9662 9663 .seealso: FormFunctionLocal() 9664 */ 9665 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9666 { 9667 DM_Plex *mesh = (DM_Plex*) dm->data; 9668 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9669 PetscQuadrature *quad = fem->quad; 9670 PetscSection section; 9671 PetscReal *v0, *J, *invJ, *detJ; 9672 PetscScalar *elemMat, *u; 9673 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9674 PetscInt cellDof = 0, numComponents = 0; 9675 PetscBool isShell; 9676 PetscErrorCode ierr; 9677 9678 PetscFunctionBegin; 9679 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9680 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9681 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9682 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9683 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9684 numCells = cEnd - cStart; 9685 for (field = 0; field < numFields; ++field) { 9686 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9687 numComponents += quad[field].numComponents; 9688 } 9689 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9690 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9691 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); 9692 for (c = cStart; c < cEnd; ++c) { 9693 const PetscScalar *x; 9694 PetscInt i; 9695 9696 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9697 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9698 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9699 9700 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9701 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9702 } 9703 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9704 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9705 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9706 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9707 PetscInt fieldJ; 9708 9709 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9710 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9711 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9712 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9713 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9714 /* Conforming batches */ 9715 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9716 PetscInt numBlocks = 1; 9717 PetscInt batchSize = numBlocks * blockSize; 9718 PetscInt numBatches = numBatchesTmp; 9719 PetscInt numChunks = numCells / (numBatches*batchSize); 9720 /* Remainder */ 9721 PetscInt numRemainder = numCells % (numBatches * batchSize); 9722 PetscInt offset = numCells - numRemainder; 9723 9724 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9725 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9726 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9727 } 9728 } 9729 for (c = cStart; c < cEnd; ++c) { 9730 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9731 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9732 } 9733 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9734 9735 /* Assemble matrix, using the 2-step process: 9736 MatAssemblyBegin(), MatAssemblyEnd(). */ 9737 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9738 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9739 9740 if (mesh->printFEM) { 9741 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9742 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9743 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9744 } 9745 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9746 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9747 if (isShell) { 9748 JacActionCtx *jctx; 9749 9750 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9751 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9752 } 9753 *str = SAME_NONZERO_PATTERN; 9754 PetscFunctionReturn(0); 9755 } 9756 9757 9758 #undef __FUNCT__ 9759 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9760 /*@C 9761 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9762 the local section and an SF describing the section point overlap. 9763 9764 Input Parameters: 9765 + s - The PetscSection for the local field layout 9766 . sf - The SF describing parallel layout of the section points 9767 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9768 . label - The label specifying the points 9769 - labelValue - The label stratum specifying the points 9770 9771 Output Parameter: 9772 . gsection - The PetscSection for the global field layout 9773 9774 Note: This gives negative sizes and offsets to points not owned by this process 9775 9776 Level: developer 9777 9778 .seealso: PetscSectionCreate() 9779 @*/ 9780 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9781 { 9782 PetscInt *neg; 9783 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9784 PetscErrorCode ierr; 9785 9786 PetscFunctionBegin; 9787 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9788 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9789 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9790 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9791 /* Mark ghost points with negative dof */ 9792 for (p = pStart; p < pEnd; ++p) { 9793 PetscInt value; 9794 9795 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9796 if (value != labelValue) continue; 9797 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9798 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9799 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9800 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9801 neg[p-pStart] = -(dof+1); 9802 } 9803 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9804 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 9805 if (nroots >= 0) { 9806 if (nroots > pEnd - pStart) { 9807 PetscInt *tmpDof; 9808 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9809 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9810 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9811 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9812 for (p = pStart; p < pEnd; ++p) { 9813 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 9814 } 9815 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9816 } else { 9817 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9818 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9819 } 9820 } 9821 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9822 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9823 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9824 9825 (*gsection)->atlasOff[p] = off; 9826 9827 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9828 } 9829 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9830 globalOff -= off; 9831 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9832 (*gsection)->atlasOff[p] += globalOff; 9833 9834 neg[p] = -((*gsection)->atlasOff[p]+1); 9835 } 9836 /* Put in negative offsets for ghost points */ 9837 if (nroots >= 0) { 9838 if (nroots > pEnd - pStart) { 9839 PetscInt *tmpOff; 9840 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9841 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9842 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9843 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9844 for (p = pStart; p < pEnd; ++p) { 9845 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 9846 } 9847 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9848 } else { 9849 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9850 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9851 } 9852 } 9853 ierr = PetscFree(neg);CHKERRQ(ierr); 9854 PetscFunctionReturn(0); 9855 } 9856