1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex*) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 167 if (size > 1) { 168 PetscSF sf; 169 170 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 171 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 172 } 173 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 174 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 175 const char *name; 176 const char *colors[3] = {"red", "blue", "green"}; 177 const int numColors = 3; 178 PetscReal scale = 2.0; 179 PetscScalar *coords; 180 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 181 PetscMPIInt rank, size; 182 183 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 184 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 185 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 186 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 187 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 188 ierr = PetscViewerASCIIPrintf(viewer, "\ 189 \\documentclass[crop,multi=false]{standalone}\n\n\ 190 \\usepackage{tikz}\n\ 191 \\usepackage{pgflibraryshapes}\n\ 192 \\usetikzlibrary{backgrounds}\n\ 193 \\usetikzlibrary{arrows}\n\ 194 \\begin{document}\n\ 195 \\section{%s}\n\ 196 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 197 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 198 for (p = 0; p < size; ++p) { 199 if (p > 0 && p == size-1) { 200 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 201 } else if (p > 0) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 203 } 204 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 207 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 208 /* Plot vertices */ 209 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 210 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 211 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 212 for (v = vStart; v < vEnd; ++v) { 213 PetscInt off, dof, d; 214 215 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 216 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 217 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 218 for (d = 0; d < dof; ++d) { 219 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 220 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 221 } 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 223 } 224 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 225 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 226 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 227 /* Plot edges */ 228 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 229 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 230 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 231 for (e = eStart; e < eEnd; ++e) { 232 const PetscInt *cone; 233 PetscInt coneSize, offA, offB, dof, d; 234 235 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 236 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 237 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 238 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 239 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 240 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 241 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 242 for (d = 0; d < dof; ++d) { 243 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 244 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 245 } 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 247 } 248 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 249 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 250 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 251 /* Plot cells */ 252 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 253 for (c = cStart; c < cEnd; ++c) { 254 PetscInt *closure = PETSC_NULL; 255 PetscInt closureSize, firstPoint = -1; 256 257 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 258 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 259 for (p = 0; p < closureSize*2; p += 2) { 260 const PetscInt point = closure[p]; 261 262 if ((point < vStart) || (point >= vEnd)) continue; 263 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 264 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 265 if (firstPoint < 0) firstPoint = point; 266 } 267 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 268 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 269 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 270 } 271 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 272 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 273 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 274 } else { 275 MPI_Comm comm = ((PetscObject) dm)->comm; 276 PetscInt *sizes; 277 PetscInt locDepth, depth, dim, d; 278 PetscInt pStart, pEnd, p; 279 PetscMPIInt size; 280 281 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 282 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 283 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 284 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 285 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 286 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 287 if (depth == 1) { 288 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 289 pEnd = pEnd - pStart; 290 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 291 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 292 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 293 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 294 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 295 pEnd = pEnd - pStart; 296 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 297 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 298 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 299 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 300 } else { 301 for (d = 0; d <= dim; d++) { 302 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 303 pEnd = pEnd - pStart; 304 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 305 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 306 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 307 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 308 } 309 } 310 ierr = PetscFree(sizes);CHKERRQ(ierr); 311 } 312 PetscFunctionReturn(0); 313 } 314 315 #undef __FUNCT__ 316 #define __FUNCT__ "DMView_Plex" 317 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 318 { 319 PetscBool iascii, isbinary; 320 PetscErrorCode ierr; 321 322 PetscFunctionBegin; 323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 324 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 325 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 326 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 327 if (iascii) { 328 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 329 #if 0 330 } else if (isbinary) { 331 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 332 #endif 333 } 334 PetscFunctionReturn(0); 335 } 336 337 #undef __FUNCT__ 338 #define __FUNCT__ "DMDestroy_Plex" 339 PetscErrorCode DMDestroy_Plex(DM dm) 340 { 341 DM_Plex *mesh = (DM_Plex*) dm->data; 342 DMLabel next = mesh->labels; 343 PetscErrorCode ierr; 344 345 PetscFunctionBegin; 346 if (--mesh->refct > 0) PetscFunctionReturn(0); 347 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 348 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 349 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 350 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 353 while (next) { 354 DMLabel tmp = next->next; 355 356 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 357 next = tmp; 358 } 359 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 360 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 361 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 362 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 363 ierr = PetscFree(mesh);CHKERRQ(ierr); 364 PetscFunctionReturn(0); 365 } 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 369 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 370 { 371 const PetscInt *support = PETSC_NULL; 372 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 373 PetscErrorCode ierr; 374 375 PetscFunctionBegin; 376 if (useClosure) { 377 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 378 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 379 for (s = 0; s < supportSize; ++s) { 380 const PetscInt *cone = PETSC_NULL; 381 PetscInt coneSize, c, q; 382 383 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 384 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 385 for (c = 0; c < coneSize; ++c) { 386 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 387 if (cone[c] == adj[q]) break; 388 } 389 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 390 } 391 } 392 } else { 393 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 394 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 395 for (s = 0; s < supportSize; ++s) { 396 const PetscInt *cone = PETSC_NULL; 397 PetscInt coneSize, c, q; 398 399 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 400 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 401 for (c = 0; c < coneSize; ++c) { 402 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 403 if (cone[c] == adj[q]) break; 404 } 405 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 406 } 407 } 408 } 409 *adjSize = numAdj; 410 PetscFunctionReturn(0); 411 } 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "DMPlexGetAdjacency_Private" 415 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 416 { 417 const PetscInt *star = tmpClosure; 418 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 419 PetscErrorCode ierr; 420 421 PetscFunctionBegin; 422 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 423 for (s = 2; s < starSize*2; s += 2) { 424 const PetscInt *closure = PETSC_NULL; 425 PetscInt closureSize, c, q; 426 427 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 428 for (c = 0; c < closureSize*2; c += 2) { 429 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 430 if (closure[c] == adj[q]) break; 431 } 432 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 433 } 434 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 435 } 436 *adjSize = numAdj; 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNCT__ 441 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 442 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 443 { 444 DM_Plex *mesh = (DM_Plex*) dm->data; 445 446 PetscFunctionBegin; 447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 448 mesh->preallocCenterDim = preallocCenterDim; 449 PetscFunctionReturn(0); 450 } 451 452 #undef __FUNCT__ 453 #define __FUNCT__ "DMPlexPreallocateOperator" 454 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 455 { 456 DM_Plex *mesh = (DM_Plex*) dm->data; 457 MPI_Comm comm = ((PetscObject) dm)->comm; 458 PetscSF sf, sfDof, sfAdj; 459 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 460 PetscInt nleaves, l, p; 461 const PetscInt *leaves; 462 const PetscSFNode *remotes; 463 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 464 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 465 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 466 PetscLayout rLayout; 467 PetscInt locRows, rStart, rEnd, r; 468 PetscMPIInt size; 469 PetscBool useClosure, debug = PETSC_FALSE; 470 PetscErrorCode ierr; 471 472 PetscFunctionBegin; 473 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 474 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 475 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 476 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 477 /* Create dof SF based on point SF */ 478 if (debug) { 479 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 480 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 481 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 485 } 486 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 487 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 488 if (debug) { 489 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 490 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 491 } 492 /* Create section for dof adjacency (dof ==> # adj dof) */ 493 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 494 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 495 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 496 if (mesh->preallocCenterDim == dim) { 497 useClosure = PETSC_FALSE; 498 } else if (mesh->preallocCenterDim == 0) { 499 useClosure = PETSC_TRUE; 500 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 501 502 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 503 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 504 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 505 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 508 /* Fill in the ghost dofs on the interface */ 509 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 510 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 511 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 512 513 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 514 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 515 516 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 517 518 /* 519 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 520 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 521 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 522 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 523 Create sfAdj connecting rootSectionAdj and leafSectionAdj 524 3. Visit unowned points on interface, write adjacencies to adj 525 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 526 4. Visit owned points on interface, write adjacencies to rootAdj 527 Remove redundancy in rootAdj 528 ** The last two traversals use transitive closure 529 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 530 Allocate memory addressed by sectionAdj (cols) 531 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 532 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 533 */ 534 535 for (l = 0; l < nleaves; ++l) { 536 PetscInt dof, off, d, q; 537 PetscInt p = leaves[l], numAdj = maxAdjSize; 538 539 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 540 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 541 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 542 for (q = 0; q < numAdj; ++q) { 543 PetscInt ndof, ncdof; 544 545 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 546 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 547 for (d = off; d < off+dof; ++d) { 548 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 549 } 550 } 551 } 552 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 553 if (debug) { 554 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 555 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 556 } 557 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 558 if (size > 1) { 559 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 560 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 561 } 562 if (debug) { 563 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 564 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 565 } 566 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 567 for (p = pStart; p < pEnd; ++p) { 568 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 569 570 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 571 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 572 if (!dof) continue; 573 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 574 if (adof <= 0) continue; 575 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 576 for (q = 0; q < numAdj; ++q) { 577 PetscInt ndof, ncdof; 578 579 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 580 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 581 for (d = off; d < off+dof; ++d) { 582 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 583 } 584 } 585 } 586 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 587 if (debug) { 588 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 589 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 590 } 591 /* Create adj SF based on dof SF */ 592 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 593 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 594 if (debug) { 595 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 596 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 597 } 598 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 599 /* Create leaf adjacency */ 600 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 601 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 602 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 603 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 604 for (l = 0; l < nleaves; ++l) { 605 PetscInt dof, off, d, q; 606 PetscInt p = leaves[l], numAdj = maxAdjSize; 607 608 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 609 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 610 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 611 for (d = off; d < off+dof; ++d) { 612 PetscInt aoff, i = 0; 613 614 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 615 for (q = 0; q < numAdj; ++q) { 616 PetscInt ndof, ncdof, ngoff, nd; 617 618 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 619 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 621 for (nd = 0; nd < ndof-ncdof; ++nd) { 622 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 623 ++i; 624 } 625 } 626 } 627 } 628 /* Debugging */ 629 if (debug) { 630 IS tmp; 631 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 632 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 633 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 634 } 635 /* Gather adjacenct indices to root */ 636 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 637 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 638 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 639 if (size > 1) { 640 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 641 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 642 } 643 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 644 ierr = PetscFree(adj);CHKERRQ(ierr); 645 /* Debugging */ 646 if (debug) { 647 IS tmp; 648 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 649 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 650 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 651 } 652 /* Add in local adjacency indices for owned dofs on interface (roots) */ 653 for (p = pStart; p < pEnd; ++p) { 654 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 655 656 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 657 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 658 if (!dof) continue; 659 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 660 if (adof <= 0) continue; 661 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 662 for (d = off; d < off+dof; ++d) { 663 PetscInt adof, aoff, i; 664 665 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 666 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 667 i = adof-1; 668 for (q = 0; q < numAdj; ++q) { 669 PetscInt ndof, ncdof, ngoff, nd; 670 671 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 672 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 673 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 674 for (nd = 0; nd < ndof-ncdof; ++nd) { 675 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 676 --i; 677 } 678 } 679 } 680 } 681 /* Debugging */ 682 if (debug) { 683 IS tmp; 684 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 685 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 686 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 687 } 688 /* Compress indices */ 689 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 690 for (p = pStart; p < pEnd; ++p) { 691 PetscInt dof, cdof, off, d; 692 PetscInt adof, aoff; 693 694 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 695 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 696 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 697 if (!dof) continue; 698 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 699 if (adof <= 0) continue; 700 for (d = off; d < off+dof-cdof; ++d) { 701 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 702 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 703 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 704 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 705 } 706 } 707 /* Debugging */ 708 if (debug) { 709 IS tmp; 710 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 711 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 712 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 713 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 714 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 715 } 716 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 717 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 718 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 719 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 720 for (p = pStart; p < pEnd; ++p) { 721 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 722 PetscBool found = PETSC_TRUE; 723 724 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 725 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 727 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 728 for (d = 0; d < dof-cdof; ++d) { 729 PetscInt ldof, rdof; 730 731 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 732 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 733 if (ldof > 0) { 734 /* We do not own this point */ 735 } else if (rdof > 0) { 736 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 737 } else { 738 found = PETSC_FALSE; 739 } 740 } 741 if (found) continue; 742 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 743 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 744 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 745 for (q = 0; q < numAdj; ++q) { 746 PetscInt ndof, ncdof, noff; 747 748 /* Adjacent points may not be in the section chart */ 749 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 750 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 751 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 752 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 753 for (d = goff; d < goff+dof-cdof; ++d) { 754 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 755 } 756 } 757 } 758 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 759 if (debug) { 760 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 761 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 762 } 763 /* Get adjacent indices */ 764 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 765 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 768 PetscBool found = PETSC_TRUE; 769 770 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 771 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 772 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 773 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 774 for (d = 0; d < dof-cdof; ++d) { 775 PetscInt ldof, rdof; 776 777 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 778 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 779 if (ldof > 0) { 780 /* We do not own this point */ 781 } else if (rdof > 0) { 782 PetscInt aoff, roff; 783 784 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 786 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 787 } else { 788 found = PETSC_FALSE; 789 } 790 } 791 if (found) continue; 792 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 793 for (d = goff; d < goff+dof-cdof; ++d) { 794 PetscInt adof, aoff, i = 0; 795 796 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 797 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 798 for (q = 0; q < numAdj; ++q) { 799 PetscInt ndof, ncdof, ngoff, nd; 800 const PetscInt *ncind; 801 802 /* Adjacent points may not be in the section chart */ 803 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 804 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 805 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 806 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 807 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 808 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 809 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 810 } 811 } 812 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); 813 } 814 } 815 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 816 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 817 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 818 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 819 /* Debugging */ 820 if (debug) { 821 IS tmp; 822 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 823 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 824 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 825 } 826 /* Create allocation vectors from adjacency graph */ 827 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 828 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 829 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 830 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 831 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 832 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 833 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 834 /* Only loop over blocks of rows */ 835 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 836 for (r = rStart/bs; r < rEnd/bs; ++r) { 837 const PetscInt row = r*bs; 838 PetscInt numCols, cStart, c; 839 840 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 841 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 842 for (c = cStart; c < cStart+numCols; ++c) { 843 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 844 ++dnz[r-rStart]; 845 if (cols[c] >= row) ++dnzu[r-rStart]; 846 } else { 847 ++onz[r-rStart]; 848 if (cols[c] >= row) ++onzu[r-rStart]; 849 } 850 } 851 } 852 if (bs > 1) { 853 for (r = 0; r < locRows/bs; ++r) { 854 dnz[r] /= bs; 855 onz[r] /= bs; 856 dnzu[r] /= bs; 857 onzu[r] /= bs; 858 } 859 } 860 /* Set matrix pattern */ 861 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 862 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 863 /* Fill matrix with zeros */ 864 if (fillMatrix) { 865 PetscScalar *values; 866 PetscInt maxRowLen = 0; 867 868 for (r = rStart; r < rEnd; ++r) { 869 PetscInt len; 870 871 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 872 maxRowLen = PetscMax(maxRowLen, len); 873 } 874 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 875 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 876 for (r = rStart; r < rEnd; ++r) { 877 PetscInt numCols, cStart; 878 879 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 880 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 881 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 882 } 883 ierr = PetscFree(values);CHKERRQ(ierr); 884 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 885 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 886 } 887 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 888 ierr = PetscFree(cols);CHKERRQ(ierr); 889 PetscFunctionReturn(0); 890 } 891 892 #if 0 893 #undef __FUNCT__ 894 #define __FUNCT__ "DMPlexPreallocateOperator_2" 895 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 896 { 897 PetscInt *tmpClosure,*tmpAdj,*visits; 898 PetscInt c,cStart,cEnd,pStart,pEnd; 899 PetscErrorCode ierr; 900 901 PetscFunctionBegin; 902 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 903 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 904 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 905 906 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 907 908 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 909 npoints = pEnd - pStart; 910 911 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 912 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 913 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 914 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 915 for (c=cStart; c<cEnd; c++) { 916 PetscInt *support = tmpClosure; 917 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 918 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 919 } 920 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 921 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 922 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 923 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 924 925 ierr = PetscSFGetRanks();CHKERRQ(ierr); 926 927 928 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 929 for (c=cStart; c<cEnd; c++) { 930 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 931 /* 932 Depth-first walk of transitive closure. 933 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. 934 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 935 */ 936 } 937 938 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 939 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 940 PetscFunctionReturn(0); 941 } 942 #endif 943 944 #undef __FUNCT__ 945 #define __FUNCT__ "DMCreateMatrix_Plex" 946 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 947 { 948 PetscSection section, sectionGlobal; 949 PetscInt bs = -1; 950 PetscInt localSize; 951 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 952 PetscErrorCode ierr; 953 954 PetscFunctionBegin; 955 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 956 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 957 #endif 958 if (!mtype) mtype = MATAIJ; 959 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 960 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 961 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 962 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 963 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 964 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 965 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 966 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 967 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 974 /* Check for symmetric storage */ 975 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 976 if (isSymmetric) { 977 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 978 } 979 if (!isShell) { 980 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 981 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 982 983 if (bs < 0) { 984 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 985 PetscInt pStart, pEnd, p, dof, cdof; 986 987 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 988 for (p = pStart; p < pEnd; ++p) { 989 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 990 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 991 if (dof-cdof) { 992 if (bs < 0) { 993 bs = dof-cdof; 994 } else if (bs != dof-cdof) { 995 /* Layout does not admit a pointwise block size */ 996 bs = 1; 997 break; 998 } 999 } 1000 } 1001 /* Must have same blocksize on all procs (some might have no points) */ 1002 bsLocal = bs; 1003 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1004 bsLocal = bs < 0 ? bsMax : bs; 1005 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1006 if (bsMin != bsMax) { 1007 bs = 1; 1008 } else { 1009 bs = bsMax; 1010 } 1011 } else { 1012 bs = 1; 1013 } 1014 } 1015 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1016 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1017 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1018 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1019 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1020 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1021 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1022 } 1023 PetscFunctionReturn(0); 1024 } 1025 1026 #undef __FUNCT__ 1027 #define __FUNCT__ "DMPlexGetDimension" 1028 /*@ 1029 DMPlexGetDimension - Return the topological mesh dimension 1030 1031 Not collective 1032 1033 Input Parameter: 1034 . mesh - The DMPlex 1035 1036 Output Parameter: 1037 . dim - The topological mesh dimension 1038 1039 Level: beginner 1040 1041 .seealso: DMPlexCreate() 1042 @*/ 1043 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1044 { 1045 DM_Plex *mesh = (DM_Plex*) dm->data; 1046 1047 PetscFunctionBegin; 1048 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1049 PetscValidPointer(dim, 2); 1050 *dim = mesh->dim; 1051 PetscFunctionReturn(0); 1052 } 1053 1054 #undef __FUNCT__ 1055 #define __FUNCT__ "DMPlexSetDimension" 1056 /*@ 1057 DMPlexSetDimension - Set the topological mesh dimension 1058 1059 Collective on mesh 1060 1061 Input Parameters: 1062 + mesh - The DMPlex 1063 - dim - The topological mesh dimension 1064 1065 Level: beginner 1066 1067 .seealso: DMPlexCreate() 1068 @*/ 1069 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1070 { 1071 DM_Plex *mesh = (DM_Plex*) dm->data; 1072 1073 PetscFunctionBegin; 1074 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1075 PetscValidLogicalCollectiveInt(dm, dim, 2); 1076 mesh->dim = dim; 1077 mesh->preallocCenterDim = dim; 1078 PetscFunctionReturn(0); 1079 } 1080 1081 #undef __FUNCT__ 1082 #define __FUNCT__ "DMPlexGetChart" 1083 /*@ 1084 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1085 1086 Not collective 1087 1088 Input Parameter: 1089 . mesh - The DMPlex 1090 1091 Output Parameters: 1092 + pStart - The first mesh point 1093 - pEnd - The upper bound for mesh points 1094 1095 Level: beginner 1096 1097 .seealso: DMPlexCreate(), DMPlexSetChart() 1098 @*/ 1099 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1100 { 1101 DM_Plex *mesh = (DM_Plex*) dm->data; 1102 PetscErrorCode ierr; 1103 1104 PetscFunctionBegin; 1105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1106 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1107 PetscFunctionReturn(0); 1108 } 1109 1110 #undef __FUNCT__ 1111 #define __FUNCT__ "DMPlexSetChart" 1112 /*@ 1113 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1114 1115 Not collective 1116 1117 Input Parameters: 1118 + mesh - The DMPlex 1119 . pStart - The first mesh point 1120 - pEnd - The upper bound for mesh points 1121 1122 Output Parameters: 1123 1124 Level: beginner 1125 1126 .seealso: DMPlexCreate(), DMPlexGetChart() 1127 @*/ 1128 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1129 { 1130 DM_Plex *mesh = (DM_Plex*) dm->data; 1131 PetscErrorCode ierr; 1132 1133 PetscFunctionBegin; 1134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1135 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1136 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1137 PetscFunctionReturn(0); 1138 } 1139 1140 #undef __FUNCT__ 1141 #define __FUNCT__ "DMPlexGetConeSize" 1142 /*@ 1143 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1144 1145 Not collective 1146 1147 Input Parameters: 1148 + mesh - The DMPlex 1149 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1150 1151 Output Parameter: 1152 . size - The cone size for point p 1153 1154 Level: beginner 1155 1156 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1157 @*/ 1158 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1159 { 1160 DM_Plex *mesh = (DM_Plex*) dm->data; 1161 PetscErrorCode ierr; 1162 1163 PetscFunctionBegin; 1164 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1165 PetscValidPointer(size, 3); 1166 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1167 PetscFunctionReturn(0); 1168 } 1169 1170 #undef __FUNCT__ 1171 #define __FUNCT__ "DMPlexSetConeSize" 1172 /*@ 1173 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1174 1175 Not collective 1176 1177 Input Parameters: 1178 + mesh - The DMPlex 1179 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1180 - size - The cone size for point p 1181 1182 Output Parameter: 1183 1184 Note: 1185 This should be called after DMPlexSetChart(). 1186 1187 Level: beginner 1188 1189 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1190 @*/ 1191 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1192 { 1193 DM_Plex *mesh = (DM_Plex*) dm->data; 1194 PetscErrorCode ierr; 1195 1196 PetscFunctionBegin; 1197 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1198 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1199 1200 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1201 PetscFunctionReturn(0); 1202 } 1203 1204 #undef __FUNCT__ 1205 #define __FUNCT__ "DMPlexGetCone" 1206 /*@C 1207 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1208 1209 Not collective 1210 1211 Input Parameters: 1212 + mesh - The DMPlex 1213 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1214 1215 Output Parameter: 1216 . cone - An array of points which are on the in-edges for point p 1217 1218 Level: beginner 1219 1220 Note: 1221 This routine is not available in Fortran. 1222 1223 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1224 @*/ 1225 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1226 { 1227 DM_Plex *mesh = (DM_Plex*) dm->data; 1228 PetscInt off; 1229 PetscErrorCode ierr; 1230 1231 PetscFunctionBegin; 1232 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1233 PetscValidPointer(cone, 3); 1234 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1235 *cone = &mesh->cones[off]; 1236 PetscFunctionReturn(0); 1237 } 1238 1239 #undef __FUNCT__ 1240 #define __FUNCT__ "DMPlexSetCone" 1241 /*@ 1242 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1243 1244 Not collective 1245 1246 Input Parameters: 1247 + mesh - The DMPlex 1248 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1249 - cone - An array of points which are on the in-edges for point p 1250 1251 Output Parameter: 1252 1253 Note: 1254 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1255 1256 Level: beginner 1257 1258 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1259 @*/ 1260 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1261 { 1262 DM_Plex *mesh = (DM_Plex*) dm->data; 1263 PetscInt pStart, pEnd; 1264 PetscInt dof, off, c; 1265 PetscErrorCode ierr; 1266 1267 PetscFunctionBegin; 1268 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1269 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1270 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1271 if (dof) PetscValidPointer(cone, 3); 1272 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1273 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1274 for (c = 0; c < dof; ++c) { 1275 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1276 mesh->cones[off+c] = cone[c]; 1277 } 1278 PetscFunctionReturn(0); 1279 } 1280 1281 #undef __FUNCT__ 1282 #define __FUNCT__ "DMPlexGetConeOrientation" 1283 /*@C 1284 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1285 1286 Not collective 1287 1288 Input Parameters: 1289 + mesh - The DMPlex 1290 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1291 1292 Output Parameter: 1293 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1294 integer giving the prescription for cone traversal. If it is negative, the cone is 1295 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1296 the index of the cone point on which to start. 1297 1298 Level: beginner 1299 1300 Note: 1301 This routine is not available in Fortran. 1302 1303 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1304 @*/ 1305 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1306 { 1307 DM_Plex *mesh = (DM_Plex*) dm->data; 1308 PetscInt off; 1309 PetscErrorCode ierr; 1310 1311 PetscFunctionBegin; 1312 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1313 #if defined(PETSC_USE_DEBUG) 1314 { 1315 PetscInt dof; 1316 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1317 if (dof) PetscValidPointer(coneOrientation, 3); 1318 } 1319 #endif 1320 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1321 1322 *coneOrientation = &mesh->coneOrientations[off]; 1323 PetscFunctionReturn(0); 1324 } 1325 1326 #undef __FUNCT__ 1327 #define __FUNCT__ "DMPlexSetConeOrientation" 1328 /*@ 1329 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1330 1331 Not collective 1332 1333 Input Parameters: 1334 + mesh - The DMPlex 1335 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1336 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1337 integer giving the prescription for cone traversal. If it is negative, the cone is 1338 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1339 the index of the cone point on which to start. 1340 1341 Output Parameter: 1342 1343 Note: 1344 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1345 1346 Level: beginner 1347 1348 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1349 @*/ 1350 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1351 { 1352 DM_Plex *mesh = (DM_Plex*) dm->data; 1353 PetscInt pStart, pEnd; 1354 PetscInt dof, off, c; 1355 PetscErrorCode ierr; 1356 1357 PetscFunctionBegin; 1358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1359 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1360 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1361 if (dof) PetscValidPointer(coneOrientation, 3); 1362 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1363 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1364 for (c = 0; c < dof; ++c) { 1365 PetscInt cdof, o = coneOrientation[c]; 1366 1367 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1368 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1369 mesh->coneOrientations[off+c] = o; 1370 } 1371 PetscFunctionReturn(0); 1372 } 1373 1374 #undef __FUNCT__ 1375 #define __FUNCT__ "DMPlexInsertCone" 1376 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1377 { 1378 DM_Plex *mesh = (DM_Plex*) dm->data; 1379 PetscInt pStart, pEnd; 1380 PetscInt dof, off; 1381 PetscErrorCode ierr; 1382 1383 PetscFunctionBegin; 1384 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1385 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1386 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1387 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1388 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1389 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1390 if (conePos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1391 mesh->cones[off+conePos] = conePoint; 1392 PetscFunctionReturn(0); 1393 } 1394 1395 #undef __FUNCT__ 1396 #define __FUNCT__ "DMPlexGetSupportSize" 1397 /*@ 1398 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1399 1400 Not collective 1401 1402 Input Parameters: 1403 + mesh - The DMPlex 1404 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1405 1406 Output Parameter: 1407 . size - The support size for point p 1408 1409 Level: beginner 1410 1411 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1412 @*/ 1413 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1414 { 1415 DM_Plex *mesh = (DM_Plex*) dm->data; 1416 PetscErrorCode ierr; 1417 1418 PetscFunctionBegin; 1419 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1420 PetscValidPointer(size, 3); 1421 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1422 PetscFunctionReturn(0); 1423 } 1424 1425 #undef __FUNCT__ 1426 #define __FUNCT__ "DMPlexSetSupportSize" 1427 /*@ 1428 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1429 1430 Not collective 1431 1432 Input Parameters: 1433 + mesh - The DMPlex 1434 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1435 - size - The support size for point p 1436 1437 Output Parameter: 1438 1439 Note: 1440 This should be called after DMPlexSetChart(). 1441 1442 Level: beginner 1443 1444 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1445 @*/ 1446 PetscErrorCode DMPlexSetSupportSize(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 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1454 1455 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1456 PetscFunctionReturn(0); 1457 } 1458 1459 #undef __FUNCT__ 1460 #define __FUNCT__ "DMPlexGetSupport" 1461 /*@C 1462 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1463 1464 Not collective 1465 1466 Input Parameters: 1467 + mesh - The DMPlex 1468 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1469 1470 Output Parameter: 1471 . support - An array of points which are on the out-edges for point p 1472 1473 Level: beginner 1474 1475 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1476 @*/ 1477 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1478 { 1479 DM_Plex *mesh = (DM_Plex*) dm->data; 1480 PetscInt off; 1481 PetscErrorCode ierr; 1482 1483 PetscFunctionBegin; 1484 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1485 PetscValidPointer(support, 3); 1486 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1487 *support = &mesh->supports[off]; 1488 PetscFunctionReturn(0); 1489 } 1490 1491 #undef __FUNCT__ 1492 #define __FUNCT__ "DMPlexSetSupport" 1493 /*@ 1494 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1495 1496 Not collective 1497 1498 Input Parameters: 1499 + mesh - The DMPlex 1500 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1501 - support - An array of points which are on the in-edges for point p 1502 1503 Output Parameter: 1504 1505 Note: 1506 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1507 1508 Level: beginner 1509 1510 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1511 @*/ 1512 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1513 { 1514 DM_Plex *mesh = (DM_Plex*) dm->data; 1515 PetscInt pStart, pEnd; 1516 PetscInt dof, off, c; 1517 PetscErrorCode ierr; 1518 1519 PetscFunctionBegin; 1520 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1521 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1522 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1523 if (dof) PetscValidPointer(support, 3); 1524 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1525 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1526 for (c = 0; c < dof; ++c) { 1527 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1528 mesh->supports[off+c] = support[c]; 1529 } 1530 PetscFunctionReturn(0); 1531 } 1532 1533 #undef __FUNCT__ 1534 #define __FUNCT__ "DMPlexInsertSupport" 1535 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1536 { 1537 DM_Plex *mesh = (DM_Plex*) dm->data; 1538 PetscInt pStart, pEnd; 1539 PetscInt dof, off; 1540 PetscErrorCode ierr; 1541 1542 PetscFunctionBegin; 1543 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1544 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1545 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1546 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1547 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1548 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1549 if (supportPos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1550 mesh->supports[off+supportPos] = supportPoint; 1551 PetscFunctionReturn(0); 1552 } 1553 1554 #undef __FUNCT__ 1555 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1556 /*@C 1557 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1558 1559 Not collective 1560 1561 Input Parameters: 1562 + mesh - The DMPlex 1563 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1564 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1565 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1566 1567 Output Parameters: 1568 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1569 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1570 1571 Note: 1572 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1573 1574 Level: beginner 1575 1576 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1577 @*/ 1578 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1579 { 1580 DM_Plex *mesh = (DM_Plex*) dm->data; 1581 PetscInt *closure, *fifo; 1582 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1583 PetscInt tmpSize, t; 1584 PetscInt depth = 0, maxSize; 1585 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1586 PetscErrorCode ierr; 1587 1588 PetscFunctionBegin; 1589 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1590 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1591 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1592 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1593 if (*points) { 1594 closure = *points; 1595 } else { 1596 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1597 } 1598 closure[0] = p; closure[1] = 0; 1599 /* This is only 1-level */ 1600 if (useCone) { 1601 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1602 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1603 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1604 } else { 1605 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1606 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1607 } 1608 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1609 const PetscInt cp = tmp[t]; 1610 const PetscInt co = tmpO ? tmpO[t] : 0; 1611 1612 closure[closureSize] = cp; 1613 closure[closureSize+1] = co; 1614 fifo[fifoSize] = cp; 1615 fifo[fifoSize+1] = co; 1616 } 1617 while (fifoSize - fifoStart) { 1618 const PetscInt q = fifo[fifoStart]; 1619 const PetscInt o = fifo[fifoStart+1]; 1620 const PetscInt rev = o >= 0 ? 0 : 1; 1621 const PetscInt off = rev ? -(o+1) : o; 1622 1623 if (useCone) { 1624 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1625 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1626 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1627 } else { 1628 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1629 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1630 tmpO = PETSC_NULL; 1631 } 1632 for (t = 0; t < tmpSize; ++t) { 1633 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1634 const PetscInt cp = tmp[i]; 1635 /* Must propogate orientation */ 1636 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1637 PetscInt c; 1638 1639 /* Check for duplicate */ 1640 for (c = 0; c < closureSize; c += 2) { 1641 if (closure[c] == cp) break; 1642 } 1643 if (c == closureSize) { 1644 closure[closureSize] = cp; 1645 closure[closureSize+1] = co; 1646 fifo[fifoSize] = cp; 1647 fifo[fifoSize+1] = co; 1648 closureSize += 2; 1649 fifoSize += 2; 1650 } 1651 } 1652 fifoStart += 2; 1653 } 1654 if (numPoints) *numPoints = closureSize/2; 1655 if (points) *points = closure; 1656 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1657 PetscFunctionReturn(0); 1658 } 1659 1660 #undef __FUNCT__ 1661 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1662 /*@C 1663 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1664 1665 Not collective 1666 1667 Input Parameters: 1668 + mesh - The DMPlex 1669 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1670 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1671 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1672 1673 Output Parameters: 1674 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1675 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1676 1677 Note: 1678 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1679 1680 Level: beginner 1681 1682 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1683 @*/ 1684 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1685 { 1686 PetscErrorCode ierr; 1687 1688 PetscFunctionBegin; 1689 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1690 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1691 PetscFunctionReturn(0); 1692 } 1693 1694 #undef __FUNCT__ 1695 #define __FUNCT__ "DMPlexGetFaces" 1696 /* 1697 DMPlexGetFaces - 1698 1699 Note: This will only work for cell-vertex meshes. 1700 */ 1701 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1702 { 1703 DM_Plex *mesh = (DM_Plex*) dm->data; 1704 const PetscInt *cone = PETSC_NULL; 1705 PetscInt depth = 0, dim, coneSize; 1706 PetscErrorCode ierr; 1707 1708 PetscFunctionBegin; 1709 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1710 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1711 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1712 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1713 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1714 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1715 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1716 switch (dim) { 1717 case 2: 1718 switch (coneSize) { 1719 case 3: 1720 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1721 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1722 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1723 *numFaces = 3; 1724 *faceSize = 2; 1725 *faces = mesh->facesTmp; 1726 break; 1727 case 4: 1728 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1729 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1730 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1731 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1732 *numFaces = 4; 1733 *faceSize = 2; 1734 *faces = mesh->facesTmp; 1735 break; 1736 default: 1737 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1738 } 1739 break; 1740 case 3: 1741 switch (coneSize) { 1742 case 3: 1743 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1744 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1745 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1746 *numFaces = 3; 1747 *faceSize = 2; 1748 *faces = mesh->facesTmp; 1749 break; 1750 case 4: 1751 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1752 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1753 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1754 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1755 *numFaces = 4; 1756 *faceSize = 3; 1757 *faces = mesh->facesTmp; 1758 break; 1759 default: 1760 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1761 } 1762 break; 1763 default: 1764 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1765 } 1766 PetscFunctionReturn(0); 1767 } 1768 1769 #undef __FUNCT__ 1770 #define __FUNCT__ "DMPlexGetMaxSizes" 1771 /*@ 1772 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1773 1774 Not collective 1775 1776 Input Parameter: 1777 . mesh - The DMPlex 1778 1779 Output Parameters: 1780 + maxConeSize - The maximum number of in-edges 1781 - maxSupportSize - The maximum number of out-edges 1782 1783 Level: beginner 1784 1785 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1786 @*/ 1787 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1788 { 1789 DM_Plex *mesh = (DM_Plex*) dm->data; 1790 1791 PetscFunctionBegin; 1792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1793 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1794 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1795 PetscFunctionReturn(0); 1796 } 1797 1798 #undef __FUNCT__ 1799 #define __FUNCT__ "DMSetUp_Plex" 1800 PetscErrorCode DMSetUp_Plex(DM dm) 1801 { 1802 DM_Plex *mesh = (DM_Plex*) dm->data; 1803 PetscInt size; 1804 PetscErrorCode ierr; 1805 1806 PetscFunctionBegin; 1807 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1808 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1809 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1810 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1811 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1812 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1813 if (mesh->maxSupportSize) { 1814 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1815 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1816 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1817 } 1818 PetscFunctionReturn(0); 1819 } 1820 1821 #undef __FUNCT__ 1822 #define __FUNCT__ "DMCreateSubDM_Plex" 1823 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1824 { 1825 PetscSection section, sectionGlobal; 1826 PetscInt *subIndices; 1827 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1828 PetscErrorCode ierr; 1829 1830 PetscFunctionBegin; 1831 if (!numFields) PetscFunctionReturn(0); 1832 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1833 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1834 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1835 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1836 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1837 if (numFields > nF) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1838 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1839 for (p = pStart; p < pEnd; ++p) { 1840 PetscInt gdof; 1841 1842 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1843 if (gdof > 0) { 1844 for (f = 0; f < numFields; ++f) { 1845 PetscInt fdof, fcdof; 1846 1847 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1848 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1849 subSize += fdof-fcdof; 1850 } 1851 } 1852 } 1853 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1854 for (p = pStart; p < pEnd; ++p) { 1855 PetscInt gdof, goff; 1856 1857 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1858 if (gdof > 0) { 1859 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1860 for (f = 0; f < numFields; ++f) { 1861 PetscInt fdof, fcdof, fc, f2, poff = 0; 1862 1863 /* Can get rid of this loop by storing field information in the global section */ 1864 for (f2 = 0; f2 < fields[f]; ++f2) { 1865 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1866 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1867 poff += fdof-fcdof; 1868 } 1869 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1870 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1871 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1872 subIndices[subOff] = goff+poff+fc; 1873 } 1874 } 1875 } 1876 } 1877 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1878 if (subdm) { 1879 PetscSection subsection; 1880 PetscBool haveNull = PETSC_FALSE; 1881 PetscInt f, nf = 0; 1882 1883 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1884 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1885 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1886 for (f = 0; f < numFields; ++f) { 1887 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1888 if ((*subdm)->nullspaceConstructors[f]) { 1889 haveNull = PETSC_TRUE; 1890 nf = f; 1891 } 1892 } 1893 if (haveNull) { 1894 MatNullSpace nullSpace; 1895 1896 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1897 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1898 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1899 } 1900 if (dm->fields) { 1901 if (nF != dm->numFields) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1902 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1903 for (f = 0; f < numFields; ++f) { 1904 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1905 } 1906 if (numFields == 1) { 1907 MatNullSpace space; 1908 Mat pmat; 1909 1910 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1911 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1912 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1913 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1914 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1915 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1916 } 1917 } 1918 } 1919 PetscFunctionReturn(0); 1920 } 1921 1922 #undef __FUNCT__ 1923 #define __FUNCT__ "DMPlexSymmetrize" 1924 /*@ 1925 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1926 1927 Not collective 1928 1929 Input Parameter: 1930 . mesh - The DMPlex 1931 1932 Output Parameter: 1933 1934 Note: 1935 This should be called after all calls to DMPlexSetCone() 1936 1937 Level: beginner 1938 1939 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1940 @*/ 1941 PetscErrorCode DMPlexSymmetrize(DM dm) 1942 { 1943 DM_Plex *mesh = (DM_Plex*) dm->data; 1944 PetscInt *offsets; 1945 PetscInt supportSize; 1946 PetscInt pStart, pEnd, p; 1947 PetscErrorCode ierr; 1948 1949 PetscFunctionBegin; 1950 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1951 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1952 /* Calculate support sizes */ 1953 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1954 for (p = pStart; p < pEnd; ++p) { 1955 PetscInt dof, off, c; 1956 1957 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1958 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1959 for (c = off; c < off+dof; ++c) { 1960 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1961 } 1962 } 1963 for (p = pStart; p < pEnd; ++p) { 1964 PetscInt dof; 1965 1966 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1967 1968 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1969 } 1970 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1971 /* Calculate supports */ 1972 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1973 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1974 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1975 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1976 for (p = pStart; p < pEnd; ++p) { 1977 PetscInt dof, off, c; 1978 1979 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1980 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1981 for (c = off; c < off+dof; ++c) { 1982 const PetscInt q = mesh->cones[c]; 1983 PetscInt offS; 1984 1985 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1986 1987 mesh->supports[offS+offsets[q]] = p; 1988 ++offsets[q]; 1989 } 1990 } 1991 ierr = PetscFree(offsets);CHKERRQ(ierr); 1992 PetscFunctionReturn(0); 1993 } 1994 1995 #undef __FUNCT__ 1996 #define __FUNCT__ "DMPlexSetDepth_Private" 1997 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1998 { 1999 PetscInt d; 2000 PetscErrorCode ierr; 2001 2002 PetscFunctionBegin; 2003 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 2004 if (d < 0) { 2005 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2006 const PetscInt *cone = PETSC_NULL; 2007 PetscInt dCone; 2008 2009 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2010 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2011 d = dCone+1; 2012 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2013 } 2014 *depth = d; 2015 PetscFunctionReturn(0); 2016 } 2017 2018 #undef __FUNCT__ 2019 #define __FUNCT__ "DMPlexStratify" 2020 /*@ 2021 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2022 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2023 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2024 the DAG. 2025 2026 Not collective 2027 2028 Input Parameter: 2029 . mesh - The DMPlex 2030 2031 Output Parameter: 2032 2033 Notes: 2034 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2035 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2036 2037 This should be called after all calls to DMPlexSymmetrize() 2038 2039 Level: beginner 2040 2041 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2042 @*/ 2043 PetscErrorCode DMPlexStratify(DM dm) 2044 { 2045 DM_Plex *mesh = (DM_Plex*) dm->data; 2046 PetscInt pStart, pEnd, p; 2047 PetscInt numRoots = 0, numLeaves = 0; 2048 PetscErrorCode ierr; 2049 2050 PetscFunctionBegin; 2051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2052 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2053 /* Calculate depth */ 2054 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2055 /* Initialize roots and count leaves */ 2056 for (p = pStart; p < pEnd; ++p) { 2057 PetscInt coneSize, supportSize; 2058 2059 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2060 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2061 if (!coneSize && supportSize) { 2062 ++numRoots; 2063 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2064 } else if (!supportSize && coneSize) { 2065 ++numLeaves; 2066 } else if (!supportSize && !coneSize) { 2067 /* Isolated points */ 2068 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2069 } 2070 } 2071 if (numRoots + numLeaves == (pEnd - pStart)) { 2072 for (p = pStart; p < pEnd; ++p) { 2073 PetscInt coneSize, supportSize; 2074 2075 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2076 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2077 if (!supportSize && coneSize) { 2078 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2079 } 2080 } 2081 } else { 2082 /* This might be slow since lookup is not fast */ 2083 for (p = pStart; p < pEnd; ++p) { 2084 PetscInt depth; 2085 2086 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2087 } 2088 } 2089 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2090 PetscFunctionReturn(0); 2091 } 2092 2093 #undef __FUNCT__ 2094 #define __FUNCT__ "DMPlexGetJoin" 2095 /*@C 2096 DMPlexGetJoin - Get an array for the join of the set of points 2097 2098 Not Collective 2099 2100 Input Parameters: 2101 + dm - The DMPlex object 2102 . numPoints - The number of input points for the join 2103 - points - The input points 2104 2105 Output Parameters: 2106 + numCoveredPoints - The number of points in the join 2107 - coveredPoints - The points in the join 2108 2109 Level: intermediate 2110 2111 Note: Currently, this is restricted to a single level join 2112 2113 .keywords: mesh 2114 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2115 @*/ 2116 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2117 { 2118 DM_Plex *mesh = (DM_Plex*) dm->data; 2119 PetscInt *join[2]; 2120 PetscInt joinSize, i = 0; 2121 PetscInt dof, off, p, c, m; 2122 PetscErrorCode ierr; 2123 2124 PetscFunctionBegin; 2125 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2126 PetscValidPointer(points, 2); 2127 PetscValidPointer(numCoveredPoints, 3); 2128 PetscValidPointer(coveredPoints, 4); 2129 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2130 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2131 /* Copy in support of first point */ 2132 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2133 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2134 for (joinSize = 0; joinSize < dof; ++joinSize) { 2135 join[i][joinSize] = mesh->supports[off+joinSize]; 2136 } 2137 /* Check each successive support */ 2138 for (p = 1; p < numPoints; ++p) { 2139 PetscInt newJoinSize = 0; 2140 2141 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2142 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2143 for (c = 0; c < dof; ++c) { 2144 const PetscInt point = mesh->supports[off+c]; 2145 2146 for (m = 0; m < joinSize; ++m) { 2147 if (point == join[i][m]) { 2148 join[1-i][newJoinSize++] = point; 2149 break; 2150 } 2151 } 2152 } 2153 joinSize = newJoinSize; 2154 i = 1-i; 2155 } 2156 *numCoveredPoints = joinSize; 2157 *coveredPoints = join[i]; 2158 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2159 PetscFunctionReturn(0); 2160 } 2161 2162 #undef __FUNCT__ 2163 #define __FUNCT__ "DMPlexRestoreJoin" 2164 /*@C 2165 DMPlexRestoreJoin - Restore an array for the join of the set of points 2166 2167 Not Collective 2168 2169 Input Parameters: 2170 + dm - The DMPlex object 2171 . numPoints - The number of input points for the join 2172 - points - The input points 2173 2174 Output Parameters: 2175 + numCoveredPoints - The number of points in the join 2176 - coveredPoints - The points in the join 2177 2178 Level: intermediate 2179 2180 .keywords: mesh 2181 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2182 @*/ 2183 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2184 { 2185 PetscErrorCode ierr; 2186 2187 PetscFunctionBegin; 2188 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2189 PetscValidPointer(coveredPoints, 4); 2190 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2191 PetscFunctionReturn(0); 2192 } 2193 2194 #undef __FUNCT__ 2195 #define __FUNCT__ "DMPlexGetFullJoin" 2196 /*@C 2197 DMPlexGetFullJoin - Get an array for the join of the set of points 2198 2199 Not Collective 2200 2201 Input Parameters: 2202 + dm - The DMPlex object 2203 . numPoints - The number of input points for the join 2204 - points - The input points 2205 2206 Output Parameters: 2207 + numCoveredPoints - The number of points in the join 2208 - coveredPoints - The points in the join 2209 2210 Level: intermediate 2211 2212 .keywords: mesh 2213 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2214 @*/ 2215 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2216 { 2217 DM_Plex *mesh = (DM_Plex*) dm->data; 2218 PetscInt *offsets, **closures; 2219 PetscInt *join[2]; 2220 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2221 PetscInt p, d, c, m; 2222 PetscErrorCode ierr; 2223 2224 PetscFunctionBegin; 2225 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2226 PetscValidPointer(points, 2); 2227 PetscValidPointer(numCoveredPoints, 3); 2228 PetscValidPointer(coveredPoints, 4); 2229 2230 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2231 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2232 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2233 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2234 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2235 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2236 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2237 2238 for (p = 0; p < numPoints; ++p) { 2239 PetscInt closureSize; 2240 2241 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2242 2243 offsets[p*(depth+2)+0] = 0; 2244 for (d = 0; d < depth+1; ++d) { 2245 PetscInt pStart, pEnd, i; 2246 2247 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2248 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2249 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2250 offsets[p*(depth+2)+d+1] = i; 2251 break; 2252 } 2253 } 2254 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2255 } 2256 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2257 } 2258 for (d = 0; d < depth+1; ++d) { 2259 PetscInt dof; 2260 2261 /* Copy in support of first point */ 2262 dof = offsets[d+1] - offsets[d]; 2263 for (joinSize = 0; joinSize < dof; ++joinSize) { 2264 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2265 } 2266 /* Check each successive cone */ 2267 for (p = 1; p < numPoints && joinSize; ++p) { 2268 PetscInt newJoinSize = 0; 2269 2270 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2271 for (c = 0; c < dof; ++c) { 2272 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2273 2274 for (m = 0; m < joinSize; ++m) { 2275 if (point == join[i][m]) { 2276 join[1-i][newJoinSize++] = point; 2277 break; 2278 } 2279 } 2280 } 2281 joinSize = newJoinSize; 2282 i = 1-i; 2283 } 2284 if (joinSize) break; 2285 } 2286 *numCoveredPoints = joinSize; 2287 *coveredPoints = join[i]; 2288 for (p = 0; p < numPoints; ++p) { 2289 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2290 } 2291 ierr = PetscFree(closures);CHKERRQ(ierr); 2292 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2293 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2294 PetscFunctionReturn(0); 2295 } 2296 2297 #undef __FUNCT__ 2298 #define __FUNCT__ "DMPlexGetMeet" 2299 /*@C 2300 DMPlexGetMeet - Get an array for the meet of the set of points 2301 2302 Not Collective 2303 2304 Input Parameters: 2305 + dm - The DMPlex object 2306 . numPoints - The number of input points for the meet 2307 - points - The input points 2308 2309 Output Parameters: 2310 + numCoveredPoints - The number of points in the meet 2311 - coveredPoints - The points in the meet 2312 2313 Level: intermediate 2314 2315 Note: Currently, this is restricted to a single level meet 2316 2317 .keywords: mesh 2318 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2319 @*/ 2320 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2321 { 2322 DM_Plex *mesh = (DM_Plex*) dm->data; 2323 PetscInt *meet[2]; 2324 PetscInt meetSize, i = 0; 2325 PetscInt dof, off, p, c, m; 2326 PetscErrorCode ierr; 2327 2328 PetscFunctionBegin; 2329 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2330 PetscValidPointer(points, 2); 2331 PetscValidPointer(numCoveringPoints, 3); 2332 PetscValidPointer(coveringPoints, 4); 2333 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2334 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2335 /* Copy in cone of first point */ 2336 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2337 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2338 for (meetSize = 0; meetSize < dof; ++meetSize) { 2339 meet[i][meetSize] = mesh->cones[off+meetSize]; 2340 } 2341 /* Check each successive cone */ 2342 for (p = 1; p < numPoints; ++p) { 2343 PetscInt newMeetSize = 0; 2344 2345 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2346 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2347 for (c = 0; c < dof; ++c) { 2348 const PetscInt point = mesh->cones[off+c]; 2349 2350 for (m = 0; m < meetSize; ++m) { 2351 if (point == meet[i][m]) { 2352 meet[1-i][newMeetSize++] = point; 2353 break; 2354 } 2355 } 2356 } 2357 meetSize = newMeetSize; 2358 i = 1-i; 2359 } 2360 *numCoveringPoints = meetSize; 2361 *coveringPoints = meet[i]; 2362 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2363 PetscFunctionReturn(0); 2364 } 2365 2366 #undef __FUNCT__ 2367 #define __FUNCT__ "DMPlexRestoreMeet" 2368 /*@C 2369 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2370 2371 Not Collective 2372 2373 Input Parameters: 2374 + dm - The DMPlex object 2375 . numPoints - The number of input points for the meet 2376 - points - The input points 2377 2378 Output Parameters: 2379 + numCoveredPoints - The number of points in the meet 2380 - coveredPoints - The points in the meet 2381 2382 Level: intermediate 2383 2384 .keywords: mesh 2385 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2386 @*/ 2387 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2388 { 2389 PetscErrorCode ierr; 2390 2391 PetscFunctionBegin; 2392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2393 PetscValidPointer(coveredPoints, 4); 2394 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2395 PetscFunctionReturn(0); 2396 } 2397 2398 #undef __FUNCT__ 2399 #define __FUNCT__ "DMPlexGetFullMeet" 2400 /*@C 2401 DMPlexGetFullMeet - Get an array for the meet of the set of points 2402 2403 Not Collective 2404 2405 Input Parameters: 2406 + dm - The DMPlex object 2407 . numPoints - The number of input points for the meet 2408 - points - The input points 2409 2410 Output Parameters: 2411 + numCoveredPoints - The number of points in the meet 2412 - coveredPoints - The points in the meet 2413 2414 Level: intermediate 2415 2416 .keywords: mesh 2417 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2418 @*/ 2419 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2420 { 2421 DM_Plex *mesh = (DM_Plex*) dm->data; 2422 PetscInt *offsets, **closures; 2423 PetscInt *meet[2]; 2424 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2425 PetscInt p, h, c, m; 2426 PetscErrorCode ierr; 2427 2428 PetscFunctionBegin; 2429 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2430 PetscValidPointer(points, 2); 2431 PetscValidPointer(numCoveredPoints, 3); 2432 PetscValidPointer(coveredPoints, 4); 2433 2434 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2435 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2436 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2437 maxSize = PetscPowInt(mesh->maxConeSize,height); 2438 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2439 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2440 2441 for (p = 0; p < numPoints; ++p) { 2442 PetscInt closureSize; 2443 2444 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2445 2446 offsets[p*(height+2)+0] = 0; 2447 for (h = 0; h < height+1; ++h) { 2448 PetscInt pStart, pEnd, i; 2449 2450 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2451 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2452 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2453 offsets[p*(height+2)+h+1] = i; 2454 break; 2455 } 2456 } 2457 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2458 } 2459 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2460 } 2461 for (h = 0; h < height+1; ++h) { 2462 PetscInt dof; 2463 2464 /* Copy in cone of first point */ 2465 dof = offsets[h+1] - offsets[h]; 2466 for (meetSize = 0; meetSize < dof; ++meetSize) { 2467 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2468 } 2469 /* Check each successive cone */ 2470 for (p = 1; p < numPoints && meetSize; ++p) { 2471 PetscInt newMeetSize = 0; 2472 2473 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2474 for (c = 0; c < dof; ++c) { 2475 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2476 2477 for (m = 0; m < meetSize; ++m) { 2478 if (point == meet[i][m]) { 2479 meet[1-i][newMeetSize++] = point; 2480 break; 2481 } 2482 } 2483 } 2484 meetSize = newMeetSize; 2485 i = 1-i; 2486 } 2487 if (meetSize) break; 2488 } 2489 *numCoveredPoints = meetSize; 2490 *coveredPoints = meet[i]; 2491 for (p = 0; p < numPoints; ++p) { 2492 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2493 } 2494 ierr = PetscFree(closures);CHKERRQ(ierr); 2495 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2496 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2497 PetscFunctionReturn(0); 2498 } 2499 2500 #undef __FUNCT__ 2501 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2502 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2503 { 2504 MPI_Comm comm = ((PetscObject) dm)->comm; 2505 PetscInt cellDim; 2506 PetscErrorCode ierr; 2507 2508 PetscFunctionBegin; 2509 PetscValidPointer(numFaceVertices,3); 2510 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2511 switch (cellDim) { 2512 case 0: 2513 *numFaceVertices = 0; 2514 break; 2515 case 1: 2516 *numFaceVertices = 1; 2517 break; 2518 case 2: 2519 switch (numCorners) { 2520 case 3: /* triangle */ 2521 *numFaceVertices = 2; /* Edge has 2 vertices */ 2522 break; 2523 case 4: /* quadrilateral */ 2524 *numFaceVertices = 2; /* Edge has 2 vertices */ 2525 break; 2526 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2527 *numFaceVertices = 3; /* Edge has 3 vertices */ 2528 break; 2529 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2530 *numFaceVertices = 3; /* Edge has 3 vertices */ 2531 break; 2532 default: 2533 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2534 } 2535 break; 2536 case 3: 2537 switch (numCorners) { 2538 case 4: /* tetradehdron */ 2539 *numFaceVertices = 3; /* Face has 3 vertices */ 2540 break; 2541 case 6: /* tet cohesive cells */ 2542 *numFaceVertices = 4; /* Face has 4 vertices */ 2543 break; 2544 case 8: /* hexahedron */ 2545 *numFaceVertices = 4; /* Face has 4 vertices */ 2546 break; 2547 case 9: /* tet cohesive Lagrange cells */ 2548 *numFaceVertices = 6; /* Face has 6 vertices */ 2549 break; 2550 case 10: /* quadratic tetrahedron */ 2551 *numFaceVertices = 6; /* Face has 6 vertices */ 2552 break; 2553 case 12: /* hex cohesive Lagrange cells */ 2554 *numFaceVertices = 6; /* Face has 6 vertices */ 2555 break; 2556 case 18: /* quadratic tet cohesive Lagrange cells */ 2557 *numFaceVertices = 6; /* Face has 6 vertices */ 2558 break; 2559 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2560 *numFaceVertices = 9; /* Face has 9 vertices */ 2561 break; 2562 default: 2563 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2564 } 2565 break; 2566 default: 2567 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2568 } 2569 PetscFunctionReturn(0); 2570 } 2571 2572 #undef __FUNCT__ 2573 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2574 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2575 { 2576 const PetscInt maxFaceCases = 30; 2577 PetscInt numFaceCases = 0; 2578 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2579 PetscInt *off, *adj; 2580 PetscInt *neighborCells, *tmpClosure; 2581 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2582 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2583 PetscErrorCode ierr; 2584 2585 PetscFunctionBegin; 2586 /* For parallel partitioning, I think you have to communicate supports */ 2587 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2588 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2589 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2590 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2591 if (cEnd - cStart == 0) { 2592 if (numVertices) *numVertices = 0; 2593 if (offsets) *offsets = PETSC_NULL; 2594 if (adjacency) *adjacency = PETSC_NULL; 2595 PetscFunctionReturn(0); 2596 } 2597 numCells = cEnd - cStart; 2598 /* Setup face recognition */ 2599 if (depth == 1) { 2600 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 */ 2601 2602 for (c = cStart; c < cEnd; ++c) { 2603 PetscInt corners; 2604 2605 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2606 if (!cornersSeen[corners]) { 2607 PetscInt nFV; 2608 2609 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2610 cornersSeen[corners] = 1; 2611 2612 ierr = DMPlexGetNumFaceVertices_Internal(dm, corners, &nFV);CHKERRQ(ierr); 2613 2614 numFaceVertices[numFaceCases++] = nFV; 2615 } 2616 } 2617 } 2618 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2619 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2620 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2621 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2622 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2623 /* Count neighboring cells */ 2624 for (cell = cStart; cell < cEnd; ++cell) { 2625 PetscInt numNeighbors = maxNeighbors, n; 2626 2627 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2628 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2629 for (n = 0; n < numNeighbors; ++n) { 2630 PetscInt cellPair[2]; 2631 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2632 PetscInt meetSize = 0; 2633 const PetscInt *meet = PETSC_NULL; 2634 2635 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2636 if (cellPair[0] == cellPair[1]) continue; 2637 if (!found) { 2638 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2639 if (meetSize) { 2640 PetscInt f; 2641 2642 for (f = 0; f < numFaceCases; ++f) { 2643 if (numFaceVertices[f] == meetSize) { 2644 found = PETSC_TRUE; 2645 break; 2646 } 2647 } 2648 } 2649 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2650 } 2651 if (found) ++off[cell-cStart+1]; 2652 } 2653 } 2654 /* Prefix sum */ 2655 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2656 2657 if (adjacency) { 2658 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2659 /* Get neighboring cells */ 2660 for (cell = cStart; cell < cEnd; ++cell) { 2661 PetscInt numNeighbors = maxNeighbors, n; 2662 PetscInt cellOffset = 0; 2663 2664 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2665 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2666 for (n = 0; n < numNeighbors; ++n) { 2667 PetscInt cellPair[2]; 2668 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2669 PetscInt meetSize = 0; 2670 const PetscInt *meet = PETSC_NULL; 2671 2672 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2673 if (cellPair[0] == cellPair[1]) continue; 2674 if (!found) { 2675 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2676 if (meetSize) { 2677 PetscInt f; 2678 2679 for (f = 0; f < numFaceCases; ++f) { 2680 if (numFaceVertices[f] == meetSize) { 2681 found = PETSC_TRUE; 2682 break; 2683 } 2684 } 2685 } 2686 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2687 } 2688 if (found) { 2689 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2690 ++cellOffset; 2691 } 2692 } 2693 } 2694 } 2695 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2696 if (numVertices) *numVertices = numCells; 2697 if (offsets) *offsets = off; 2698 if (adjacency) *adjacency = adj; 2699 PetscFunctionReturn(0); 2700 } 2701 2702 #if defined(PETSC_HAVE_CHACO) 2703 #if defined(PETSC_HAVE_UNISTD_H) 2704 #include <unistd.h> 2705 #endif 2706 /* Chaco does not have an include file */ 2707 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2708 float *ewgts, float *x, float *y, float *z, char *outassignname, 2709 char *outfilename, short *assignment, int architecture, int ndims_tot, 2710 int mesh_dims[3], double *goal, int global_method, int local_method, 2711 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2712 2713 extern int FREE_GRAPH; 2714 2715 #undef __FUNCT__ 2716 #define __FUNCT__ "DMPlexPartition_Chaco" 2717 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2718 { 2719 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2720 MPI_Comm comm = ((PetscObject) dm)->comm; 2721 int nvtxs = numVertices; /* number of vertices in full graph */ 2722 int *vwgts = NULL; /* weights for all vertices */ 2723 float *ewgts = NULL; /* weights for all edges */ 2724 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2725 char *outassignname = NULL; /* name of assignment output file */ 2726 char *outfilename = NULL; /* output file name */ 2727 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2728 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2729 int mesh_dims[3]; /* dimensions of mesh of processors */ 2730 double *goal = NULL; /* desired set sizes for each set */ 2731 int global_method = 1; /* global partitioning algorithm */ 2732 int local_method = 1; /* local partitioning algorithm */ 2733 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2734 int vmax = 200; /* how many vertices to coarsen down to? */ 2735 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2736 double eigtol = 0.001; /* tolerance on eigenvectors */ 2737 long seed = 123636512; /* for random graph mutations */ 2738 short int *assignment; /* Output partition */ 2739 int fd_stdout, fd_pipe[2]; 2740 PetscInt *points; 2741 PetscMPIInt commSize; 2742 int i, v, p; 2743 PetscErrorCode ierr; 2744 2745 PetscFunctionBegin; 2746 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2747 if (!numVertices) { 2748 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2749 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2750 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2751 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2752 PetscFunctionReturn(0); 2753 } 2754 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2755 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2756 2757 if (global_method == INERTIAL_METHOD) { 2758 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2759 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2760 } 2761 mesh_dims[0] = commSize; 2762 mesh_dims[1] = 1; 2763 mesh_dims[2] = 1; 2764 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2765 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2766 /* TODO: check error codes for UNIX calls */ 2767 #if defined(PETSC_HAVE_UNISTD_H) 2768 { 2769 int piperet; 2770 piperet = pipe(fd_pipe); 2771 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2772 fd_stdout = dup(1); 2773 close(1); 2774 dup2(fd_pipe[1], 1); 2775 } 2776 #endif 2777 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2778 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2779 vmax, ndims, eigtol, seed); 2780 #if defined(PETSC_HAVE_UNISTD_H) 2781 { 2782 char msgLog[10000]; 2783 int count; 2784 2785 fflush(stdout); 2786 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2787 if (count < 0) count = 0; 2788 msgLog[count] = 0; 2789 close(1); 2790 dup2(fd_stdout, 1); 2791 close(fd_stdout); 2792 close(fd_pipe[0]); 2793 close(fd_pipe[1]); 2794 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2795 } 2796 #endif 2797 /* Convert to PetscSection+IS */ 2798 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2799 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2800 for (v = 0; v < nvtxs; ++v) { 2801 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2802 } 2803 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2804 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2805 for (p = 0, i = 0; p < commSize; ++p) { 2806 for (v = 0; v < nvtxs; ++v) { 2807 if (assignment[v] == p) points[i++] = v; 2808 } 2809 } 2810 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2811 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2812 if (global_method == INERTIAL_METHOD) { 2813 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2814 } 2815 ierr = PetscFree(assignment);CHKERRQ(ierr); 2816 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2817 PetscFunctionReturn(0); 2818 } 2819 #endif 2820 2821 #if defined(PETSC_HAVE_PARMETIS) 2822 #undef __FUNCT__ 2823 #define __FUNCT__ "DMPlexPartition_ParMetis" 2824 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2825 { 2826 PetscFunctionBegin; 2827 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2828 PetscFunctionReturn(0); 2829 } 2830 #endif 2831 2832 #undef __FUNCT__ 2833 #define __FUNCT__ "DMPlexEnlargePartition" 2834 /* Expand the partition by BFS on the adjacency graph */ 2835 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2836 { 2837 PetscHashI h; 2838 const PetscInt *points; 2839 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2840 PetscInt pStart, pEnd, part, q; 2841 PetscErrorCode ierr; 2842 2843 PetscFunctionBegin; 2844 PetscHashICreate(h); 2845 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2846 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2847 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2848 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2849 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2850 for (part = pStart; part < pEnd; ++part) { 2851 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2852 2853 PetscHashIClear(h); 2854 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2855 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2856 /* Add all existing points to h */ 2857 for (p = 0; p < numPoints; ++p) { 2858 const PetscInt point = points[off+p]; 2859 PetscHashIAdd(h, point, 1); 2860 } 2861 PetscHashISize(h, nP); 2862 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2863 /* Add all points in next BFS level */ 2864 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2865 for (p = 0; p < numPoints; ++p) { 2866 const PetscInt point = points[off+p]; 2867 PetscInt s = start[point], e = start[point+1], a; 2868 2869 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2870 } 2871 PetscHashISize(h, numNewPoints); 2872 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2873 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2874 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2875 totPoints += numNewPoints; 2876 } 2877 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2878 PetscHashIDestroy(h); 2879 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2880 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2881 for (part = pStart, q = 0; part < pEnd; ++part) { 2882 PetscInt numPoints, p; 2883 2884 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2885 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2886 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2887 } 2888 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2889 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2890 PetscFunctionReturn(0); 2891 } 2892 2893 #undef __FUNCT__ 2894 #define __FUNCT__ "DMPlexCreatePartition" 2895 /* 2896 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2897 2898 Collective on DM 2899 2900 Input Parameters: 2901 + dm - The DM 2902 . height - The height for points in the partition 2903 - enlarge - Expand each partition with neighbors 2904 2905 Output Parameters: 2906 + partSection - The PetscSection giving the division of points by partition 2907 . partition - The list of points by partition 2908 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2909 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2910 2911 Level: developer 2912 2913 .seealso DMPlexDistribute() 2914 */ 2915 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2916 { 2917 PetscMPIInt size; 2918 PetscErrorCode ierr; 2919 2920 PetscFunctionBegin; 2921 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2922 2923 *origPartSection = PETSC_NULL; 2924 *origPartition = PETSC_NULL; 2925 if (size == 1) { 2926 PetscInt *points; 2927 PetscInt cStart, cEnd, c; 2928 2929 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2930 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2931 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2932 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2933 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2934 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2935 for (c = cStart; c < cEnd; ++c) points[c] = c; 2936 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2937 PetscFunctionReturn(0); 2938 } 2939 if (height == 0) { 2940 PetscInt numVertices; 2941 PetscInt *start = PETSC_NULL; 2942 PetscInt *adjacency = PETSC_NULL; 2943 2944 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2945 if (1) { 2946 #if defined(PETSC_HAVE_CHACO) 2947 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2948 #endif 2949 } else { 2950 #if defined(PETSC_HAVE_PARMETIS) 2951 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2952 #endif 2953 } 2954 if (enlarge) { 2955 *origPartSection = *partSection; 2956 *origPartition = *partition; 2957 2958 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2959 } 2960 ierr = PetscFree(start);CHKERRQ(ierr); 2961 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2962 # if 0 2963 } else if (height == 1) { 2964 /* Build the dual graph for faces and partition the hypergraph */ 2965 PetscInt numEdges; 2966 2967 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2968 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2969 destroyCSR(numEdges, start, adjacency); 2970 #endif 2971 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2972 PetscFunctionReturn(0); 2973 } 2974 2975 #undef __FUNCT__ 2976 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2977 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2978 { 2979 /* const PetscInt height = 0; */ 2980 const PetscInt *partArray; 2981 PetscInt *allPoints, *partPoints = PETSC_NULL; 2982 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2983 PetscErrorCode ierr; 2984 2985 PetscFunctionBegin; 2986 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2987 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2988 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2989 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2990 for (rank = rStart; rank < rEnd; ++rank) { 2991 PetscInt partSize = 0; 2992 PetscInt numPoints, offset, p; 2993 2994 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2995 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2996 for (p = 0; p < numPoints; ++p) { 2997 PetscInt point = partArray[offset+p], closureSize, c; 2998 PetscInt *closure = PETSC_NULL; 2999 3000 /* TODO Include support for height > 0 case */ 3001 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3002 /* Merge into existing points */ 3003 if (partSize+closureSize > maxPartSize) { 3004 PetscInt *tmpPoints; 3005 3006 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 3007 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 3008 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3009 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3010 3011 partPoints = tmpPoints; 3012 } 3013 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3014 partSize += closureSize; 3015 3016 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3017 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3018 } 3019 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3020 } 3021 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3022 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3023 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3024 3025 for (rank = rStart; rank < rEnd; ++rank) { 3026 PetscInt partSize = 0, newOffset; 3027 PetscInt numPoints, offset, p; 3028 3029 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3030 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3031 for (p = 0; p < numPoints; ++p) { 3032 PetscInt point = partArray[offset+p], closureSize, c; 3033 PetscInt *closure = PETSC_NULL; 3034 3035 /* TODO Include support for height > 0 case */ 3036 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3037 /* Merge into existing points */ 3038 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3039 partSize += closureSize; 3040 3041 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3042 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3043 } 3044 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3045 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3046 } 3047 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3048 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3049 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3050 PetscFunctionReturn(0); 3051 } 3052 3053 #undef __FUNCT__ 3054 #define __FUNCT__ "DMPlexDistributeField" 3055 /* 3056 Input Parameters: 3057 . originalSection 3058 , originalVec 3059 3060 Output Parameters: 3061 . newSection 3062 . newVec 3063 */ 3064 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3065 { 3066 PetscSF fieldSF; 3067 PetscInt *remoteOffsets, fieldSize; 3068 PetscScalar *originalValues, *newValues; 3069 PetscErrorCode ierr; 3070 3071 PetscFunctionBegin; 3072 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3073 3074 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3075 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3076 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3077 3078 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3079 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3080 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3081 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3082 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3083 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3084 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3085 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3086 PetscFunctionReturn(0); 3087 } 3088 3089 #undef __FUNCT__ 3090 #define __FUNCT__ "DMPlexDistribute" 3091 /*@C 3092 DMPlexDistribute - Distributes the mesh and any associated sections. 3093 3094 Not Collective 3095 3096 Input Parameter: 3097 + dm - The original DMPlex object 3098 . partitioner - The partitioning package, or NULL for the default 3099 - overlap - The overlap of partitions, 0 is the default 3100 3101 Output Parameter: 3102 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3103 3104 Note: If the mesh was not distributed, the return value is PETSC_NULL 3105 3106 Level: intermediate 3107 3108 .keywords: mesh, elements 3109 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3110 @*/ 3111 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3112 { 3113 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3114 MPI_Comm comm = ((PetscObject) dm)->comm; 3115 const PetscInt height = 0; 3116 PetscInt dim, numRemoteRanks; 3117 IS origCellPart, cellPart, part; 3118 PetscSection origCellPartSection, cellPartSection, partSection; 3119 PetscSFNode *remoteRanks; 3120 PetscSF partSF, pointSF, coneSF; 3121 ISLocalToGlobalMapping renumbering; 3122 PetscSection originalConeSection, newConeSection; 3123 PetscInt *remoteOffsets; 3124 PetscInt *cones, *newCones, newConesSize; 3125 PetscBool flg; 3126 PetscMPIInt rank, numProcs, p; 3127 PetscErrorCode ierr; 3128 3129 PetscFunctionBegin; 3130 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3131 PetscValidPointer(dmParallel,4); 3132 3133 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3134 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3135 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3136 3137 *dmParallel = PETSC_NULL; 3138 if (numProcs == 1) PetscFunctionReturn(0); 3139 3140 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3141 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3142 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3143 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3144 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3145 if (!rank) numRemoteRanks = numProcs; 3146 else numRemoteRanks = 0; 3147 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3148 for (p = 0; p < numRemoteRanks; ++p) { 3149 remoteRanks[p].rank = p; 3150 remoteRanks[p].index = 0; 3151 } 3152 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3153 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3154 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3155 if (flg) { 3156 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3157 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3158 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3159 if (origCellPart) { 3160 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3161 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3162 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3163 } 3164 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3165 } 3166 /* Close the partition over the mesh */ 3167 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3168 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3169 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3170 /* Create new mesh */ 3171 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3172 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3173 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3174 pmesh = (DM_Plex*) (*dmParallel)->data; 3175 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3176 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3177 if (flg) { 3178 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3179 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3180 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3181 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3182 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3183 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3184 } 3185 /* Distribute cone section */ 3186 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3187 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3188 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3189 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3190 { 3191 PetscInt pStart, pEnd, p; 3192 3193 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3194 for (p = pStart; p < pEnd; ++p) { 3195 PetscInt coneSize; 3196 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3197 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3198 } 3199 } 3200 /* Communicate and renumber cones */ 3201 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3202 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3203 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3204 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3205 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3206 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3207 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3208 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3209 if (flg) { 3210 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3211 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3212 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3213 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3214 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3215 } 3216 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3217 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3218 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3219 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3220 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3221 /* Create supports and stratify sieve */ 3222 { 3223 PetscInt pStart, pEnd; 3224 3225 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3226 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3227 } 3228 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3229 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3230 /* Distribute Coordinates */ 3231 { 3232 PetscSection originalCoordSection, newCoordSection; 3233 Vec originalCoordinates, newCoordinates; 3234 const char *name; 3235 3236 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3237 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3238 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3239 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3240 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3241 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3242 3243 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3244 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3245 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3246 } 3247 /* Distribute labels */ 3248 { 3249 DMLabel next = mesh->labels, newNext = pmesh->labels; 3250 PetscInt numLabels = 0, l; 3251 3252 /* Bcast number of labels */ 3253 while (next) { 3254 ++numLabels; next = next->next; 3255 } 3256 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3257 next = mesh->labels; 3258 for (l = 0; l < numLabels; ++l) { 3259 DMLabel newLabel; 3260 const PetscInt *partArray; 3261 char *name; 3262 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3263 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3264 PetscInt nameSize, s, p; 3265 PetscBool isdepth; 3266 size_t len = 0; 3267 3268 /* Bcast name (could filter for no points) */ 3269 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3270 nameSize = len; 3271 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3272 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3273 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3274 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3275 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3276 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3277 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3278 newLabel->name = name; 3279 /* Bcast numStrata (could filter for no points in stratum) */ 3280 if (!rank) newLabel->numStrata = next->numStrata; 3281 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3282 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3283 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3284 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3285 /* Bcast stratumValues (could filter for no points in stratum) */ 3286 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3287 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3288 /* Find size on each process and Scatter */ 3289 if (!rank) { 3290 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3291 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3292 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3293 for (s = 0; s < next->numStrata; ++s) { 3294 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3295 const PetscInt point = next->points[p]; 3296 PetscInt proc; 3297 3298 for (proc = 0; proc < numProcs; ++proc) { 3299 PetscInt dof, off, pPart; 3300 3301 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3302 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3303 for (pPart = off; pPart < off+dof; ++pPart) { 3304 if (partArray[pPart] == point) { 3305 ++stratumSizes[proc*next->numStrata+s]; 3306 break; 3307 } 3308 } 3309 } 3310 } 3311 } 3312 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3313 } 3314 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3315 /* Calculate stratumOffsets */ 3316 newLabel->stratumOffsets[0] = 0; 3317 for (s = 0; s < newLabel->numStrata; ++s) { 3318 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3319 } 3320 /* Pack points and Scatter */ 3321 if (!rank) { 3322 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3323 displs[0] = 0; 3324 for (p = 0; p < numProcs; ++p) { 3325 sendcnts[p] = 0; 3326 for (s = 0; s < next->numStrata; ++s) { 3327 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3328 } 3329 offsets[p] = displs[p]; 3330 displs[p+1] = displs[p] + sendcnts[p]; 3331 } 3332 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3333 for (s = 0; s < next->numStrata; ++s) { 3334 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3335 const PetscInt point = next->points[p]; 3336 PetscInt proc; 3337 3338 for (proc = 0; proc < numProcs; ++proc) { 3339 PetscInt dof, off, pPart; 3340 3341 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3342 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3343 for (pPart = off; pPart < off+dof; ++pPart) { 3344 if (partArray[pPart] == point) { 3345 points[offsets[proc]++] = point; 3346 break; 3347 } 3348 } 3349 } 3350 } 3351 } 3352 } 3353 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3354 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3355 ierr = PetscFree(points);CHKERRQ(ierr); 3356 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3357 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3358 /* Renumber points */ 3359 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3360 /* Sort points */ 3361 for (s = 0; s < newLabel->numStrata; ++s) { 3362 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3363 } 3364 /* Insert into list */ 3365 if (newNext) newNext->next = newLabel; 3366 else pmesh->labels = newLabel; 3367 newNext = newLabel; 3368 if (!rank) next = next->next; 3369 } 3370 } 3371 /* Cleanup Partition */ 3372 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3373 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3374 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3375 ierr = ISDestroy(&part);CHKERRQ(ierr); 3376 /* Create point SF for parallel mesh */ 3377 { 3378 const PetscInt *leaves; 3379 PetscSFNode *remotePoints, *rowners, *lowners; 3380 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3381 PetscInt pStart, pEnd; 3382 3383 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3384 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3385 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3386 for (p=0; p<numRoots; p++) { 3387 rowners[p].rank = -1; 3388 rowners[p].index = -1; 3389 } 3390 if (origCellPart) { 3391 /* Make sure cells in the original partition are not assigned to other procs */ 3392 const PetscInt *origCells; 3393 3394 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3395 for (p = 0; p < numProcs; ++p) { 3396 PetscInt dof, off, d; 3397 3398 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3399 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3400 for (d = off; d < off+dof; ++d) { 3401 rowners[origCells[d]].rank = p; 3402 } 3403 } 3404 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3405 } 3406 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3407 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3408 3409 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3410 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3411 for (p = 0; p < numLeaves; ++p) { 3412 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3413 lowners[p].rank = rank; 3414 lowners[p].index = leaves ? leaves[p] : p; 3415 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3416 lowners[p].rank = -2; 3417 lowners[p].index = -2; 3418 } 3419 } 3420 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3421 rowners[p].rank = -3; 3422 rowners[p].index = -3; 3423 } 3424 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3425 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3426 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3427 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3428 for (p = 0; p < numLeaves; ++p) { 3429 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3430 if (lowners[p].rank != rank) ++numGhostPoints; 3431 } 3432 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3433 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3434 for (p = 0, gp = 0; p < numLeaves; ++p) { 3435 if (lowners[p].rank != rank) { 3436 ghostPoints[gp] = leaves ? leaves[p] : p; 3437 remotePoints[gp].rank = lowners[p].rank; 3438 remotePoints[gp].index = lowners[p].index; 3439 ++gp; 3440 } 3441 } 3442 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3443 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3444 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3445 } 3446 /* Cleanup */ 3447 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3448 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3449 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3450 PetscFunctionReturn(0); 3451 } 3452 3453 #undef __FUNCT__ 3454 #define __FUNCT__ "DMPlexRenumber_Private" 3455 /* 3456 Reasons to renumber: 3457 3458 1) Permute points, e.g. bandwidth reduction (Renumber) 3459 3460 a) Must not mix strata 3461 3462 2) Shift numbers for point insertion (Shift) 3463 3464 a) Want operation brken into parts so that insertion can be interleaved 3465 3466 renumbering - An IS which provides the new numbering 3467 */ 3468 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3469 { 3470 PetscFunctionBegin; 3471 PetscFunctionReturn(0); 3472 } 3473 3474 #undef __FUNCT__ 3475 #define __FUNCT__ "DMPlexShiftPoint_Private" 3476 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3477 { 3478 if (depth < 0) return p; 3479 /* Cells */ if (p < depthEnd[depth]) return p; 3480 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3481 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3482 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3483 } 3484 3485 #undef __FUNCT__ 3486 #define __FUNCT__ "DMPlexShiftSizes_Private" 3487 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3488 { 3489 PetscInt *depthEnd; 3490 PetscInt depth = 0, d, pStart, pEnd, p; 3491 PetscErrorCode ierr; 3492 3493 PetscFunctionBegin; 3494 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3495 if (depth < 0) PetscFunctionReturn(0); 3496 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3497 /* Step 1: Expand chart */ 3498 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3499 for (d = 0; d <= depth; ++d) { 3500 pEnd += depthShift[d]; 3501 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3502 } 3503 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3504 /* Step 2: Set cone and support sizes */ 3505 for (d = 0; d <= depth; ++d) { 3506 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3507 for (p = pStart; p < pEnd; ++p) { 3508 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3509 PetscInt size; 3510 3511 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3512 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3513 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3514 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3515 } 3516 } 3517 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3518 PetscFunctionReturn(0); 3519 } 3520 3521 #undef __FUNCT__ 3522 #define __FUNCT__ "DMPlexShiftPoints_Private" 3523 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3524 { 3525 PetscInt *depthEnd, *newpoints; 3526 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3527 PetscErrorCode ierr; 3528 3529 PetscFunctionBegin; 3530 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3531 if (depth < 0) PetscFunctionReturn(0); 3532 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3533 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3534 for (d = 0; d <= depth; ++d) { 3535 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3536 } 3537 /* Step 5: Set cones and supports */ 3538 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3539 for (p = pStart; p < pEnd; ++p) { 3540 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3541 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3542 3543 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3544 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3545 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3546 for (i = 0; i < size; ++i) { 3547 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3548 } 3549 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3550 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3551 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3552 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3553 for (i = 0; i < size; ++i) { 3554 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3555 } 3556 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3557 } 3558 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3559 PetscFunctionReturn(0); 3560 } 3561 3562 #undef __FUNCT__ 3563 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3564 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3565 { 3566 PetscSection coordSection, newCoordSection; 3567 Vec coordinates, newCoordinates; 3568 PetscScalar *coords, *newCoords; 3569 PetscInt *depthEnd, coordSize; 3570 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3571 PetscErrorCode ierr; 3572 3573 PetscFunctionBegin; 3574 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3575 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3576 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3577 for (d = 0; d <= depth; ++d) { 3578 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3579 } 3580 /* Step 8: Convert coordinates */ 3581 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3582 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3583 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3584 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3585 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3586 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3587 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3588 for (v = vStartNew; v < vEndNew; ++v) { 3589 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3590 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3591 } 3592 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3593 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3594 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3595 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3596 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3597 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3598 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3599 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3600 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3601 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3602 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3603 for (v = vStart; v < vEnd; ++v) { 3604 PetscInt dof, off, noff, d; 3605 3606 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3607 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3608 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3609 for (d = 0; d < dof; ++d) { 3610 newCoords[noff+d] = coords[off+d]; 3611 } 3612 } 3613 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3614 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3615 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3616 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3617 PetscFunctionReturn(0); 3618 } 3619 3620 #undef __FUNCT__ 3621 #define __FUNCT__ "DMPlexShiftSF_Private" 3622 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3623 { 3624 PetscInt *depthEnd; 3625 PetscInt depth = 0, d; 3626 PetscSF sfPoint, sfPointNew; 3627 const PetscSFNode *remotePoints; 3628 PetscSFNode *gremotePoints; 3629 const PetscInt *localPoints; 3630 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3631 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3632 PetscMPIInt numProcs; 3633 PetscErrorCode ierr; 3634 3635 PetscFunctionBegin; 3636 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3637 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3638 for (d = 0; d <= depth; ++d) { 3639 totShift += depthShift[d]; 3640 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3641 } 3642 /* Step 9: Convert pointSF */ 3643 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3644 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3645 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3646 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3647 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3648 if (numRoots >= 0) { 3649 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3650 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3651 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3652 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3653 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3654 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3655 for (l = 0; l < numLeaves; ++l) { 3656 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3657 gremotePoints[l].rank = remotePoints[l].rank; 3658 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3659 } 3660 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3661 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3662 } 3663 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3664 PetscFunctionReturn(0); 3665 } 3666 3667 #undef __FUNCT__ 3668 #define __FUNCT__ "DMPlexShiftLabels_Private" 3669 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3670 { 3671 PetscSF sfPoint; 3672 DMLabel vtkLabel, ghostLabel; 3673 PetscInt *depthEnd; 3674 const PetscSFNode *leafRemote; 3675 const PetscInt *leafLocal; 3676 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3677 PetscMPIInt rank; 3678 PetscErrorCode ierr; 3679 3680 PetscFunctionBegin; 3681 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3682 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3683 for (d = 0; d <= depth; ++d) { 3684 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3685 } 3686 /* Step 10: Convert labels */ 3687 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3688 for (l = 0; l < numLabels; ++l) { 3689 DMLabel label, newlabel; 3690 const char *lname; 3691 PetscBool isDepth; 3692 IS valueIS; 3693 const PetscInt *values; 3694 PetscInt numValues, val; 3695 3696 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3697 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3698 if (isDepth) continue; 3699 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3700 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3701 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3702 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3703 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3704 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3705 for (val = 0; val < numValues; ++val) { 3706 IS pointIS; 3707 const PetscInt *points; 3708 PetscInt numPoints, p; 3709 3710 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3711 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3712 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3713 for (p = 0; p < numPoints; ++p) { 3714 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3715 3716 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3717 } 3718 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3719 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3720 } 3721 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3722 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3723 } 3724 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3725 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3726 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3727 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3728 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3729 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3730 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3731 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3732 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3733 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3734 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3735 for (; c < leafLocal[l] && c < cEnd; ++c) { 3736 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3737 } 3738 if (leafLocal[l] >= cEnd) break; 3739 if (leafRemote[l].rank == rank) { 3740 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3741 } else { 3742 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3743 } 3744 } 3745 for (; c < cEnd; ++c) { 3746 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3747 } 3748 if (0) { 3749 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3750 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3751 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3752 } 3753 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3754 for (f = fStart; f < fEnd; ++f) { 3755 PetscInt numCells; 3756 3757 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3758 if (numCells < 2) { 3759 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3760 } else { 3761 const PetscInt *cells = PETSC_NULL; 3762 PetscInt vA, vB; 3763 3764 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3765 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3766 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3767 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3768 } 3769 } 3770 if (0) { 3771 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3772 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3773 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3774 } 3775 PetscFunctionReturn(0); 3776 } 3777 3778 #undef __FUNCT__ 3779 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3780 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3781 { 3782 DMLabel label; 3783 IS valueIS; 3784 const PetscInt *values; 3785 PetscInt *depthShift; 3786 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3787 PetscErrorCode ierr; 3788 3789 PetscFunctionBegin; 3790 /* Count ghost cells */ 3791 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3792 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3793 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3794 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3795 3796 *numGhostCells = 0; 3797 for (fs = 0; fs < numFS; ++fs) { 3798 PetscInt numBdFaces; 3799 3800 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3801 3802 *numGhostCells += numBdFaces; 3803 } 3804 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3805 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3806 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3807 if (depth >= 0) depthShift[depth] = *numGhostCells; 3808 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3809 /* Step 3: Set cone/support sizes for new points */ 3810 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3811 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3812 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3813 } 3814 for (fs = 0; fs < numFS; ++fs) { 3815 IS faceIS; 3816 const PetscInt *faces; 3817 PetscInt numFaces, f; 3818 3819 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3820 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3821 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3822 for (f = 0; f < numFaces; ++f) { 3823 PetscInt size; 3824 3825 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3826 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3827 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3828 } 3829 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3830 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3831 } 3832 /* Step 4: Setup ghosted DM */ 3833 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3834 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3835 /* Step 6: Set cones and supports for new points */ 3836 ghostCell = cEnd; 3837 for (fs = 0; fs < numFS; ++fs) { 3838 IS faceIS; 3839 const PetscInt *faces; 3840 PetscInt numFaces, f; 3841 3842 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3843 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3844 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3845 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3846 PetscInt newFace = faces[f] + *numGhostCells; 3847 3848 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3849 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3850 } 3851 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3852 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3853 } 3854 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3855 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3856 /* Step 7: Stratify */ 3857 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3858 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3859 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3860 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3861 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3862 PetscFunctionReturn(0); 3863 } 3864 3865 #undef __FUNCT__ 3866 #define __FUNCT__ "DMPlexConstructGhostCells" 3867 /*@C 3868 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3869 3870 Collective on dm 3871 3872 Input Parameters: 3873 + dm - The original DM 3874 - labelName - The label specifying the boundary faces (this could be auto-generated) 3875 3876 Output Parameters: 3877 + numGhostCells - The number of ghost cells added to the DM 3878 - dmGhosted - The new DM 3879 3880 Level: developer 3881 3882 .seealso: DMCreate() 3883 */ 3884 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3885 { 3886 DM gdm; 3887 PetscInt dim; 3888 PetscErrorCode ierr; 3889 3890 PetscFunctionBegin; 3891 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3892 PetscValidPointer(numGhostCells, 3); 3893 PetscValidPointer(dmGhosted, 4); 3894 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3895 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3896 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3897 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3898 switch (dim) { 3899 case 2: 3900 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3901 break; 3902 default: 3903 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3904 } 3905 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3906 *dmGhosted = gdm; 3907 PetscFunctionReturn(0); 3908 } 3909 3910 #undef __FUNCT__ 3911 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3912 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3913 { 3914 MPI_Comm comm = ((PetscObject) dm)->comm; 3915 IS valueIS, *pointIS; 3916 const PetscInt *values, **splitPoints; 3917 PetscSection coordSection; 3918 Vec coordinates; 3919 PetscScalar *coords; 3920 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3921 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3922 PetscErrorCode ierr; 3923 3924 PetscFunctionBegin; 3925 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3926 /* Count split points and add cohesive cells */ 3927 if (label) { 3928 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3929 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3930 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3931 } 3932 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3933 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3934 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3935 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3936 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3937 for (d = 0; d <= depth; ++d) { 3938 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3939 numSplitPoints[d] = 0; 3940 splitPoints[d] = PETSC_NULL; 3941 pointIS[d] = PETSC_NULL; 3942 } 3943 for (sp = 0; sp < numSP; ++sp) { 3944 const PetscInt dep = values[sp]; 3945 3946 if ((dep < 0) || (dep > depth)) continue; 3947 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3948 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3949 if (pointIS[dep]) { 3950 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3951 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3952 } 3953 } 3954 if (depth >= 0) { 3955 /* Calculate number of additional points */ 3956 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3957 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3958 /* Calculate hybrid bound for each dimension */ 3959 pMaxNew[0] += depthShift[depth]; 3960 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3961 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3962 3963 /* Calculate point offset for each dimension */ 3964 depthOffset[depth] = 0; 3965 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3966 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3967 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3968 } 3969 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3970 /* Step 3: Set cone/support sizes for new points */ 3971 for (dep = 0; dep <= depth; ++dep) { 3972 for (p = 0; p < numSplitPoints[dep]; ++p) { 3973 const PetscInt oldp = splitPoints[dep][p]; 3974 const PetscInt newp = depthOffset[dep] + oldp; 3975 const PetscInt splitp = pMaxNew[dep] + p; 3976 const PetscInt *support; 3977 PetscInt coneSize, supportSize, q, e; 3978 3979 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3980 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3981 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3982 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3983 if (dep == depth-1) { 3984 const PetscInt ccell = pMaxNew[depth] + p; 3985 /* Add cohesive cells, they are prisms */ 3986 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3987 } else if (dep == 0) { 3988 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3989 3990 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3991 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3992 for (e = 0, q = 0; e < supportSize; ++e) { 3993 PetscInt val; 3994 3995 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3996 if ((val == 1) || (val == (shift + 1))) ++q; 3997 } 3998 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3999 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4000 for (e = 0, q = 0; e < supportSize; ++e) { 4001 PetscInt val; 4002 4003 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4004 if ((val == 1) || (val == -(shift + 1))) ++q; 4005 } 4006 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 4007 /* Add cohesive edges */ 4008 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 4009 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4010 } else if (dep == dim-2) { 4011 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4012 /* Split old edge: Faces in positive side cells and old split faces */ 4013 for (e = 0, q = 0; e < supportSize; ++e) { 4014 PetscInt val; 4015 4016 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4017 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4018 } 4019 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4020 /* Split new edge: Faces in negative side cells and new split faces */ 4021 for (e = 0, q = 0; e < supportSize; ++e) { 4022 PetscInt val; 4023 4024 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4025 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4026 } 4027 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4028 } 4029 } 4030 } 4031 /* Step 4: Setup split DM */ 4032 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4033 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4034 /* Step 6: Set cones and supports for new points */ 4035 for (dep = 0; dep <= depth; ++dep) { 4036 for (p = 0; p < numSplitPoints[dep]; ++p) { 4037 const PetscInt oldp = splitPoints[dep][p]; 4038 const PetscInt newp = depthOffset[dep] + oldp; 4039 const PetscInt splitp = pMaxNew[dep] + p; 4040 const PetscInt *cone, *support, *ornt; 4041 PetscInt coneSize, supportSize, q, v, e, s; 4042 4043 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4044 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4045 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4046 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4047 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4048 if (dep == depth-1) { 4049 const PetscInt ccell = pMaxNew[depth] + p; 4050 const PetscInt *supportF; 4051 4052 /* Split face: copy in old face to new face to start */ 4053 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4054 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4055 /* Split old face: old vertices/edges in cone so no change */ 4056 /* Split new face: new vertices/edges in cone */ 4057 for (q = 0; q < coneSize; ++q) { 4058 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4059 4060 coneNew[2+q] = pMaxNew[dim-2] + v; 4061 } 4062 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4063 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4064 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4065 coneNew[0] = newp; 4066 coneNew[1] = splitp; 4067 for (q = 0; q < coneSize; ++q) { 4068 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4069 } 4070 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4071 4072 4073 for (s = 0; s < supportSize; ++s) { 4074 PetscInt val; 4075 4076 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4077 if (val < 0) { 4078 /* Split old face: Replace negative side cell with cohesive cell */ 4079 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4080 } else { 4081 /* Split new face: Replace positive side cell with cohesive cell */ 4082 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4083 } 4084 } 4085 } else if (dep == 0) { 4086 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4087 4088 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4089 for (e = 0, q = 0; e < supportSize; ++e) { 4090 PetscInt val; 4091 4092 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4093 if ((val == 1) || (val == (shift + 1))) { 4094 supportNew[q++] = depthOffset[1] + support[e]; 4095 } 4096 } 4097 supportNew[q] = cedge; 4098 4099 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4100 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4101 for (e = 0, q = 0; e < supportSize; ++e) { 4102 PetscInt val, edge; 4103 4104 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4105 if (val == 1) { 4106 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4107 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4108 supportNew[q++] = pMaxNew[1] + edge; 4109 } else if (val == -(shift + 1)) { 4110 supportNew[q++] = depthOffset[1] + support[e]; 4111 } 4112 } 4113 supportNew[q] = cedge; 4114 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4115 /* Cohesive edge: Old and new split vertex, punting on support */ 4116 coneNew[0] = newp; 4117 coneNew[1] = splitp; 4118 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4119 } else if (dep == dim-2) { 4120 /* Split old edge: old vertices in cone so no change */ 4121 /* Split new edge: new vertices in cone */ 4122 for (q = 0; q < coneSize; ++q) { 4123 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4124 4125 coneNew[q] = pMaxNew[dim-3] + v; 4126 } 4127 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4128 /* Split old edge: Faces in positive side cells and old split faces */ 4129 for (e = 0, q = 0; e < supportSize; ++e) { 4130 PetscInt val; 4131 4132 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4133 if ((val == dim-1) || (val == (shift + dim-1))) { 4134 supportNew[q++] = depthOffset[dim-1] + support[e]; 4135 } 4136 } 4137 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4138 /* Split new edge: Faces in negative side cells and new split faces */ 4139 for (e = 0, q = 0; e < supportSize; ++e) { 4140 PetscInt val, face; 4141 4142 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4143 if (val == dim-1) { 4144 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4145 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4146 supportNew[q++] = pMaxNew[dim-1] + face; 4147 } else if (val == -(shift + dim-1)) { 4148 supportNew[q++] = depthOffset[dim-1] + support[e]; 4149 } 4150 } 4151 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4152 } 4153 } 4154 } 4155 /* Step 6b: Replace split points in negative side cones */ 4156 for (sp = 0; sp < numSP; ++sp) { 4157 PetscInt dep = values[sp]; 4158 IS pIS; 4159 PetscInt numPoints; 4160 const PetscInt *points; 4161 4162 if (dep >= 0) continue; 4163 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4164 if (!pIS) continue; 4165 dep = -dep - shift; 4166 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4167 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4168 for (p = 0; p < numPoints; ++p) { 4169 const PetscInt oldp = points[p]; 4170 const PetscInt newp = depthOffset[dep] + oldp; 4171 const PetscInt *cone; 4172 PetscInt coneSize, c; 4173 PetscBool replaced = PETSC_FALSE; 4174 4175 /* Negative edge: replace split vertex */ 4176 /* Negative cell: replace split face */ 4177 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4178 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4179 for (c = 0; c < coneSize; ++c) { 4180 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4181 PetscInt csplitp, cp, val; 4182 4183 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4184 if (val == dep-1) { 4185 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4186 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4187 csplitp = pMaxNew[dep-1] + cp; 4188 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4189 replaced = PETSC_TRUE; 4190 } 4191 } 4192 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4193 } 4194 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4195 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4196 } 4197 /* Step 7: Stratify */ 4198 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4199 /* Step 8: Coordinates */ 4200 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4201 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4202 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4203 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4204 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4205 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4206 const PetscInt splitp = pMaxNew[0] + v; 4207 PetscInt dof, off, soff, d; 4208 4209 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4210 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4211 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4212 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4213 } 4214 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4215 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4216 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4217 /* Step 10: Labels */ 4218 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4219 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4220 for (dep = 0; dep <= depth; ++dep) { 4221 for (p = 0; p < numSplitPoints[dep]; ++p) { 4222 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4223 const PetscInt splitp = pMaxNew[dep] + p; 4224 PetscInt l; 4225 4226 for (l = 0; l < numLabels; ++l) { 4227 DMLabel mlabel; 4228 const char *lname; 4229 PetscInt val; 4230 4231 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4232 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4233 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4234 if (val >= 0) { 4235 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4236 if (dep == 0) { 4237 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4238 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4239 } 4240 } 4241 } 4242 } 4243 } 4244 for (sp = 0; sp < numSP; ++sp) { 4245 const PetscInt dep = values[sp]; 4246 4247 if ((dep < 0) || (dep > depth)) continue; 4248 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4249 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4250 } 4251 if (label) { 4252 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4253 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4254 } 4255 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4256 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4257 PetscFunctionReturn(0); 4258 } 4259 4260 #undef __FUNCT__ 4261 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4262 /*@C 4263 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4264 4265 Collective on dm 4266 4267 Input Parameters: 4268 + dm - The original DM 4269 - labelName - The label specifying the boundary faces (this could be auto-generated) 4270 4271 Output Parameters: 4272 - dmSplit - The new DM 4273 4274 Level: developer 4275 4276 .seealso: DMCreate() 4277 */ 4278 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4279 { 4280 DM sdm; 4281 PetscInt dim; 4282 PetscErrorCode ierr; 4283 4284 PetscFunctionBegin; 4285 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4286 PetscValidPointer(dmSplit, 4); 4287 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4288 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4289 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4290 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4291 switch (dim) { 4292 case 2: 4293 case 3: 4294 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4295 break; 4296 default: 4297 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4298 } 4299 *dmSplit = sdm; 4300 PetscFunctionReturn(0); 4301 } 4302 4303 #undef __FUNCT__ 4304 #define __FUNCT__ "DMLabelCohesiveComplete" 4305 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4306 { 4307 IS dimIS; 4308 const PetscInt *points; 4309 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4310 PetscErrorCode ierr; 4311 4312 PetscFunctionBegin; 4313 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4314 /* Cell orientation for face gives the side of the fault */ 4315 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4316 if (!dimIS) PetscFunctionReturn(0); 4317 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4318 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4319 for (p = 0; p < numPoints; ++p) { 4320 const PetscInt *support; 4321 PetscInt supportSize, s; 4322 4323 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4324 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4325 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4326 for (s = 0; s < supportSize; ++s) { 4327 const PetscInt *cone, *ornt; 4328 PetscInt coneSize, c; 4329 PetscBool pos = PETSC_TRUE; 4330 4331 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4332 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4333 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4334 for (c = 0; c < coneSize; ++c) { 4335 if (cone[c] == points[p]) { 4336 if (ornt[c] >= 0) { 4337 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4338 } else { 4339 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4340 pos = PETSC_FALSE; 4341 } 4342 break; 4343 } 4344 } 4345 if (c == coneSize) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]); 4346 /* Put faces touching the fault in the label */ 4347 for (c = 0; c < coneSize; ++c) { 4348 const PetscInt point = cone[c]; 4349 4350 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4351 if (val == -1) { 4352 PetscInt *closure = PETSC_NULL; 4353 PetscInt closureSize, cl; 4354 4355 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4356 for (cl = 0; cl < closureSize*2; cl += 2) { 4357 const PetscInt clp = closure[cl]; 4358 4359 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4360 if ((val >= 0) && (val < dim-1)) { 4361 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4362 break; 4363 } 4364 } 4365 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4366 } 4367 } 4368 } 4369 } 4370 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4371 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4372 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4373 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4374 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4375 if (!dimIS) PetscFunctionReturn(0); 4376 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4377 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4378 for (p = 0; p < numPoints; ++p) { 4379 PetscInt *star = PETSC_NULL; 4380 PetscInt starSize, s; 4381 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4382 4383 /* First mark cells connected to the fault */ 4384 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4385 while (again) { 4386 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4387 again = 0; 4388 for (s = 0; s < starSize*2; s += 2) { 4389 const PetscInt point = star[s]; 4390 const PetscInt *cone; 4391 PetscInt coneSize, c; 4392 4393 if ((point < cStart) || (point >= cEnd)) continue; 4394 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4395 if (val != -1) continue; 4396 again = 2; 4397 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4398 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4399 for (c = 0; c < coneSize; ++c) { 4400 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4401 if (val != -1) { 4402 if (abs(val) < shift) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 4403 if (val > 0) { 4404 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4405 } else { 4406 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4407 } 4408 again = 1; 4409 break; 4410 } 4411 } 4412 } 4413 } 4414 /* Classify the rest by cell membership */ 4415 for (s = 0; s < starSize*2; s += 2) { 4416 const PetscInt point = star[s]; 4417 4418 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4419 if (val == -1) { 4420 PetscInt *sstar = PETSC_NULL; 4421 PetscInt sstarSize, ss; 4422 PetscBool marked = PETSC_FALSE; 4423 4424 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4425 for (ss = 0; ss < sstarSize*2; ss += 2) { 4426 const PetscInt spoint = sstar[ss]; 4427 4428 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4429 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4430 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4431 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4432 if (val > 0) { 4433 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4434 } else { 4435 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4436 } 4437 marked = PETSC_TRUE; 4438 break; 4439 } 4440 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4441 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4442 } 4443 } 4444 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4445 } 4446 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4447 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4448 PetscFunctionReturn(0); 4449 } 4450 4451 #undef __FUNCT__ 4452 #define __FUNCT__ "DMPlexInterpolate_2D" 4453 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4454 { 4455 DM idm; 4456 DM_Plex *mesh; 4457 PetscHashIJ edgeTable; 4458 PetscInt *off; 4459 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4460 PetscInt numEdges, firstEdge, edge, e; 4461 PetscErrorCode ierr; 4462 4463 PetscFunctionBegin; 4464 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4465 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4466 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4467 numCells = cEnd - cStart; 4468 numVertices = vEnd - vStart; 4469 firstEdge = numCells + numVertices; 4470 numEdges = 0; 4471 /* Count edges using algorithm from CreateNeighborCSR */ 4472 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4473 if (off) { 4474 PetscInt numCorners = 0; 4475 4476 numEdges = off[numCells]/2; 4477 #if 0 4478 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4479 numEdges += 3*numCells - off[numCells]; 4480 #else 4481 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4482 for (c = cStart; c < cEnd; ++c) { 4483 PetscInt coneSize; 4484 4485 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4486 numCorners += coneSize; 4487 } 4488 numEdges += numCorners - off[numCells]; 4489 #endif 4490 } 4491 #if 0 4492 /* Check Euler characteristic V - E + F = 1 */ 4493 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4494 #endif 4495 /* Create interpolated mesh */ 4496 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4497 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4498 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4499 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4500 for (c = 0; c < numCells; ++c) { 4501 PetscInt numCorners; 4502 4503 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4504 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4505 } 4506 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4507 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4508 } 4509 ierr = DMSetUp(idm);CHKERRQ(ierr); 4510 /* Get edge cones from subsets of cell vertices */ 4511 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4512 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4513 4514 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4515 const PetscInt *cellFaces; 4516 PetscInt numCellFaces, faceSize, cf; 4517 4518 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4519 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4520 for (cf = 0; cf < numCellFaces; ++cf) { 4521 #if 1 4522 PetscHashIJKey key; 4523 4524 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4525 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4526 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4527 if (e < 0) { 4528 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4529 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4530 e = edge++; 4531 } 4532 #else 4533 PetscBool found = PETSC_FALSE; 4534 4535 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4536 for (e = firstEdge; e < edge; ++e) { 4537 const PetscInt *cone; 4538 4539 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4540 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4541 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4542 found = PETSC_TRUE; 4543 break; 4544 } 4545 } 4546 if (!found) { 4547 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4548 ++edge; 4549 } 4550 #endif 4551 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4552 } 4553 } 4554 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4555 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4556 ierr = PetscFree(off);CHKERRQ(ierr); 4557 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4558 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4559 mesh = (DM_Plex*) (idm)->data; 4560 /* Orient edges */ 4561 for (c = 0; c < numCells; ++c) { 4562 const PetscInt *cone = PETSC_NULL, *cellFaces; 4563 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4564 4565 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4566 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4567 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4568 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4569 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4570 for (cf = 0; cf < numCellFaces; ++cf) { 4571 const PetscInt *econe = PETSC_NULL; 4572 PetscInt esize; 4573 4574 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4575 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4576 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4577 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4578 /* Correctly oriented */ 4579 mesh->coneOrientations[coff+cf] = 0; 4580 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4581 /* Start at index 1, and reverse orientation */ 4582 mesh->coneOrientations[coff+cf] = -(1+1); 4583 } 4584 } 4585 } 4586 *dmInt = idm; 4587 PetscFunctionReturn(0); 4588 } 4589 4590 #undef __FUNCT__ 4591 #define __FUNCT__ "DMPlexInterpolate_3D" 4592 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4593 { 4594 DM idm, fdm; 4595 DM_Plex *mesh; 4596 PetscInt *off; 4597 const PetscInt numCorners = 4; 4598 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4599 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4600 PetscErrorCode ierr; 4601 4602 PetscFunctionBegin; 4603 { 4604 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4605 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4606 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4607 } 4608 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4609 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4610 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4611 numCells = cEnd - cStart; 4612 numVertices = vEnd - vStart; 4613 firstFace = numCells + numVertices; 4614 numFaces = 0; 4615 /* Count faces using algorithm from CreateNeighborCSR */ 4616 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4617 if (off) { 4618 numFaces = off[numCells]/2; 4619 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4620 numFaces += 4*numCells - off[numCells]; 4621 } 4622 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4623 firstEdge = firstFace + numFaces; 4624 numEdges = numVertices + numFaces - numCells - 1; 4625 /* Create interpolated mesh */ 4626 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4627 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4628 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4629 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4630 for (c = 0; c < numCells; ++c) { 4631 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4632 } 4633 for (f = firstFace; f < firstFace+numFaces; ++f) { 4634 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4635 } 4636 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4637 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4638 } 4639 ierr = DMSetUp(idm);CHKERRQ(ierr); 4640 /* Get face cones from subsets of cell vertices */ 4641 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4642 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4643 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4644 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4645 for (f = firstFace; f < firstFace+numFaces; ++f) { 4646 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4647 } 4648 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4649 for (c = 0, face = firstFace; c < numCells; ++c) { 4650 const PetscInt *cellFaces; 4651 PetscInt numCellFaces, faceSize, cf; 4652 4653 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4654 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4655 for (cf = 0; cf < numCellFaces; ++cf) { 4656 PetscBool found = PETSC_FALSE; 4657 4658 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4659 for (f = firstFace; f < face; ++f) { 4660 const PetscInt *cone = PETSC_NULL; 4661 4662 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4663 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4664 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4665 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4666 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4667 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4668 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4669 found = PETSC_TRUE; 4670 break; 4671 } 4672 } 4673 if (!found) { 4674 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4675 /* Save the vertices for orientation calculation */ 4676 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4677 ++face; 4678 } 4679 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4680 } 4681 } 4682 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4683 /* Get edge cones from subsets of face vertices */ 4684 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4685 const PetscInt *cellFaces; 4686 PetscInt numCellFaces, faceSize, cf; 4687 4688 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4689 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4690 for (cf = 0; cf < numCellFaces; ++cf) { 4691 PetscBool found = PETSC_FALSE; 4692 4693 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4694 for (e = firstEdge; e < edge; ++e) { 4695 const PetscInt *cone = PETSC_NULL; 4696 4697 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4698 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4699 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4700 found = PETSC_TRUE; 4701 break; 4702 } 4703 } 4704 if (!found) { 4705 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4706 ++edge; 4707 } 4708 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4709 } 4710 } 4711 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4712 ierr = PetscFree(off);CHKERRQ(ierr); 4713 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4714 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4715 mesh = (DM_Plex*) (idm)->data; 4716 /* Orient edges */ 4717 for (f = firstFace; f < firstFace+numFaces; ++f) { 4718 const PetscInt *cone, *cellFaces; 4719 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4720 4721 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4722 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4723 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4724 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4725 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4726 for (cf = 0; cf < numCellFaces; ++cf) { 4727 const PetscInt *econe; 4728 PetscInt esize; 4729 4730 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4731 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4732 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4733 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4734 /* Correctly oriented */ 4735 mesh->coneOrientations[coff+cf] = 0; 4736 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4737 /* Start at index 1, and reverse orientation */ 4738 mesh->coneOrientations[coff+cf] = -(1+1); 4739 } 4740 } 4741 } 4742 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4743 /* Orient faces */ 4744 for (c = 0; c < numCells; ++c) { 4745 const PetscInt *cone, *cellFaces; 4746 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4747 4748 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4749 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4750 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4751 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4752 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4753 for (cf = 0; cf < numCellFaces; ++cf) { 4754 PetscInt *origClosure = PETSC_NULL, *closure; 4755 PetscInt closureSize, i; 4756 4757 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4758 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4759 for (i = 4; i < 7; ++i) { 4760 if ((origClosure[i*2] < vStart) || (origClosure[i*2] >= vEnd)) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure point %D should be a vertex in [%D, %D)", origClosure[i*2], vStart, vEnd); 4761 } 4762 closure = &origClosure[4*2]; 4763 /* Remember that this is the orientation for edges, not vertices */ 4764 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4765 /* Correctly oriented */ 4766 mesh->coneOrientations[coff+cf] = 0; 4767 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4768 /* Shifted by 1 */ 4769 mesh->coneOrientations[coff+cf] = 1; 4770 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4771 /* Shifted by 2 */ 4772 mesh->coneOrientations[coff+cf] = 2; 4773 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4774 /* Start at edge 1, and reverse orientation */ 4775 mesh->coneOrientations[coff+cf] = -(1+1); 4776 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4777 /* Start at index 0, and reverse orientation */ 4778 mesh->coneOrientations[coff+cf] = -(0+1); 4779 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4780 /* Start at index 2, and reverse orientation */ 4781 mesh->coneOrientations[coff+cf] = -(2+1); 4782 } else SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Face %D did not match local face %D in cell %D for any orientation", cone[cf], cf, c); 4783 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4784 } 4785 } 4786 { 4787 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4788 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4789 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4790 } 4791 *dmInt = idm; 4792 PetscFunctionReturn(0); 4793 } 4794 4795 #undef __FUNCT__ 4796 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4797 /* 4798 This takes as input the common mesh generator output, a list of the vertices for each cell 4799 */ 4800 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4801 { 4802 PetscInt *cone, c, p; 4803 PetscErrorCode ierr; 4804 4805 PetscFunctionBegin; 4806 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4807 for (c = 0; c < numCells; ++c) { 4808 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4809 } 4810 ierr = DMSetUp(dm);CHKERRQ(ierr); 4811 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4812 for (c = 0; c < numCells; ++c) { 4813 for (p = 0; p < numCorners; ++p) { 4814 cone[p] = cells[c*numCorners+p]+numCells; 4815 } 4816 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4817 } 4818 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4819 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4820 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4821 PetscFunctionReturn(0); 4822 } 4823 4824 #undef __FUNCT__ 4825 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4826 /* 4827 This takes as input the coordinates for each vertex 4828 */ 4829 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4830 { 4831 PetscSection coordSection; 4832 Vec coordinates; 4833 PetscScalar *coords; 4834 PetscInt coordSize, v, d; 4835 PetscErrorCode ierr; 4836 4837 PetscFunctionBegin; 4838 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4839 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4840 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4841 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4842 for (v = numCells; v < numCells+numVertices; ++v) { 4843 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4844 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4845 } 4846 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4847 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4848 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4849 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4850 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4851 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4852 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4853 for (v = 0; v < numVertices; ++v) { 4854 for (d = 0; d < spaceDim; ++d) { 4855 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4856 } 4857 } 4858 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4859 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4860 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4861 PetscFunctionReturn(0); 4862 } 4863 4864 #undef __FUNCT__ 4865 #define __FUNCT__ "DMPlexCreateFromCellList" 4866 /* 4867 This takes as input the common mesh generator output, a list of the vertices for each cell 4868 */ 4869 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4870 { 4871 PetscErrorCode ierr; 4872 4873 PetscFunctionBegin; 4874 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4875 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4876 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4877 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4878 if (interpolate) { 4879 DM idm; 4880 4881 switch (dim) { 4882 case 2: 4883 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4884 case 3: 4885 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4886 default: 4887 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4888 } 4889 ierr = DMDestroy(dm);CHKERRQ(ierr); 4890 *dm = idm; 4891 } 4892 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4893 PetscFunctionReturn(0); 4894 } 4895 4896 #if defined(PETSC_HAVE_TRIANGLE) 4897 #include <triangle.h> 4898 4899 #undef __FUNCT__ 4900 #define __FUNCT__ "InitInput_Triangle" 4901 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4902 { 4903 PetscFunctionBegin; 4904 inputCtx->numberofpoints = 0; 4905 inputCtx->numberofpointattributes = 0; 4906 inputCtx->pointlist = PETSC_NULL; 4907 inputCtx->pointattributelist = PETSC_NULL; 4908 inputCtx->pointmarkerlist = PETSC_NULL; 4909 inputCtx->numberofsegments = 0; 4910 inputCtx->segmentlist = PETSC_NULL; 4911 inputCtx->segmentmarkerlist = PETSC_NULL; 4912 inputCtx->numberoftriangleattributes = 0; 4913 inputCtx->trianglelist = PETSC_NULL; 4914 inputCtx->numberofholes = 0; 4915 inputCtx->holelist = PETSC_NULL; 4916 inputCtx->numberofregions = 0; 4917 inputCtx->regionlist = PETSC_NULL; 4918 PetscFunctionReturn(0); 4919 } 4920 4921 #undef __FUNCT__ 4922 #define __FUNCT__ "InitOutput_Triangle" 4923 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4924 { 4925 PetscFunctionBegin; 4926 outputCtx->numberofpoints = 0; 4927 outputCtx->pointlist = PETSC_NULL; 4928 outputCtx->pointattributelist = PETSC_NULL; 4929 outputCtx->pointmarkerlist = PETSC_NULL; 4930 outputCtx->numberoftriangles = 0; 4931 outputCtx->trianglelist = PETSC_NULL; 4932 outputCtx->triangleattributelist = PETSC_NULL; 4933 outputCtx->neighborlist = PETSC_NULL; 4934 outputCtx->segmentlist = PETSC_NULL; 4935 outputCtx->segmentmarkerlist = PETSC_NULL; 4936 outputCtx->numberofedges = 0; 4937 outputCtx->edgelist = PETSC_NULL; 4938 outputCtx->edgemarkerlist = PETSC_NULL; 4939 PetscFunctionReturn(0); 4940 } 4941 4942 #undef __FUNCT__ 4943 #define __FUNCT__ "FiniOutput_Triangle" 4944 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4945 { 4946 PetscFunctionBegin; 4947 free(outputCtx->pointmarkerlist); 4948 free(outputCtx->edgelist); 4949 free(outputCtx->edgemarkerlist); 4950 free(outputCtx->trianglelist); 4951 free(outputCtx->neighborlist); 4952 PetscFunctionReturn(0); 4953 } 4954 4955 #undef __FUNCT__ 4956 #define __FUNCT__ "DMPlexGenerate_Triangle" 4957 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4958 { 4959 MPI_Comm comm = ((PetscObject) boundary)->comm; 4960 PetscInt dim = 2; 4961 const PetscBool createConvexHull = PETSC_FALSE; 4962 const PetscBool constrained = PETSC_FALSE; 4963 struct triangulateio in; 4964 struct triangulateio out; 4965 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4966 PetscMPIInt rank; 4967 PetscErrorCode ierr; 4968 4969 PetscFunctionBegin; 4970 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4971 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4972 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4973 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4974 4975 in.numberofpoints = vEnd - vStart; 4976 if (in.numberofpoints > 0) { 4977 PetscSection coordSection; 4978 Vec coordinates; 4979 PetscScalar *array; 4980 4981 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4982 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4983 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4984 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4985 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4986 for (v = vStart; v < vEnd; ++v) { 4987 const PetscInt idx = v - vStart; 4988 PetscInt off, d; 4989 4990 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4991 for (d = 0; d < dim; ++d) { 4992 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4993 } 4994 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4995 } 4996 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4997 } 4998 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4999 in.numberofsegments = eEnd - eStart; 5000 if (in.numberofsegments > 0) { 5001 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 5002 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 5003 for (e = eStart; e < eEnd; ++e) { 5004 const PetscInt idx = e - eStart; 5005 const PetscInt *cone; 5006 5007 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 5008 5009 in.segmentlist[idx*2+0] = cone[0] - vStart; 5010 in.segmentlist[idx*2+1] = cone[1] - vStart; 5011 5012 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5013 } 5014 } 5015 #if 0 /* Do not currently support holes */ 5016 PetscReal *holeCoords; 5017 PetscInt h, d; 5018 5019 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5020 if (in.numberofholes > 0) { 5021 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5022 for (h = 0; h < in.numberofholes; ++h) { 5023 for (d = 0; d < dim; ++d) { 5024 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5025 } 5026 } 5027 } 5028 #endif 5029 if (!rank) { 5030 char args[32]; 5031 5032 /* Take away 'Q' for verbose output */ 5033 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5034 if (createConvexHull) { 5035 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5036 } 5037 if (constrained) { 5038 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5039 } 5040 triangulate(args, &in, &out, PETSC_NULL); 5041 } 5042 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5043 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5044 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5045 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5046 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5047 5048 { 5049 const PetscInt numCorners = 3; 5050 const PetscInt numCells = out.numberoftriangles; 5051 const PetscInt numVertices = out.numberofpoints; 5052 const int *cells = out.trianglelist; 5053 const double *meshCoords = out.pointlist; 5054 5055 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5056 /* Set labels */ 5057 for (v = 0; v < numVertices; ++v) { 5058 if (out.pointmarkerlist[v]) { 5059 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5060 } 5061 } 5062 if (interpolate) { 5063 for (e = 0; e < out.numberofedges; e++) { 5064 if (out.edgemarkerlist[e]) { 5065 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5066 const PetscInt *edges; 5067 PetscInt numEdges; 5068 5069 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5070 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5071 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5072 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5073 } 5074 } 5075 } 5076 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5077 } 5078 #if 0 /* Do not currently support holes */ 5079 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5080 #endif 5081 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5082 PetscFunctionReturn(0); 5083 } 5084 5085 #undef __FUNCT__ 5086 #define __FUNCT__ "DMPlexRefine_Triangle" 5087 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5088 { 5089 MPI_Comm comm = ((PetscObject) dm)->comm; 5090 PetscInt dim = 2; 5091 struct triangulateio in; 5092 struct triangulateio out; 5093 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5094 PetscMPIInt rank; 5095 PetscErrorCode ierr; 5096 5097 PetscFunctionBegin; 5098 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5099 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5100 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5101 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5102 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5103 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5104 5105 in.numberofpoints = vEnd - vStart; 5106 if (in.numberofpoints > 0) { 5107 PetscSection coordSection; 5108 Vec coordinates; 5109 PetscScalar *array; 5110 5111 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5112 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5113 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5114 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5115 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5116 for (v = vStart; v < vEnd; ++v) { 5117 const PetscInt idx = v - vStart; 5118 PetscInt off, d; 5119 5120 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5121 for (d = 0; d < dim; ++d) { 5122 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5123 } 5124 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5125 } 5126 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5127 } 5128 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5129 5130 in.numberofcorners = 3; 5131 in.numberoftriangles = cEnd - cStart; 5132 5133 in.trianglearealist = (double*) maxVolumes; 5134 if (in.numberoftriangles > 0) { 5135 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5136 for (c = cStart; c < cEnd; ++c) { 5137 const PetscInt idx = c - cStart; 5138 PetscInt *closure = PETSC_NULL; 5139 PetscInt closureSize; 5140 5141 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5142 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5143 for (v = 0; v < 3; ++v) { 5144 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5145 } 5146 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5147 } 5148 } 5149 /* TODO: Segment markers are missing on input */ 5150 #if 0 /* Do not currently support holes */ 5151 PetscReal *holeCoords; 5152 PetscInt h, d; 5153 5154 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5155 if (in.numberofholes > 0) { 5156 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5157 for (h = 0; h < in.numberofholes; ++h) { 5158 for (d = 0; d < dim; ++d) { 5159 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5160 } 5161 } 5162 } 5163 #endif 5164 if (!rank) { 5165 char args[32]; 5166 5167 /* Take away 'Q' for verbose output */ 5168 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5169 triangulate(args, &in, &out, PETSC_NULL); 5170 } 5171 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5172 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5173 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5174 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5175 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5176 5177 { 5178 const PetscInt numCorners = 3; 5179 const PetscInt numCells = out.numberoftriangles; 5180 const PetscInt numVertices = out.numberofpoints; 5181 const int *cells = out.trianglelist; 5182 const double *meshCoords = out.pointlist; 5183 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5184 5185 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5186 /* Set labels */ 5187 for (v = 0; v < numVertices; ++v) { 5188 if (out.pointmarkerlist[v]) { 5189 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5190 } 5191 } 5192 if (interpolate) { 5193 PetscInt e; 5194 5195 for (e = 0; e < out.numberofedges; e++) { 5196 if (out.edgemarkerlist[e]) { 5197 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5198 const PetscInt *edges; 5199 PetscInt numEdges; 5200 5201 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5202 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5203 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5204 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5205 } 5206 } 5207 } 5208 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5209 } 5210 #if 0 /* Do not currently support holes */ 5211 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5212 #endif 5213 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5214 PetscFunctionReturn(0); 5215 } 5216 #endif 5217 5218 #if defined(PETSC_HAVE_TETGEN) 5219 #include <tetgen.h> 5220 #undef __FUNCT__ 5221 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5222 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5223 { 5224 MPI_Comm comm = ((PetscObject) boundary)->comm; 5225 const PetscInt dim = 3; 5226 ::tetgenio in; 5227 ::tetgenio out; 5228 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5229 PetscMPIInt rank; 5230 PetscErrorCode ierr; 5231 5232 PetscFunctionBegin; 5233 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5234 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5235 in.numberofpoints = vEnd - vStart; 5236 if (in.numberofpoints > 0) { 5237 PetscSection coordSection; 5238 Vec coordinates; 5239 PetscScalar *array; 5240 5241 in.pointlist = new double[in.numberofpoints*dim]; 5242 in.pointmarkerlist = new int[in.numberofpoints]; 5243 5244 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5245 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5246 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5247 for (v = vStart; v < vEnd; ++v) { 5248 const PetscInt idx = v - vStart; 5249 PetscInt off, d; 5250 5251 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5252 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5253 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5254 } 5255 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5256 } 5257 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5258 5259 in.numberoffacets = fEnd - fStart; 5260 if (in.numberoffacets > 0) { 5261 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5262 in.facetmarkerlist = new int[in.numberoffacets]; 5263 for (f = fStart; f < fEnd; ++f) { 5264 const PetscInt idx = f - fStart; 5265 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5266 5267 in.facetlist[idx].numberofpolygons = 1; 5268 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5269 in.facetlist[idx].numberofholes = 0; 5270 in.facetlist[idx].holelist = NULL; 5271 5272 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5273 for (p = 0; p < numPoints*2; p += 2) { 5274 const PetscInt point = points[p]; 5275 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5276 } 5277 5278 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5279 poly->numberofvertices = numVertices; 5280 poly->vertexlist = new int[poly->numberofvertices]; 5281 for (v = 0; v < numVertices; ++v) { 5282 const PetscInt vIdx = points[v] - vStart; 5283 poly->vertexlist[v] = vIdx; 5284 } 5285 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5286 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5287 } 5288 } 5289 if (!rank) { 5290 char args[32]; 5291 5292 /* Take away 'Q' for verbose output */ 5293 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5294 ::tetrahedralize(args, &in, &out); 5295 } 5296 { 5297 const PetscInt numCorners = 4; 5298 const PetscInt numCells = out.numberoftetrahedra; 5299 const PetscInt numVertices = out.numberofpoints; 5300 const int *cells = out.tetrahedronlist; 5301 const double *meshCoords = out.pointlist; 5302 5303 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5304 /* Set labels */ 5305 for (v = 0; v < numVertices; ++v) { 5306 if (out.pointmarkerlist[v]) { 5307 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5308 } 5309 } 5310 if (interpolate) { 5311 PetscInt e; 5312 5313 for (e = 0; e < out.numberofedges; e++) { 5314 if (out.edgemarkerlist[e]) { 5315 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5316 const PetscInt *edges; 5317 PetscInt numEdges; 5318 5319 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5320 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5321 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5322 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5323 } 5324 } 5325 for (f = 0; f < out.numberoftrifaces; f++) { 5326 if (out.trifacemarkerlist[f]) { 5327 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5328 const PetscInt *faces; 5329 PetscInt numFaces; 5330 5331 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5332 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5333 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5334 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5335 } 5336 } 5337 } 5338 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5339 } 5340 PetscFunctionReturn(0); 5341 } 5342 5343 #undef __FUNCT__ 5344 #define __FUNCT__ "DMPlexRefine_Tetgen" 5345 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5346 { 5347 MPI_Comm comm = ((PetscObject) dm)->comm; 5348 const PetscInt dim = 3; 5349 ::tetgenio in; 5350 ::tetgenio out; 5351 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5352 PetscMPIInt rank; 5353 PetscErrorCode ierr; 5354 5355 PetscFunctionBegin; 5356 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5357 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5358 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5359 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5360 5361 in.numberofpoints = vEnd - vStart; 5362 if (in.numberofpoints > 0) { 5363 PetscSection coordSection; 5364 Vec coordinates; 5365 PetscScalar *array; 5366 5367 in.pointlist = new double[in.numberofpoints*dim]; 5368 in.pointmarkerlist = new int[in.numberofpoints]; 5369 5370 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5371 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5372 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5373 for (v = vStart; v < vEnd; ++v) { 5374 const PetscInt idx = v - vStart; 5375 PetscInt off, d; 5376 5377 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5378 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5379 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5380 } 5381 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5382 } 5383 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5384 5385 in.numberofcorners = 4; 5386 in.numberoftetrahedra = cEnd - cStart; 5387 in.tetrahedronvolumelist = (double*) maxVolumes; 5388 if (in.numberoftetrahedra > 0) { 5389 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5390 for (c = cStart; c < cEnd; ++c) { 5391 const PetscInt idx = c - cStart; 5392 PetscInt *closure = PETSC_NULL; 5393 PetscInt closureSize; 5394 5395 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5396 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5397 for (v = 0; v < 4; ++v) { 5398 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5399 } 5400 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5401 } 5402 } 5403 /* TODO: Put in boundary faces with markers */ 5404 if (!rank) { 5405 char args[32]; 5406 5407 /* Take away 'Q' for verbose output */ 5408 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5409 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5410 ::tetrahedralize(args, &in, &out); 5411 } 5412 in.tetrahedronvolumelist = NULL; 5413 5414 { 5415 const PetscInt numCorners = 4; 5416 const PetscInt numCells = out.numberoftetrahedra; 5417 const PetscInt numVertices = out.numberofpoints; 5418 const int *cells = out.tetrahedronlist; 5419 const double *meshCoords = out.pointlist; 5420 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5421 5422 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5423 /* Set labels */ 5424 for (v = 0; v < numVertices; ++v) { 5425 if (out.pointmarkerlist[v]) { 5426 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5427 } 5428 } 5429 if (interpolate) { 5430 PetscInt e, f; 5431 5432 for (e = 0; e < out.numberofedges; e++) { 5433 if (out.edgemarkerlist[e]) { 5434 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5435 const PetscInt *edges; 5436 PetscInt numEdges; 5437 5438 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5439 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5440 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5441 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5442 } 5443 } 5444 for (f = 0; f < out.numberoftrifaces; f++) { 5445 if (out.trifacemarkerlist[f]) { 5446 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5447 const PetscInt *faces; 5448 PetscInt numFaces; 5449 5450 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5451 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5452 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5453 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5454 } 5455 } 5456 } 5457 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5458 } 5459 PetscFunctionReturn(0); 5460 } 5461 #endif 5462 5463 #if defined(PETSC_HAVE_CTETGEN) 5464 #include "ctetgen.h" 5465 5466 #undef __FUNCT__ 5467 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5468 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5469 { 5470 MPI_Comm comm = ((PetscObject) boundary)->comm; 5471 const PetscInt dim = 3; 5472 PLC *in, *out; 5473 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5474 PetscMPIInt rank; 5475 PetscErrorCode ierr; 5476 5477 PetscFunctionBegin; 5478 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5479 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5480 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5481 ierr = PLCCreate(&in);CHKERRQ(ierr); 5482 ierr = PLCCreate(&out);CHKERRQ(ierr); 5483 5484 in->numberofpoints = vEnd - vStart; 5485 if (in->numberofpoints > 0) { 5486 PetscSection coordSection; 5487 Vec coordinates; 5488 PetscScalar *array; 5489 5490 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5491 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5492 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5493 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5494 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5495 for (v = vStart; v < vEnd; ++v) { 5496 const PetscInt idx = v - vStart; 5497 PetscInt off, d, m; 5498 5499 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5500 for (d = 0; d < dim; ++d) { 5501 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5502 } 5503 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5504 5505 in->pointmarkerlist[idx] = (int) m; 5506 } 5507 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5508 } 5509 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5510 5511 in->numberoffacets = fEnd - fStart; 5512 if (in->numberoffacets > 0) { 5513 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5514 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5515 for (f = fStart; f < fEnd; ++f) { 5516 const PetscInt idx = f - fStart; 5517 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5518 polygon *poly; 5519 5520 in->facetlist[idx].numberofpolygons = 1; 5521 5522 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5523 5524 in->facetlist[idx].numberofholes = 0; 5525 in->facetlist[idx].holelist = PETSC_NULL; 5526 5527 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5528 for (p = 0; p < numPoints*2; p += 2) { 5529 const PetscInt point = points[p]; 5530 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5531 } 5532 5533 poly = in->facetlist[idx].polygonlist; 5534 poly->numberofvertices = numVertices; 5535 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5536 for (v = 0; v < numVertices; ++v) { 5537 const PetscInt vIdx = points[v] - vStart; 5538 poly->vertexlist[v] = vIdx; 5539 } 5540 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5541 in->facetmarkerlist[idx] = (int) m; 5542 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5543 } 5544 } 5545 if (!rank) { 5546 TetGenOpts t; 5547 5548 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5549 t.in = boundary; /* Should go away */ 5550 t.plc = 1; 5551 t.quality = 1; 5552 t.edgesout = 1; 5553 t.zeroindex = 1; 5554 t.quiet = 1; 5555 t.verbose = verbose; 5556 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5557 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5558 } 5559 { 5560 const PetscInt numCorners = 4; 5561 const PetscInt numCells = out->numberoftetrahedra; 5562 const PetscInt numVertices = out->numberofpoints; 5563 const int *cells = out->tetrahedronlist; 5564 const double *meshCoords = out->pointlist; 5565 5566 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5567 /* Set labels */ 5568 for (v = 0; v < numVertices; ++v) { 5569 if (out->pointmarkerlist[v]) { 5570 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5571 } 5572 } 5573 if (interpolate) { 5574 PetscInt e; 5575 5576 for (e = 0; e < out->numberofedges; e++) { 5577 if (out->edgemarkerlist[e]) { 5578 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5579 const PetscInt *edges; 5580 PetscInt numEdges; 5581 5582 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5583 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5584 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5585 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5586 } 5587 } 5588 for (f = 0; f < out->numberoftrifaces; f++) { 5589 if (out->trifacemarkerlist[f]) { 5590 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5591 const PetscInt *faces; 5592 PetscInt numFaces; 5593 5594 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5595 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5596 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5597 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5598 } 5599 } 5600 } 5601 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5602 } 5603 5604 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5605 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5606 PetscFunctionReturn(0); 5607 } 5608 5609 #undef __FUNCT__ 5610 #define __FUNCT__ "DMPlexRefine_CTetgen" 5611 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5612 { 5613 MPI_Comm comm = ((PetscObject) dm)->comm; 5614 const PetscInt dim = 3; 5615 PLC *in, *out; 5616 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5617 PetscMPIInt rank; 5618 PetscErrorCode ierr; 5619 5620 PetscFunctionBegin; 5621 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5622 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5623 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5624 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5625 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5626 ierr = PLCCreate(&in);CHKERRQ(ierr); 5627 ierr = PLCCreate(&out);CHKERRQ(ierr); 5628 5629 in->numberofpoints = vEnd - vStart; 5630 if (in->numberofpoints > 0) { 5631 PetscSection coordSection; 5632 Vec coordinates; 5633 PetscScalar *array; 5634 5635 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5636 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5637 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5638 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5639 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5640 for (v = vStart; v < vEnd; ++v) { 5641 const PetscInt idx = v - vStart; 5642 PetscInt off, d, m; 5643 5644 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5645 for (d = 0; d < dim; ++d) { 5646 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5647 } 5648 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5649 5650 in->pointmarkerlist[idx] = (int) m; 5651 } 5652 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5653 } 5654 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5655 5656 in->numberofcorners = 4; 5657 in->numberoftetrahedra = cEnd - cStart; 5658 in->tetrahedronvolumelist = maxVolumes; 5659 if (in->numberoftetrahedra > 0) { 5660 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5661 for (c = cStart; c < cEnd; ++c) { 5662 const PetscInt idx = c - cStart; 5663 PetscInt *closure = PETSC_NULL; 5664 PetscInt closureSize; 5665 5666 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5667 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5668 for (v = 0; v < 4; ++v) { 5669 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5670 } 5671 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5672 } 5673 } 5674 if (!rank) { 5675 TetGenOpts t; 5676 5677 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5678 5679 t.in = dm; /* Should go away */ 5680 t.refine = 1; 5681 t.varvolume = 1; 5682 t.quality = 1; 5683 t.edgesout = 1; 5684 t.zeroindex = 1; 5685 t.quiet = 1; 5686 t.verbose = verbose; /* Change this */ 5687 5688 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5689 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5690 } 5691 { 5692 const PetscInt numCorners = 4; 5693 const PetscInt numCells = out->numberoftetrahedra; 5694 const PetscInt numVertices = out->numberofpoints; 5695 const int *cells = out->tetrahedronlist; 5696 const double *meshCoords = out->pointlist; 5697 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5698 5699 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5700 /* Set labels */ 5701 for (v = 0; v < numVertices; ++v) { 5702 if (out->pointmarkerlist[v]) { 5703 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5704 } 5705 } 5706 if (interpolate) { 5707 PetscInt e, f; 5708 5709 for (e = 0; e < out->numberofedges; e++) { 5710 if (out->edgemarkerlist[e]) { 5711 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5712 const PetscInt *edges; 5713 PetscInt numEdges; 5714 5715 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5716 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5717 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5718 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5719 } 5720 } 5721 for (f = 0; f < out->numberoftrifaces; f++) { 5722 if (out->trifacemarkerlist[f]) { 5723 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5724 const PetscInt *faces; 5725 PetscInt numFaces; 5726 5727 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5728 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5729 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5730 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5731 } 5732 } 5733 } 5734 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5735 } 5736 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5737 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5738 PetscFunctionReturn(0); 5739 } 5740 #endif 5741 5742 #undef __FUNCT__ 5743 #define __FUNCT__ "DMPlexGenerate" 5744 /*@C 5745 DMPlexGenerate - Generates a mesh. 5746 5747 Not Collective 5748 5749 Input Parameters: 5750 + boundary - The DMPlex boundary object 5751 . name - The mesh generation package name 5752 - interpolate - Flag to create intermediate mesh elements 5753 5754 Output Parameter: 5755 . mesh - The DMPlex object 5756 5757 Level: intermediate 5758 5759 .keywords: mesh, elements 5760 .seealso: DMPlexCreate(), DMRefine() 5761 @*/ 5762 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5763 { 5764 PetscInt dim; 5765 char genname[1024]; 5766 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5767 PetscErrorCode ierr; 5768 5769 PetscFunctionBegin; 5770 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5771 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5772 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5773 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5774 if (flg) name = genname; 5775 if (name) { 5776 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5777 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5778 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5779 } 5780 switch (dim) { 5781 case 1: 5782 if (!name || isTriangle) { 5783 #if defined(PETSC_HAVE_TRIANGLE) 5784 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5785 #else 5786 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5787 #endif 5788 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5789 break; 5790 case 2: 5791 if (!name || isCTetgen) { 5792 #if defined(PETSC_HAVE_CTETGEN) 5793 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5794 #else 5795 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5796 #endif 5797 } else if (isTetgen) { 5798 #if defined(PETSC_HAVE_TETGEN) 5799 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5800 #else 5801 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5802 #endif 5803 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5804 break; 5805 default: 5806 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5807 } 5808 PetscFunctionReturn(0); 5809 } 5810 5811 typedef PetscInt CellRefiner; 5812 5813 #undef __FUNCT__ 5814 #define __FUNCT__ "GetDepthStart_Private" 5815 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5816 { 5817 PetscFunctionBegin; 5818 if (cStart) *cStart = 0; 5819 if (vStart) *vStart = depthSize[depth]; 5820 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5821 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5822 PetscFunctionReturn(0); 5823 } 5824 5825 #undef __FUNCT__ 5826 #define __FUNCT__ "GetDepthEnd_Private" 5827 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5828 { 5829 PetscFunctionBegin; 5830 if (cEnd) *cEnd = depthSize[depth]; 5831 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5832 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5833 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5834 PetscFunctionReturn(0); 5835 } 5836 5837 #undef __FUNCT__ 5838 #define __FUNCT__ "CellRefinerGetSizes" 5839 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5840 { 5841 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5842 PetscErrorCode ierr; 5843 5844 PetscFunctionBegin; 5845 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5846 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5847 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5848 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5849 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5850 switch (refiner) { 5851 case 1: 5852 /* Simplicial 2D */ 5853 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5854 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5855 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5856 break; 5857 case 3: 5858 /* Hybrid 2D */ 5859 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5860 cMax = PetscMin(cEnd, cMax); 5861 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5862 fMax = PetscMin(fEnd, fMax); 5863 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5864 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 */ 5865 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5866 break; 5867 case 2: 5868 /* Hex 2D */ 5869 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5870 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5871 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5872 break; 5873 default: 5874 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5875 } 5876 PetscFunctionReturn(0); 5877 } 5878 5879 #undef __FUNCT__ 5880 #define __FUNCT__ "CellRefinerSetConeSizes" 5881 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5882 { 5883 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5884 PetscErrorCode ierr; 5885 5886 PetscFunctionBegin; 5887 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5888 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5889 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5890 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5891 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5892 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5893 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5894 switch (refiner) { 5895 case 1: 5896 /* Simplicial 2D */ 5897 /* All cells have 3 faces */ 5898 for (c = cStart; c < cEnd; ++c) { 5899 for (r = 0; r < 4; ++r) { 5900 const PetscInt newp = (c - cStart)*4 + r; 5901 5902 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5903 } 5904 } 5905 /* Split faces have 2 vertices and the same cells as the parent */ 5906 for (f = fStart; f < fEnd; ++f) { 5907 for (r = 0; r < 2; ++r) { 5908 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5909 PetscInt size; 5910 5911 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5912 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5913 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5914 } 5915 } 5916 /* Interior faces have 2 vertices and 2 cells */ 5917 for (c = cStart; c < cEnd; ++c) { 5918 for (r = 0; r < 3; ++r) { 5919 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5920 5921 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5922 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5923 } 5924 } 5925 /* Old vertices have identical supports */ 5926 for (v = vStart; v < vEnd; ++v) { 5927 const PetscInt newp = vStartNew + (v - vStart); 5928 PetscInt size; 5929 5930 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5931 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5932 } 5933 /* Face vertices have 2 + cells*2 supports */ 5934 for (f = fStart; f < fEnd; ++f) { 5935 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5936 PetscInt size; 5937 5938 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5939 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5940 } 5941 break; 5942 case 2: 5943 /* Hex 2D */ 5944 /* All cells have 4 faces */ 5945 for (c = cStart; c < cEnd; ++c) { 5946 for (r = 0; r < 4; ++r) { 5947 const PetscInt newp = (c - cStart)*4 + r; 5948 5949 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5950 } 5951 } 5952 /* Split faces have 2 vertices and the same cells as the parent */ 5953 for (f = fStart; f < fEnd; ++f) { 5954 for (r = 0; r < 2; ++r) { 5955 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5956 PetscInt size; 5957 5958 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5959 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5960 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5961 } 5962 } 5963 /* Interior faces have 2 vertices and 2 cells */ 5964 for (c = cStart; c < cEnd; ++c) { 5965 for (r = 0; r < 4; ++r) { 5966 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5967 5968 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5969 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5970 } 5971 } 5972 /* Old vertices have identical supports */ 5973 for (v = vStart; v < vEnd; ++v) { 5974 const PetscInt newp = vStartNew + (v - vStart); 5975 PetscInt size; 5976 5977 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5978 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5979 } 5980 /* Face vertices have 2 + cells supports */ 5981 for (f = fStart; f < fEnd; ++f) { 5982 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5983 PetscInt size; 5984 5985 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5986 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5987 } 5988 /* Cell vertices have 4 supports */ 5989 for (c = cStart; c < cEnd; ++c) { 5990 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5991 5992 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5993 } 5994 break; 5995 case 3: 5996 /* Hybrid 2D */ 5997 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5998 cMax = PetscMin(cEnd, cMax); 5999 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6000 fMax = PetscMin(fEnd, fMax); 6001 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6002 /* Interior cells have 3 faces */ 6003 for (c = cStart; c < cMax; ++c) { 6004 for (r = 0; r < 4; ++r) { 6005 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 6006 6007 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 6008 } 6009 } 6010 /* Hybrid cells have 4 faces */ 6011 for (c = cMax; c < cEnd; ++c) { 6012 for (r = 0; r < 2; ++r) { 6013 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6014 6015 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6016 } 6017 } 6018 /* Interior split faces have 2 vertices and the same cells as the parent */ 6019 for (f = fStart; f < fMax; ++f) { 6020 for (r = 0; r < 2; ++r) { 6021 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6022 PetscInt size; 6023 6024 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6025 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6026 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6027 } 6028 } 6029 /* Interior cell faces have 2 vertices and 2 cells */ 6030 for (c = cStart; c < cMax; ++c) { 6031 for (r = 0; r < 3; ++r) { 6032 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6033 6034 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6035 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6036 } 6037 } 6038 /* Hybrid faces have 2 vertices and the same cells */ 6039 for (f = fMax; f < fEnd; ++f) { 6040 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6041 PetscInt size; 6042 6043 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6044 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6045 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6046 } 6047 /* Hybrid cell faces have 2 vertices and 2 cells */ 6048 for (c = cMax; c < cEnd; ++c) { 6049 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6050 6051 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6052 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6053 } 6054 /* Old vertices have identical supports */ 6055 for (v = vStart; v < vEnd; ++v) { 6056 const PetscInt newp = vStartNew + (v - vStart); 6057 PetscInt size; 6058 6059 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6060 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6061 } 6062 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6063 for (f = fStart; f < fMax; ++f) { 6064 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6065 const PetscInt *support; 6066 PetscInt size, newSize = 2, s; 6067 6068 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6069 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6070 for (s = 0; s < size; ++s) { 6071 if (support[s] >= cMax) newSize += 1; 6072 else newSize += 2; 6073 } 6074 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6075 } 6076 break; 6077 default: 6078 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6079 } 6080 PetscFunctionReturn(0); 6081 } 6082 6083 #undef __FUNCT__ 6084 #define __FUNCT__ "CellRefinerSetCones" 6085 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6086 { 6087 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; 6088 PetscInt maxSupportSize, *supportRef; 6089 PetscErrorCode ierr; 6090 6091 PetscFunctionBegin; 6092 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6093 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6094 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6095 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6096 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6097 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6098 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6099 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6100 switch (refiner) { 6101 case 1: 6102 /* Simplicial 2D */ 6103 /* 6104 2 6105 |\ 6106 | \ 6107 | \ 6108 | \ 6109 | C \ 6110 | \ 6111 | \ 6112 2---1---1 6113 |\ D / \ 6114 | 2 0 \ 6115 |A \ / B \ 6116 0---0-------1 6117 */ 6118 /* All cells have 3 faces */ 6119 for (c = cStart; c < cEnd; ++c) { 6120 const PetscInt newp = cStartNew + (c - cStart)*4; 6121 const PetscInt *cone, *ornt; 6122 PetscInt coneNew[3], orntNew[3]; 6123 6124 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6125 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6126 /* A triangle */ 6127 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6128 orntNew[0] = ornt[0]; 6129 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6130 orntNew[1] = -2; 6131 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6132 orntNew[2] = ornt[2]; 6133 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6134 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6135 #if 1 6136 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6137 for (p = 0; p < 3; ++p) { 6138 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6139 } 6140 #endif 6141 /* B triangle */ 6142 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6143 orntNew[0] = ornt[0]; 6144 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6145 orntNew[1] = ornt[1]; 6146 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6147 orntNew[2] = -2; 6148 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6149 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6150 #if 1 6151 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6152 for (p = 0; p < 3; ++p) { 6153 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6154 } 6155 #endif 6156 /* C triangle */ 6157 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6158 orntNew[0] = -2; 6159 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6160 orntNew[1] = ornt[1]; 6161 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6162 orntNew[2] = ornt[2]; 6163 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6164 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6165 #if 1 6166 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6167 for (p = 0; p < 3; ++p) { 6168 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6169 } 6170 #endif 6171 /* D triangle */ 6172 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6173 orntNew[0] = 0; 6174 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6175 orntNew[1] = 0; 6176 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6177 orntNew[2] = 0; 6178 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6179 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6180 #if 1 6181 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6182 for (p = 0; p < 3; ++p) { 6183 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6184 } 6185 #endif 6186 } 6187 /* Split faces have 2 vertices and the same cells as the parent */ 6188 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6189 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6190 for (f = fStart; f < fEnd; ++f) { 6191 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6192 6193 for (r = 0; r < 2; ++r) { 6194 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6195 const PetscInt *cone, *support; 6196 PetscInt coneNew[2], coneSize, c, supportSize, s; 6197 6198 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6199 coneNew[0] = vStartNew + (cone[0] - vStart); 6200 coneNew[1] = vStartNew + (cone[1] - vStart); 6201 coneNew[(r+1)%2] = newv; 6202 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6203 #if 1 6204 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6205 for (p = 0; p < 2; ++p) { 6206 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6207 } 6208 #endif 6209 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6210 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6211 for (s = 0; s < supportSize; ++s) { 6212 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6213 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6214 for (c = 0; c < coneSize; ++c) { 6215 if (cone[c] == f) break; 6216 } 6217 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6218 } 6219 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6220 #if 1 6221 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6222 for (p = 0; p < supportSize; ++p) { 6223 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6224 } 6225 #endif 6226 } 6227 } 6228 /* Interior faces have 2 vertices and 2 cells */ 6229 for (c = cStart; c < cEnd; ++c) { 6230 const PetscInt *cone; 6231 6232 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6233 for (r = 0; r < 3; ++r) { 6234 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6235 PetscInt coneNew[2]; 6236 PetscInt supportNew[2]; 6237 6238 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6239 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6240 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6241 #if 1 6242 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6243 for (p = 0; p < 2; ++p) { 6244 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6245 } 6246 #endif 6247 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6248 supportNew[1] = (c - cStart)*4 + 3; 6249 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6250 #if 1 6251 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6252 for (p = 0; p < 2; ++p) { 6253 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6254 } 6255 #endif 6256 } 6257 } 6258 /* Old vertices have identical supports */ 6259 for (v = vStart; v < vEnd; ++v) { 6260 const PetscInt newp = vStartNew + (v - vStart); 6261 const PetscInt *support, *cone; 6262 PetscInt size, s; 6263 6264 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6265 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6266 for (s = 0; s < size; ++s) { 6267 PetscInt r = 0; 6268 6269 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6270 if (cone[1] == v) r = 1; 6271 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6272 } 6273 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6274 #if 1 6275 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6276 for (p = 0; p < size; ++p) { 6277 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6278 } 6279 #endif 6280 } 6281 /* Face vertices have 2 + cells*2 supports */ 6282 for (f = fStart; f < fEnd; ++f) { 6283 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6284 const PetscInt *cone, *support; 6285 PetscInt size, s; 6286 6287 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6288 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6289 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6290 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6291 for (s = 0; s < size; ++s) { 6292 PetscInt r = 0; 6293 6294 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6295 if (cone[1] == f) r = 1; 6296 else if (cone[2] == f) r = 2; 6297 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6298 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6299 } 6300 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6301 #if 1 6302 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6303 for (p = 0; p < 2+size*2; ++p) { 6304 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6305 } 6306 #endif 6307 } 6308 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6309 break; 6310 case 2: 6311 /* Hex 2D */ 6312 /* 6313 3---------2---------2 6314 | | | 6315 | D 2 C | 6316 | | | 6317 3----3----0----1----1 6318 | | | 6319 | A 0 B | 6320 | | | 6321 0---------0---------1 6322 */ 6323 /* All cells have 4 faces */ 6324 for (c = cStart; c < cEnd; ++c) { 6325 const PetscInt newp = (c - cStart)*4; 6326 const PetscInt *cone, *ornt; 6327 PetscInt coneNew[4], orntNew[4]; 6328 6329 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6330 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6331 /* A quad */ 6332 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6333 orntNew[0] = ornt[0]; 6334 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6335 orntNew[1] = 0; 6336 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6337 orntNew[2] = -2; 6338 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6339 orntNew[3] = ornt[3]; 6340 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6341 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6342 #if 1 6343 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6344 for (p = 0; p < 4; ++p) { 6345 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6346 } 6347 #endif 6348 /* B quad */ 6349 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6350 orntNew[0] = ornt[0]; 6351 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6352 orntNew[1] = ornt[1]; 6353 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6354 orntNew[2] = 0; 6355 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6356 orntNew[3] = -2; 6357 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6358 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6359 #if 1 6360 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6361 for (p = 0; p < 4; ++p) { 6362 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6363 } 6364 #endif 6365 /* C quad */ 6366 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6367 orntNew[0] = -2; 6368 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6369 orntNew[1] = ornt[1]; 6370 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6371 orntNew[2] = ornt[2]; 6372 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6373 orntNew[3] = 0; 6374 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6375 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6376 #if 1 6377 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6378 for (p = 0; p < 4; ++p) { 6379 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6380 } 6381 #endif 6382 /* D quad */ 6383 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6384 orntNew[0] = 0; 6385 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6386 orntNew[1] = -2; 6387 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6388 orntNew[2] = ornt[2]; 6389 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6390 orntNew[3] = ornt[3]; 6391 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6392 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6393 #if 1 6394 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6395 for (p = 0; p < 4; ++p) { 6396 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6397 } 6398 #endif 6399 } 6400 /* Split faces have 2 vertices and the same cells as the parent */ 6401 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6402 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6403 for (f = fStart; f < fEnd; ++f) { 6404 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6405 6406 for (r = 0; r < 2; ++r) { 6407 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6408 const PetscInt *cone, *support; 6409 PetscInt coneNew[2], coneSize, c, supportSize, s; 6410 6411 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6412 coneNew[0] = vStartNew + (cone[0] - vStart); 6413 coneNew[1] = vStartNew + (cone[1] - vStart); 6414 coneNew[(r+1)%2] = newv; 6415 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6416 #if 1 6417 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6418 for (p = 0; p < 2; ++p) { 6419 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6420 } 6421 #endif 6422 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6423 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6424 for (s = 0; s < supportSize; ++s) { 6425 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6426 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6427 for (c = 0; c < coneSize; ++c) { 6428 if (cone[c] == f) break; 6429 } 6430 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6431 } 6432 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6433 #if 1 6434 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6435 for (p = 0; p < supportSize; ++p) { 6436 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6437 } 6438 #endif 6439 } 6440 } 6441 /* Interior faces have 2 vertices and 2 cells */ 6442 for (c = cStart; c < cEnd; ++c) { 6443 const PetscInt *cone; 6444 PetscInt coneNew[2], supportNew[2]; 6445 6446 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6447 for (r = 0; r < 4; ++r) { 6448 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6449 6450 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6451 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6452 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6453 #if 1 6454 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6455 for (p = 0; p < 2; ++p) { 6456 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6457 } 6458 #endif 6459 supportNew[0] = (c - cStart)*4 + r; 6460 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6461 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6462 #if 1 6463 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6464 for (p = 0; p < 2; ++p) { 6465 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6466 } 6467 #endif 6468 } 6469 } 6470 /* Old vertices have identical supports */ 6471 for (v = vStart; v < vEnd; ++v) { 6472 const PetscInt newp = vStartNew + (v - vStart); 6473 const PetscInt *support, *cone; 6474 PetscInt size, s; 6475 6476 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6477 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6478 for (s = 0; s < size; ++s) { 6479 PetscInt r = 0; 6480 6481 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6482 if (cone[1] == v) r = 1; 6483 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6484 } 6485 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6486 #if 1 6487 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6488 for (p = 0; p < size; ++p) { 6489 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6490 } 6491 #endif 6492 } 6493 /* Face vertices have 2 + cells supports */ 6494 for (f = fStart; f < fEnd; ++f) { 6495 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6496 const PetscInt *cone, *support; 6497 PetscInt size, s; 6498 6499 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6500 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6501 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6502 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6503 for (s = 0; s < size; ++s) { 6504 PetscInt r = 0; 6505 6506 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6507 if (cone[1] == f) r = 1; 6508 else if (cone[2] == f) r = 2; 6509 else if (cone[3] == f) r = 3; 6510 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6511 } 6512 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6513 #if 1 6514 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6515 for (p = 0; p < 2+size; ++p) { 6516 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6517 } 6518 #endif 6519 } 6520 /* Cell vertices have 4 supports */ 6521 for (c = cStart; c < cEnd; ++c) { 6522 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6523 PetscInt supportNew[4]; 6524 6525 for (r = 0; r < 4; ++r) { 6526 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6527 } 6528 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6529 } 6530 break; 6531 case 3: 6532 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6533 cMax = PetscMin(cEnd, cMax); 6534 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6535 fMax = PetscMin(fEnd, fMax); 6536 /* Interior cells have 3 faces */ 6537 for (c = cStart; c < cMax; ++c) { 6538 const PetscInt newp = cStartNew + (c - cStart)*4; 6539 const PetscInt *cone, *ornt; 6540 PetscInt coneNew[3], orntNew[3]; 6541 6542 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6543 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6544 /* A triangle */ 6545 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6546 orntNew[0] = ornt[0]; 6547 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6548 orntNew[1] = -2; 6549 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6550 orntNew[2] = ornt[2]; 6551 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6552 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6553 #if 1 6554 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6555 for (p = 0; p < 3; ++p) { 6556 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6557 } 6558 #endif 6559 /* B triangle */ 6560 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6561 orntNew[0] = ornt[0]; 6562 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6563 orntNew[1] = ornt[1]; 6564 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6565 orntNew[2] = -2; 6566 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6567 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6568 #if 1 6569 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6570 for (p = 0; p < 3; ++p) { 6571 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6572 } 6573 #endif 6574 /* C triangle */ 6575 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6576 orntNew[0] = -2; 6577 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6578 orntNew[1] = ornt[1]; 6579 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6580 orntNew[2] = ornt[2]; 6581 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6582 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6583 #if 1 6584 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6585 for (p = 0; p < 3; ++p) { 6586 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6587 } 6588 #endif 6589 /* D triangle */ 6590 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6591 orntNew[0] = 0; 6592 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6593 orntNew[1] = 0; 6594 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6595 orntNew[2] = 0; 6596 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6597 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6598 #if 1 6599 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6600 for (p = 0; p < 3; ++p) { 6601 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6602 } 6603 #endif 6604 } 6605 /* 6606 2----3----3 6607 | | 6608 | B | 6609 | | 6610 0----4--- 1 6611 | | 6612 | A | 6613 | | 6614 0----2----1 6615 */ 6616 /* Hybrid cells have 4 faces */ 6617 for (c = cMax; c < cEnd; ++c) { 6618 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6619 const PetscInt *cone, *ornt; 6620 PetscInt coneNew[4], orntNew[4]; 6621 6622 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6623 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6624 /* A quad */ 6625 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6626 orntNew[0] = ornt[0]; 6627 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6628 orntNew[1] = ornt[1]; 6629 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6630 orntNew[2] = 0; 6631 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6632 orntNew[3] = 0; 6633 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6634 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6635 #if 1 6636 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6637 for (p = 0; p < 4; ++p) { 6638 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6639 } 6640 #endif 6641 /* B quad */ 6642 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6643 orntNew[0] = ornt[0]; 6644 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6645 orntNew[1] = ornt[1]; 6646 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6647 orntNew[2] = 0; 6648 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6649 orntNew[3] = 0; 6650 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6651 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6652 #if 1 6653 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6654 for (p = 0; p < 4; ++p) { 6655 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6656 } 6657 #endif 6658 } 6659 /* Interior split faces have 2 vertices and the same cells as the parent */ 6660 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6661 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6662 for (f = fStart; f < fMax; ++f) { 6663 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6664 6665 for (r = 0; r < 2; ++r) { 6666 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6667 const PetscInt *cone, *support; 6668 PetscInt coneNew[2], coneSize, c, supportSize, s; 6669 6670 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6671 coneNew[0] = vStartNew + (cone[0] - vStart); 6672 coneNew[1] = vStartNew + (cone[1] - vStart); 6673 coneNew[(r+1)%2] = newv; 6674 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6675 #if 1 6676 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6677 for (p = 0; p < 2; ++p) { 6678 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6679 } 6680 #endif 6681 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6682 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6683 for (s = 0; s < supportSize; ++s) { 6684 if (support[s] >= cMax) { 6685 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6686 } else { 6687 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6688 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6689 for (c = 0; c < coneSize; ++c) { 6690 if (cone[c] == f) break; 6691 } 6692 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6693 } 6694 } 6695 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6696 #if 1 6697 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6698 for (p = 0; p < supportSize; ++p) { 6699 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6700 } 6701 #endif 6702 } 6703 } 6704 /* Interior cell faces have 2 vertices and 2 cells */ 6705 for (c = cStart; c < cMax; ++c) { 6706 const PetscInt *cone; 6707 6708 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6709 for (r = 0; r < 3; ++r) { 6710 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6711 PetscInt coneNew[2]; 6712 PetscInt supportNew[2]; 6713 6714 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6715 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6716 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6717 #if 1 6718 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6719 for (p = 0; p < 2; ++p) { 6720 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6721 } 6722 #endif 6723 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6724 supportNew[1] = (c - cStart)*4 + 3; 6725 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6726 #if 1 6727 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6728 for (p = 0; p < 2; ++p) { 6729 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6730 } 6731 #endif 6732 } 6733 } 6734 /* Interior hybrid faces have 2 vertices and the same cells */ 6735 for (f = fMax; f < fEnd; ++f) { 6736 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6737 const PetscInt *cone; 6738 const PetscInt *support; 6739 PetscInt coneNew[2]; 6740 PetscInt supportNew[2]; 6741 PetscInt size, s, r; 6742 6743 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6744 coneNew[0] = vStartNew + (cone[0] - vStart); 6745 coneNew[1] = vStartNew + (cone[1] - vStart); 6746 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6747 #if 1 6748 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6749 for (p = 0; p < 2; ++p) { 6750 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6751 } 6752 #endif 6753 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6754 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6755 for (s = 0; s < size; ++s) { 6756 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6757 for (r = 0; r < 2; ++r) { 6758 if (cone[r+2] == f) break; 6759 } 6760 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6761 } 6762 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6763 #if 1 6764 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6765 for (p = 0; p < size; ++p) { 6766 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6767 } 6768 #endif 6769 } 6770 /* Cell hybrid faces have 2 vertices and 2 cells */ 6771 for (c = cMax; c < cEnd; ++c) { 6772 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6773 const PetscInt *cone; 6774 PetscInt coneNew[2]; 6775 PetscInt supportNew[2]; 6776 6777 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6778 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6779 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6780 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6781 #if 1 6782 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6783 for (p = 0; p < 2; ++p) { 6784 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6785 } 6786 #endif 6787 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6788 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6789 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6790 #if 1 6791 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6792 for (p = 0; p < 2; ++p) { 6793 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6794 } 6795 #endif 6796 } 6797 /* Old vertices have identical supports */ 6798 for (v = vStart; v < vEnd; ++v) { 6799 const PetscInt newp = vStartNew + (v - vStart); 6800 const PetscInt *support, *cone; 6801 PetscInt size, s; 6802 6803 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6804 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6805 for (s = 0; s < size; ++s) { 6806 if (support[s] >= fMax) { 6807 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6808 } else { 6809 PetscInt r = 0; 6810 6811 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6812 if (cone[1] == v) r = 1; 6813 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6814 } 6815 } 6816 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6817 #if 1 6818 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6819 for (p = 0; p < size; ++p) { 6820 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6821 } 6822 #endif 6823 } 6824 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6825 for (f = fStart; f < fMax; ++f) { 6826 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6827 const PetscInt *cone, *support; 6828 PetscInt size, newSize = 2, s; 6829 6830 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6831 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6832 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6833 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6834 for (s = 0; s < size; ++s) { 6835 PetscInt r = 0; 6836 6837 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6838 if (support[s] >= cMax) { 6839 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6840 6841 newSize += 1; 6842 } else { 6843 if (cone[1] == f) r = 1; 6844 else if (cone[2] == f) r = 2; 6845 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6846 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6847 6848 newSize += 2; 6849 } 6850 } 6851 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6852 #if 1 6853 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6854 for (p = 0; p < newSize; ++p) { 6855 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6856 } 6857 #endif 6858 } 6859 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6860 break; 6861 default: 6862 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6863 } 6864 PetscFunctionReturn(0); 6865 } 6866 6867 #undef __FUNCT__ 6868 #define __FUNCT__ "CellRefinerSetCoordinates" 6869 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6870 { 6871 PetscSection coordSection, coordSectionNew; 6872 Vec coordinates, coordinatesNew; 6873 PetscScalar *coords, *coordsNew; 6874 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6875 PetscErrorCode ierr; 6876 6877 PetscFunctionBegin; 6878 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6879 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6880 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6881 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6882 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6883 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6884 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6885 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6886 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6887 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6888 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6889 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6890 if (fMax < 0) fMax = fEnd; 6891 switch (refiner) { 6892 case 1: 6893 case 2: 6894 case 3: 6895 /* Simplicial and Hex 2D */ 6896 /* All vertices have the dim coordinates */ 6897 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6898 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6899 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6900 } 6901 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6902 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6903 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6904 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6905 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6906 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6907 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6908 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6909 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6910 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6911 /* Old vertices have the same coordinates */ 6912 for (v = vStart; v < vEnd; ++v) { 6913 const PetscInt newv = vStartNew + (v - vStart); 6914 PetscInt off, offnew, d; 6915 6916 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6917 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6918 for (d = 0; d < dim; ++d) { 6919 coordsNew[offnew+d] = coords[off+d]; 6920 } 6921 } 6922 /* Face vertices have the average of endpoint coordinates */ 6923 for (f = fStart; f < fMax; ++f) { 6924 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6925 const PetscInt *cone; 6926 PetscInt coneSize, offA, offB, offnew, d; 6927 6928 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6929 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6930 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6931 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6932 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6933 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6934 for (d = 0; d < dim; ++d) { 6935 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6936 } 6937 } 6938 /* Just Hex 2D */ 6939 if (refiner == 2) { 6940 /* Cell vertices have the average of corner coordinates */ 6941 for (c = cStart; c < cEnd; ++c) { 6942 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6943 PetscInt *cone = PETSC_NULL; 6944 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6945 6946 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6947 for (p = 0; p < closureSize*2; p += 2) { 6948 const PetscInt point = cone[p]; 6949 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6950 } 6951 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6952 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6953 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6954 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6955 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6956 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6957 for (d = 0; d < dim; ++d) { 6958 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6959 } 6960 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6961 } 6962 } 6963 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6964 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6965 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6966 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6967 break; 6968 default: 6969 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6970 } 6971 PetscFunctionReturn(0); 6972 } 6973 6974 #undef __FUNCT__ 6975 #define __FUNCT__ "DMPlexCreateProcessSF" 6976 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6977 { 6978 PetscInt numRoots, numLeaves, l; 6979 const PetscInt *localPoints; 6980 const PetscSFNode *remotePoints; 6981 PetscInt *localPointsNew; 6982 PetscSFNode *remotePointsNew; 6983 PetscInt *ranks, *ranksNew; 6984 PetscErrorCode ierr; 6985 6986 PetscFunctionBegin; 6987 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6988 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6989 for (l = 0; l < numLeaves; ++l) { 6990 ranks[l] = remotePoints[l].rank; 6991 } 6992 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6993 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6994 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6995 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6996 for (l = 0; l < numLeaves; ++l) { 6997 ranksNew[l] = ranks[l]; 6998 localPointsNew[l] = l; 6999 remotePointsNew[l].index = 0; 7000 remotePointsNew[l].rank = ranksNew[l]; 7001 } 7002 ierr = PetscFree(ranks);CHKERRQ(ierr); 7003 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 7004 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 7005 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 7006 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7007 PetscFunctionReturn(0); 7008 } 7009 7010 #undef __FUNCT__ 7011 #define __FUNCT__ "CellRefinerCreateSF" 7012 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7013 { 7014 PetscSF sf, sfNew, sfProcess; 7015 IS processRanks; 7016 MPI_Datatype depthType; 7017 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7018 const PetscInt *localPoints, *neighbors; 7019 const PetscSFNode *remotePoints; 7020 PetscInt *localPointsNew; 7021 PetscSFNode *remotePointsNew; 7022 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7023 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7024 PetscErrorCode ierr; 7025 7026 PetscFunctionBegin; 7027 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7028 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7029 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7030 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7031 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7032 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7033 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7034 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7035 switch (refiner) { 7036 case 3: 7037 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7038 cMax = PetscMin(cEnd, cMax); 7039 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7040 fMax = PetscMin(fEnd, fMax); 7041 } 7042 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7043 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7044 /* Caculate size of new SF */ 7045 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7046 if (numRoots < 0) PetscFunctionReturn(0); 7047 for (l = 0; l < numLeaves; ++l) { 7048 const PetscInt p = localPoints[l]; 7049 7050 switch (refiner) { 7051 case 1: 7052 /* Simplicial 2D */ 7053 if ((p >= vStart) && (p < vEnd)) { 7054 /* Old vertices stay the same */ 7055 ++numLeavesNew; 7056 } else if ((p >= fStart) && (p < fEnd)) { 7057 /* Old faces add new faces and vertex */ 7058 numLeavesNew += 1 + 2; 7059 } else if ((p >= cStart) && (p < cEnd)) { 7060 /* Old cells add new cells and interior faces */ 7061 numLeavesNew += 4 + 3; 7062 } 7063 break; 7064 case 2: 7065 /* Hex 2D */ 7066 if ((p >= vStart) && (p < vEnd)) { 7067 /* Old vertices stay the same */ 7068 ++numLeavesNew; 7069 } else if ((p >= fStart) && (p < fEnd)) { 7070 /* Old faces add new faces and vertex */ 7071 numLeavesNew += 1 + 2; 7072 } else if ((p >= cStart) && (p < cEnd)) { 7073 /* Old cells add new cells and interior faces */ 7074 numLeavesNew += 4 + 4; 7075 } 7076 break; 7077 default: 7078 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7079 } 7080 } 7081 /* Communicate depthSizes for each remote rank */ 7082 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7083 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7084 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7085 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); 7086 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7087 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7088 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7089 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7090 for (n = 0; n < numNeighbors; ++n) { 7091 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7092 } 7093 depthSizeOld[depth] = cMax; 7094 depthSizeOld[0] = vMax; 7095 depthSizeOld[depth-1] = fMax; 7096 depthSizeOld[1] = eMax; 7097 7098 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7099 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7100 7101 depthSizeOld[depth] = cEnd - cStart; 7102 depthSizeOld[0] = vEnd - vStart; 7103 depthSizeOld[depth-1] = fEnd - fStart; 7104 depthSizeOld[1] = eEnd - eStart; 7105 7106 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7107 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7108 for (n = 0; n < numNeighbors; ++n) { 7109 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7110 } 7111 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7112 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7113 /* Calculate new point SF */ 7114 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7115 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7116 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7117 for (l = 0, m = 0; l < numLeaves; ++l) { 7118 PetscInt p = localPoints[l]; 7119 PetscInt rp = remotePoints[l].index, n; 7120 PetscMPIInt rrank = remotePoints[l].rank; 7121 7122 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7123 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7124 switch (refiner) { 7125 case 1: 7126 /* Simplicial 2D */ 7127 if ((p >= vStart) && (p < vEnd)) { 7128 /* Old vertices stay the same */ 7129 localPointsNew[m] = vStartNew + (p - vStart); 7130 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7131 remotePointsNew[m].rank = rrank; 7132 ++m; 7133 } else if ((p >= fStart) && (p < fEnd)) { 7134 /* Old faces add new faces and vertex */ 7135 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7136 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7137 remotePointsNew[m].rank = rrank; 7138 ++m; 7139 for (r = 0; r < 2; ++r, ++m) { 7140 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7141 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7142 remotePointsNew[m].rank = rrank; 7143 } 7144 } else if ((p >= cStart) && (p < cEnd)) { 7145 /* Old cells add new cells and interior faces */ 7146 for (r = 0; r < 4; ++r, ++m) { 7147 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7148 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7149 remotePointsNew[m].rank = rrank; 7150 } 7151 for (r = 0; r < 3; ++r, ++m) { 7152 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7153 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7154 remotePointsNew[m].rank = rrank; 7155 } 7156 } 7157 break; 7158 case 2: 7159 /* Hex 2D */ 7160 if ((p >= vStart) && (p < vEnd)) { 7161 /* Old vertices stay the same */ 7162 localPointsNew[m] = vStartNew + (p - vStart); 7163 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7164 remotePointsNew[m].rank = rrank; 7165 ++m; 7166 } else if ((p >= fStart) && (p < fEnd)) { 7167 /* Old faces add new faces and vertex */ 7168 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7169 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7170 remotePointsNew[m].rank = rrank; 7171 ++m; 7172 for (r = 0; r < 2; ++r, ++m) { 7173 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7174 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7175 remotePointsNew[m].rank = rrank; 7176 } 7177 } else if ((p >= cStart) && (p < cEnd)) { 7178 /* Old cells add new cells and interior faces */ 7179 for (r = 0; r < 4; ++r, ++m) { 7180 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7181 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7182 remotePointsNew[m].rank = rrank; 7183 } 7184 for (r = 0; r < 4; ++r, ++m) { 7185 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7186 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7187 remotePointsNew[m].rank = rrank; 7188 } 7189 } 7190 break; 7191 case 3: 7192 /* Hybrid simplicial 2D */ 7193 if ((p >= vStart) && (p < vEnd)) { 7194 /* Old vertices stay the same */ 7195 localPointsNew[m] = vStartNew + (p - vStart); 7196 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7197 remotePointsNew[m].rank = rrank; 7198 ++m; 7199 } else if ((p >= fStart) && (p < fMax)) { 7200 /* Old interior faces add new faces and vertex */ 7201 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7202 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7203 remotePointsNew[m].rank = rrank; 7204 ++m; 7205 for (r = 0; r < 2; ++r, ++m) { 7206 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7207 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7208 remotePointsNew[m].rank = rrank; 7209 } 7210 } else if ((p >= fMax) && (p < fEnd)) { 7211 /* Old hybrid faces stay the same */ 7212 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7213 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7214 remotePointsNew[m].rank = rrank; 7215 ++m; 7216 } else if ((p >= cStart) && (p < cMax)) { 7217 /* Old interior cells add new cells and interior faces */ 7218 for (r = 0; r < 4; ++r, ++m) { 7219 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7220 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7221 remotePointsNew[m].rank = rrank; 7222 } 7223 for (r = 0; r < 3; ++r, ++m) { 7224 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7225 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7226 remotePointsNew[m].rank = rrank; 7227 } 7228 } else if ((p >= cStart) && (p < cMax)) { 7229 /* Old hybrid cells add new cells and hybrid face */ 7230 for (r = 0; r < 2; ++r, ++m) { 7231 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7232 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7233 remotePointsNew[m].rank = rrank; 7234 } 7235 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7236 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]); 7237 remotePointsNew[m].rank = rrank; 7238 ++m; 7239 } 7240 break; 7241 default: 7242 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7243 } 7244 } 7245 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7246 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7247 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7248 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7249 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7250 PetscFunctionReturn(0); 7251 } 7252 7253 #undef __FUNCT__ 7254 #define __FUNCT__ "CellRefinerCreateLabels" 7255 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7256 { 7257 PetscInt numLabels, l; 7258 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7259 PetscErrorCode ierr; 7260 7261 PetscFunctionBegin; 7262 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7263 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7264 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7265 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7266 7267 cStartNew = 0; 7268 vStartNew = depthSize[2]; 7269 fStartNew = depthSize[2] + depthSize[0]; 7270 7271 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7272 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7273 switch (refiner) { 7274 case 3: 7275 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7276 cMax = PetscMin(cEnd, cMax); 7277 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7278 fMax = PetscMin(fEnd, fMax); 7279 } 7280 for (l = 0; l < numLabels; ++l) { 7281 DMLabel label, labelNew; 7282 const char *lname; 7283 PetscBool isDepth; 7284 IS valueIS; 7285 const PetscInt *values; 7286 PetscInt numValues, val; 7287 7288 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7289 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7290 if (isDepth) continue; 7291 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7292 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7293 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7294 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7295 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7296 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7297 for (val = 0; val < numValues; ++val) { 7298 IS pointIS; 7299 const PetscInt *points; 7300 PetscInt numPoints, n; 7301 7302 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7303 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7304 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7305 for (n = 0; n < numPoints; ++n) { 7306 const PetscInt p = points[n]; 7307 switch (refiner) { 7308 case 1: 7309 /* Simplicial 2D */ 7310 if ((p >= vStart) && (p < vEnd)) { 7311 /* Old vertices stay the same */ 7312 newp = vStartNew + (p - vStart); 7313 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7314 } else if ((p >= fStart) && (p < fEnd)) { 7315 /* Old faces add new faces and vertex */ 7316 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7317 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7318 for (r = 0; r < 2; ++r) { 7319 newp = fStartNew + (p - fStart)*2 + r; 7320 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7321 } 7322 } else if ((p >= cStart) && (p < cEnd)) { 7323 /* Old cells add new cells and interior faces */ 7324 for (r = 0; r < 4; ++r) { 7325 newp = cStartNew + (p - cStart)*4 + r; 7326 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7327 } 7328 for (r = 0; r < 3; ++r) { 7329 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7330 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7331 } 7332 } 7333 break; 7334 case 2: 7335 /* Hex 2D */ 7336 if ((p >= vStart) && (p < vEnd)) { 7337 /* Old vertices stay the same */ 7338 newp = vStartNew + (p - vStart); 7339 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7340 } else if ((p >= fStart) && (p < fEnd)) { 7341 /* Old faces add new faces and vertex */ 7342 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7343 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7344 for (r = 0; r < 2; ++r) { 7345 newp = fStartNew + (p - fStart)*2 + r; 7346 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7347 } 7348 } else if ((p >= cStart) && (p < cEnd)) { 7349 /* Old cells add new cells and interior faces and vertex */ 7350 for (r = 0; r < 4; ++r) { 7351 newp = cStartNew + (p - cStart)*4 + r; 7352 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7353 } 7354 for (r = 0; r < 4; ++r) { 7355 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7356 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7357 } 7358 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7359 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7360 } 7361 break; 7362 case 3: 7363 /* Hybrid simplicial 2D */ 7364 if ((p >= vStart) && (p < vEnd)) { 7365 /* Old vertices stay the same */ 7366 newp = vStartNew + (p - vStart); 7367 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7368 } else if ((p >= fStart) && (p < fMax)) { 7369 /* Old interior faces add new faces and vertex */ 7370 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7371 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7372 for (r = 0; r < 2; ++r) { 7373 newp = fStartNew + (p - fStart)*2 + r; 7374 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7375 } 7376 } else if ((p >= fMax) && (p < fEnd)) { 7377 /* Old hybrid faces stay the same */ 7378 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7379 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7380 } else if ((p >= cStart) && (p < cMax)) { 7381 /* Old interior cells add new cells and interior faces */ 7382 for (r = 0; r < 4; ++r) { 7383 newp = cStartNew + (p - cStart)*4 + r; 7384 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7385 } 7386 for (r = 0; r < 3; ++r) { 7387 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7388 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7389 } 7390 } else if ((p >= cMax) && (p < cEnd)) { 7391 /* Old hybrid cells add new cells and hybrid face */ 7392 for (r = 0; r < 2; ++r) { 7393 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7394 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7395 } 7396 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7397 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7398 } 7399 break; 7400 default: 7401 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7402 } 7403 } 7404 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7405 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7406 } 7407 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7408 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7409 if (0) { 7410 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7411 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7412 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7413 } 7414 } 7415 PetscFunctionReturn(0); 7416 } 7417 7418 #undef __FUNCT__ 7419 #define __FUNCT__ "DMPlexRefine_Uniform" 7420 /* This will only work for interpolated meshes */ 7421 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7422 { 7423 DM rdm; 7424 PetscInt *depthSize; 7425 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7426 PetscErrorCode ierr; 7427 7428 PetscFunctionBegin; 7429 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7430 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7431 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7432 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7433 /* Calculate number of new points of each depth */ 7434 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7435 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7436 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7437 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7438 /* Step 1: Set chart */ 7439 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7440 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7441 /* Step 2: Set cone/support sizes */ 7442 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7443 /* Step 3: Setup refined DM */ 7444 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7445 /* Step 4: Set cones and supports */ 7446 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7447 /* Step 5: Stratify */ 7448 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7449 /* Step 6: Set coordinates for vertices */ 7450 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7451 /* Step 7: Create pointSF */ 7452 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7453 /* Step 8: Create labels */ 7454 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7455 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7456 7457 *dmRefined = rdm; 7458 PetscFunctionReturn(0); 7459 } 7460 7461 #undef __FUNCT__ 7462 #define __FUNCT__ "DMPlexSetRefinementUniform" 7463 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7464 { 7465 DM_Plex *mesh = (DM_Plex*) dm->data; 7466 7467 PetscFunctionBegin; 7468 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7469 mesh->refinementUniform = refinementUniform; 7470 PetscFunctionReturn(0); 7471 } 7472 7473 #undef __FUNCT__ 7474 #define __FUNCT__ "DMPlexGetRefinementUniform" 7475 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7476 { 7477 DM_Plex *mesh = (DM_Plex*) dm->data; 7478 7479 PetscFunctionBegin; 7480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7481 PetscValidPointer(refinementUniform, 2); 7482 *refinementUniform = mesh->refinementUniform; 7483 PetscFunctionReturn(0); 7484 } 7485 7486 #undef __FUNCT__ 7487 #define __FUNCT__ "DMPlexSetRefinementLimit" 7488 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7489 { 7490 DM_Plex *mesh = (DM_Plex*) dm->data; 7491 7492 PetscFunctionBegin; 7493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7494 mesh->refinementLimit = refinementLimit; 7495 PetscFunctionReturn(0); 7496 } 7497 7498 #undef __FUNCT__ 7499 #define __FUNCT__ "DMPlexGetRefinementLimit" 7500 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7501 { 7502 DM_Plex *mesh = (DM_Plex*) dm->data; 7503 7504 PetscFunctionBegin; 7505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7506 PetscValidPointer(refinementLimit, 2); 7507 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7508 *refinementLimit = mesh->refinementLimit; 7509 PetscFunctionReturn(0); 7510 } 7511 7512 #undef __FUNCT__ 7513 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7514 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7515 { 7516 PetscInt dim, cStart, coneSize, cMax; 7517 PetscErrorCode ierr; 7518 7519 PetscFunctionBegin; 7520 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7521 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7522 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7523 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7524 switch (dim) { 7525 case 2: 7526 switch (coneSize) { 7527 case 3: 7528 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7529 else *cellRefiner = 1; /* Triangular */ 7530 break; 7531 case 4: 7532 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7533 else *cellRefiner = 2; /* Quadrilateral */ 7534 break; 7535 default: 7536 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7537 } 7538 break; 7539 default: 7540 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7541 } 7542 PetscFunctionReturn(0); 7543 } 7544 7545 #undef __FUNCT__ 7546 #define __FUNCT__ "DMRefine_Plex" 7547 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7548 { 7549 PetscReal refinementLimit; 7550 PetscInt dim, cStart, cEnd; 7551 char genname[1024], *name = PETSC_NULL; 7552 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7553 PetscErrorCode ierr; 7554 7555 PetscFunctionBegin; 7556 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7557 if (isUniform) { 7558 CellRefiner cellRefiner; 7559 7560 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7561 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7562 PetscFunctionReturn(0); 7563 } 7564 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7565 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7566 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7567 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7568 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7569 if (flg) name = genname; 7570 if (name) { 7571 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7572 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7573 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7574 } 7575 switch (dim) { 7576 case 2: 7577 if (!name || isTriangle) { 7578 #if defined(PETSC_HAVE_TRIANGLE) 7579 double *maxVolumes; 7580 PetscInt c; 7581 7582 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7583 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7584 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7585 #else 7586 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7587 #endif 7588 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7589 break; 7590 case 3: 7591 if (!name || isCTetgen) { 7592 #if defined(PETSC_HAVE_CTETGEN) 7593 PetscReal *maxVolumes; 7594 PetscInt c; 7595 7596 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7597 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7598 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7599 #else 7600 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7601 #endif 7602 } else if (isTetgen) { 7603 #if defined(PETSC_HAVE_TETGEN) 7604 double *maxVolumes; 7605 PetscInt c; 7606 7607 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7608 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7609 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7610 #else 7611 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7612 #endif 7613 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7614 break; 7615 default: 7616 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7617 } 7618 PetscFunctionReturn(0); 7619 } 7620 7621 #undef __FUNCT__ 7622 #define __FUNCT__ "DMPlexGetDepth" 7623 /*@ 7624 DMPlexGetDepth - get the number of strata 7625 7626 Not Collective 7627 7628 Input Parameters: 7629 . dm - The DMPlex object 7630 7631 Output Parameters: 7632 . depth - number of strata 7633 7634 Level: developer 7635 7636 Notes: 7637 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7638 7639 .keywords: mesh, points 7640 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7641 @*/ 7642 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7643 { 7644 PetscInt d; 7645 PetscErrorCode ierr; 7646 7647 PetscFunctionBegin; 7648 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7649 PetscValidPointer(depth, 2); 7650 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7651 *depth = d-1; 7652 PetscFunctionReturn(0); 7653 } 7654 7655 #undef __FUNCT__ 7656 #define __FUNCT__ "DMPlexGetDepthStratum" 7657 /*@ 7658 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7659 7660 Not Collective 7661 7662 Input Parameters: 7663 + dm - The DMPlex object 7664 - stratumValue - The requested depth 7665 7666 Output Parameters: 7667 + start - The first point at this depth 7668 - end - One beyond the last point at this depth 7669 7670 Level: developer 7671 7672 .keywords: mesh, points 7673 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7674 @*/ 7675 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7676 { 7677 DM_Plex *mesh = (DM_Plex*) dm->data; 7678 DMLabel next = mesh->labels; 7679 PetscBool flg = PETSC_FALSE; 7680 PetscInt depth; 7681 PetscErrorCode ierr; 7682 7683 PetscFunctionBegin; 7684 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7685 if (stratumValue < 0) { 7686 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7687 PetscFunctionReturn(0); 7688 } else { 7689 PetscInt pStart, pEnd; 7690 7691 if (start) *start = 0; 7692 if (end) *end = 0; 7693 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7694 if (pStart == pEnd) PetscFunctionReturn(0); 7695 } 7696 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7697 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7698 /* We should have a generic GetLabel() and a Label class */ 7699 while (next) { 7700 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7701 if (flg) break; 7702 next = next->next; 7703 } 7704 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7705 depth = stratumValue; 7706 if ((depth < 0) || (depth >= next->numStrata)) { 7707 if (start) *start = 0; 7708 if (end) *end = 0; 7709 } else { 7710 if (start) *start = next->points[next->stratumOffsets[depth]]; 7711 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7712 } 7713 PetscFunctionReturn(0); 7714 } 7715 7716 #undef __FUNCT__ 7717 #define __FUNCT__ "DMPlexGetHeightStratum" 7718 /*@ 7719 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7720 7721 Not Collective 7722 7723 Input Parameters: 7724 + dm - The DMPlex object 7725 - stratumValue - The requested height 7726 7727 Output Parameters: 7728 + start - The first point at this height 7729 - end - One beyond the last point at this height 7730 7731 Level: developer 7732 7733 .keywords: mesh, points 7734 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7735 @*/ 7736 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7737 { 7738 DM_Plex *mesh = (DM_Plex*) dm->data; 7739 DMLabel next = mesh->labels; 7740 PetscBool flg = PETSC_FALSE; 7741 PetscInt depth; 7742 PetscErrorCode ierr; 7743 7744 PetscFunctionBegin; 7745 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7746 if (stratumValue < 0) { 7747 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7748 } else { 7749 PetscInt pStart, pEnd; 7750 7751 if (start) *start = 0; 7752 if (end) *end = 0; 7753 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7754 if (pStart == pEnd) PetscFunctionReturn(0); 7755 } 7756 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7757 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7758 /* We should have a generic GetLabel() and a Label class */ 7759 while (next) { 7760 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7761 if (flg) break; 7762 next = next->next; 7763 } 7764 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7765 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7766 if ((depth < 0) || (depth >= next->numStrata)) { 7767 if (start) *start = 0; 7768 if (end) *end = 0; 7769 } else { 7770 if (start) *start = next->points[next->stratumOffsets[depth]]; 7771 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7772 } 7773 PetscFunctionReturn(0); 7774 } 7775 7776 #undef __FUNCT__ 7777 #define __FUNCT__ "DMPlexCreateSectionInitial" 7778 /* Set the number of dof on each point and separate by fields */ 7779 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7780 { 7781 PetscInt *numDofTot; 7782 PetscInt pStart = 0, pEnd = 0; 7783 PetscInt p, d, f; 7784 PetscErrorCode ierr; 7785 7786 PetscFunctionBegin; 7787 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7788 for (d = 0; d <= dim; ++d) { 7789 numDofTot[d] = 0; 7790 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7791 } 7792 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7793 if (numFields > 0) { 7794 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7795 if (numComp) { 7796 for (f = 0; f < numFields; ++f) { 7797 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7798 } 7799 } 7800 } 7801 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7802 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7803 for (d = 0; d <= dim; ++d) { 7804 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7805 for (p = pStart; p < pEnd; ++p) { 7806 for (f = 0; f < numFields; ++f) { 7807 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7808 } 7809 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7810 } 7811 } 7812 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7813 PetscFunctionReturn(0); 7814 } 7815 7816 #undef __FUNCT__ 7817 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7818 /* Set the number of dof on each point and separate by fields 7819 If constDof is PETSC_DETERMINE, constrain every dof on the point 7820 */ 7821 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7822 { 7823 PetscInt numFields; 7824 PetscInt bc; 7825 PetscErrorCode ierr; 7826 7827 PetscFunctionBegin; 7828 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7829 for (bc = 0; bc < numBC; ++bc) { 7830 PetscInt field = 0; 7831 const PetscInt *idx; 7832 PetscInt n, i; 7833 7834 if (numFields) field = bcField[bc]; 7835 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7836 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7837 for (i = 0; i < n; ++i) { 7838 const PetscInt p = idx[i]; 7839 PetscInt numConst = constDof; 7840 7841 /* Constrain every dof on the point */ 7842 if (numConst < 0) { 7843 if (numFields) { 7844 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7845 } else { 7846 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7847 } 7848 } 7849 if (numFields) { 7850 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7851 } 7852 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7853 } 7854 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7855 } 7856 PetscFunctionReturn(0); 7857 } 7858 7859 #undef __FUNCT__ 7860 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7861 /* Set the constrained indices on each point and separate by fields */ 7862 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7863 { 7864 PetscInt *maxConstraints; 7865 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7866 PetscErrorCode ierr; 7867 7868 PetscFunctionBegin; 7869 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7870 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7871 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7872 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7873 for (p = pStart; p < pEnd; ++p) { 7874 PetscInt cdof; 7875 7876 if (numFields) { 7877 for (f = 0; f < numFields; ++f) { 7878 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7879 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7880 } 7881 } else { 7882 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7883 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7884 } 7885 } 7886 for (f = 0; f < numFields; ++f) { 7887 maxConstraints[numFields] += maxConstraints[f]; 7888 } 7889 if (maxConstraints[numFields]) { 7890 PetscInt *indices; 7891 7892 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7893 for (p = pStart; p < pEnd; ++p) { 7894 PetscInt cdof, d; 7895 7896 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7897 if (cdof) { 7898 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7899 if (numFields) { 7900 PetscInt numConst = 0, foff = 0; 7901 7902 for (f = 0; f < numFields; ++f) { 7903 PetscInt cfdof, fdof; 7904 7905 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7906 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7907 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7908 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7909 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7910 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7911 numConst += cfdof; 7912 foff += fdof; 7913 } 7914 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7915 } else { 7916 for (d = 0; d < cdof; ++d) indices[d] = d; 7917 } 7918 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7919 } 7920 } 7921 ierr = PetscFree(indices);CHKERRQ(ierr); 7922 } 7923 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7924 PetscFunctionReturn(0); 7925 } 7926 7927 #undef __FUNCT__ 7928 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7929 /* Set the constrained field indices on each point */ 7930 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7931 { 7932 const PetscInt *points, *indices; 7933 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7934 PetscErrorCode ierr; 7935 7936 PetscFunctionBegin; 7937 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7938 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7939 7940 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7941 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7942 if (!constraintIndices) { 7943 PetscInt *idx, i; 7944 7945 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7946 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7947 for (i = 0; i < maxDof; ++i) idx[i] = i; 7948 for (p = 0; p < numPoints; ++p) { 7949 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7950 } 7951 ierr = PetscFree(idx);CHKERRQ(ierr); 7952 } else { 7953 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7954 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7955 for (p = 0; p < numPoints; ++p) { 7956 PetscInt fcdof; 7957 7958 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7959 if (fcdof != numConstraints) SETERRQ4(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 7960 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7961 } 7962 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7963 } 7964 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7965 PetscFunctionReturn(0); 7966 } 7967 7968 #undef __FUNCT__ 7969 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7970 /* Set the constrained indices on each point and separate by fields */ 7971 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7972 { 7973 PetscInt *indices; 7974 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7975 PetscErrorCode ierr; 7976 7977 PetscFunctionBegin; 7978 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7979 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7980 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7981 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7982 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7983 for (p = pStart; p < pEnd; ++p) { 7984 PetscInt cdof, d; 7985 7986 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7987 if (cdof) { 7988 PetscInt numConst = 0, foff = 0; 7989 7990 for (f = 0; f < numFields; ++f) { 7991 const PetscInt *fcind; 7992 PetscInt fdof, fcdof; 7993 7994 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7995 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7996 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7997 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7998 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7999 foff += fdof; 8000 numConst += fcdof; 8001 } 8002 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8003 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8004 } 8005 } 8006 ierr = PetscFree(indices);CHKERRQ(ierr); 8007 PetscFunctionReturn(0); 8008 } 8009 8010 #undef __FUNCT__ 8011 #define __FUNCT__ "DMPlexCreateSection" 8012 /*@C 8013 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8014 8015 Not Collective 8016 8017 Input Parameters: 8018 + dm - The DMPlex object 8019 . dim - The spatial dimension of the problem 8020 . numFields - The number of fields in the problem 8021 . numComp - An array of size numFields that holds the number of components for each field 8022 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8023 . numBC - The number of boundary conditions 8024 . bcField - An array of size numBC giving the field number for each boundry condition 8025 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8026 8027 Output Parameter: 8028 . section - The PetscSection object 8029 8030 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 8031 nubmer of dof for field 0 on each edge. 8032 8033 Level: developer 8034 8035 .keywords: mesh, elements 8036 .seealso: DMPlexCreate(), PetscSectionCreate() 8037 @*/ 8038 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8039 { 8040 PetscErrorCode ierr; 8041 8042 PetscFunctionBegin; 8043 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8044 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8045 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8046 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8047 { 8048 PetscBool view = PETSC_FALSE; 8049 8050 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8051 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8052 } 8053 PetscFunctionReturn(0); 8054 } 8055 8056 #undef __FUNCT__ 8057 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8058 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8059 { 8060 PetscSection section; 8061 PetscErrorCode ierr; 8062 8063 PetscFunctionBegin; 8064 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8065 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8066 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8067 PetscFunctionReturn(0); 8068 } 8069 8070 #undef __FUNCT__ 8071 #define __FUNCT__ "DMPlexGetCoordinateSection" 8072 /*@ 8073 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8074 8075 Not Collective 8076 8077 Input Parameter: 8078 . dm - The DMPlex object 8079 8080 Output Parameter: 8081 . section - The PetscSection object 8082 8083 Level: intermediate 8084 8085 .keywords: mesh, coordinates 8086 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8087 @*/ 8088 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8089 { 8090 DM cdm; 8091 PetscErrorCode ierr; 8092 8093 PetscFunctionBegin; 8094 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8095 PetscValidPointer(section, 2); 8096 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8097 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8098 PetscFunctionReturn(0); 8099 } 8100 8101 #undef __FUNCT__ 8102 #define __FUNCT__ "DMPlexSetCoordinateSection" 8103 /*@ 8104 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8105 8106 Not Collective 8107 8108 Input Parameters: 8109 + dm - The DMPlex object 8110 - section - The PetscSection object 8111 8112 Level: intermediate 8113 8114 .keywords: mesh, coordinates 8115 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8116 @*/ 8117 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8118 { 8119 DM cdm; 8120 PetscErrorCode ierr; 8121 8122 PetscFunctionBegin; 8123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8125 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8126 PetscFunctionReturn(0); 8127 } 8128 8129 #undef __FUNCT__ 8130 #define __FUNCT__ "DMPlexGetConeSection" 8131 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8132 { 8133 DM_Plex *mesh = (DM_Plex*) dm->data; 8134 8135 PetscFunctionBegin; 8136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8137 if (section) *section = mesh->coneSection; 8138 PetscFunctionReturn(0); 8139 } 8140 8141 #undef __FUNCT__ 8142 #define __FUNCT__ "DMPlexGetCones" 8143 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8144 { 8145 DM_Plex *mesh = (DM_Plex*) dm->data; 8146 8147 PetscFunctionBegin; 8148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8149 if (cones) *cones = mesh->cones; 8150 PetscFunctionReturn(0); 8151 } 8152 8153 #undef __FUNCT__ 8154 #define __FUNCT__ "DMPlexGetConeOrientations" 8155 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8156 { 8157 DM_Plex *mesh = (DM_Plex*) dm->data; 8158 8159 PetscFunctionBegin; 8160 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8161 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8162 PetscFunctionReturn(0); 8163 } 8164 8165 #undef __FUNCT__ 8166 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8167 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8168 { 8169 const PetscInt embedDim = 2; 8170 PetscReal x = PetscRealPart(point[0]); 8171 PetscReal y = PetscRealPart(point[1]); 8172 PetscReal v0[2], J[4], invJ[4], detJ; 8173 PetscReal xi, eta; 8174 PetscErrorCode ierr; 8175 8176 PetscFunctionBegin; 8177 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8178 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8179 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8180 8181 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8182 else *cell = -1; 8183 PetscFunctionReturn(0); 8184 } 8185 8186 #undef __FUNCT__ 8187 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8188 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8189 { 8190 PetscSection coordSection; 8191 Vec coordsLocal; 8192 const PetscScalar *coords; 8193 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8194 PetscReal x = PetscRealPart(point[0]); 8195 PetscReal y = PetscRealPart(point[1]); 8196 PetscInt crossings = 0, f; 8197 PetscErrorCode ierr; 8198 8199 PetscFunctionBegin; 8200 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8201 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8202 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8203 for (f = 0; f < 4; ++f) { 8204 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8205 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8206 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8207 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8208 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8209 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8210 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8211 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8212 if ((cond1 || cond2) && above) ++crossings; 8213 } 8214 if (crossings % 2) *cell = c; 8215 else *cell = -1; 8216 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8217 PetscFunctionReturn(0); 8218 } 8219 8220 #undef __FUNCT__ 8221 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8222 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8223 { 8224 const PetscInt embedDim = 3; 8225 PetscReal v0[3], J[9], invJ[9], detJ; 8226 PetscReal x = PetscRealPart(point[0]); 8227 PetscReal y = PetscRealPart(point[1]); 8228 PetscReal z = PetscRealPart(point[2]); 8229 PetscReal xi, eta, zeta; 8230 PetscErrorCode ierr; 8231 8232 PetscFunctionBegin; 8233 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8234 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8235 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8236 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8237 8238 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8239 else *cell = -1; 8240 PetscFunctionReturn(0); 8241 } 8242 8243 #undef __FUNCT__ 8244 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8245 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8246 { 8247 PetscSection coordSection; 8248 Vec coordsLocal; 8249 const PetscScalar *coords; 8250 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8251 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8252 PetscBool found = PETSC_TRUE; 8253 PetscInt f; 8254 PetscErrorCode ierr; 8255 8256 PetscFunctionBegin; 8257 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8258 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8259 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8260 for (f = 0; f < 6; ++f) { 8261 /* Check the point is under plane */ 8262 /* Get face normal */ 8263 PetscReal v_i[3]; 8264 PetscReal v_j[3]; 8265 PetscReal normal[3]; 8266 PetscReal pp[3]; 8267 PetscReal dot; 8268 8269 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8270 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8271 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8272 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8273 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8274 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8275 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8276 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8277 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8278 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8279 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8280 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8281 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8282 8283 /* Check that projected point is in face (2D location problem) */ 8284 if (dot < 0.0) { 8285 found = PETSC_FALSE; 8286 break; 8287 } 8288 } 8289 if (found) *cell = c; 8290 else *cell = -1; 8291 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8292 PetscFunctionReturn(0); 8293 } 8294 8295 #undef __FUNCT__ 8296 #define __FUNCT__ "DMLocatePoints_Plex" 8297 /* 8298 Need to implement using the guess 8299 */ 8300 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8301 { 8302 PetscInt cell = -1 /*, guess = -1*/; 8303 PetscInt bs, numPoints, p; 8304 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8305 PetscInt *cells; 8306 PetscScalar *a; 8307 PetscErrorCode ierr; 8308 8309 PetscFunctionBegin; 8310 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8311 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8312 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8313 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8314 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8315 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8316 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8317 if (bs != dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 8318 numPoints /= bs; 8319 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8320 for (p = 0; p < numPoints; ++p) { 8321 const PetscScalar *point = &a[p*bs]; 8322 8323 switch (dim) { 8324 case 2: 8325 for (c = cStart; c < cEnd; ++c) { 8326 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8327 switch (coneSize) { 8328 case 3: 8329 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8330 break; 8331 case 4: 8332 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8333 break; 8334 default: 8335 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8336 } 8337 if (cell >= 0) break; 8338 } 8339 break; 8340 case 3: 8341 for (c = cStart; c < cEnd; ++c) { 8342 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8343 switch (coneSize) { 8344 case 4: 8345 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8346 break; 8347 case 8: 8348 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8349 break; 8350 default: 8351 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8352 } 8353 if (cell >= 0) break; 8354 } 8355 break; 8356 default: 8357 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8358 } 8359 cells[p] = cell; 8360 } 8361 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8362 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8363 PetscFunctionReturn(0); 8364 } 8365 8366 /******************************** FEM Support **********************************/ 8367 8368 #undef __FUNCT__ 8369 #define __FUNCT__ "DMPlexVecGetClosure" 8370 /*@C 8371 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8372 8373 Not collective 8374 8375 Input Parameters: 8376 + dm - The DM 8377 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8378 . v - The local vector 8379 - point - The sieve point in the DM 8380 8381 Output Parameters: 8382 + csize - The number of values in the closure, or PETSC_NULL 8383 - values - The array of values, which is a borrowed array and should not be freed 8384 8385 Level: intermediate 8386 8387 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8388 @*/ 8389 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8390 { 8391 PetscScalar *array, *vArray; 8392 PetscInt *points = PETSC_NULL; 8393 PetscInt offsets[32]; 8394 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8395 PetscErrorCode ierr; 8396 8397 PetscFunctionBegin; 8398 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8399 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8400 if (!section) { 8401 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8402 } 8403 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8404 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8405 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8406 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8407 /* Compress out points not in the section */ 8408 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8409 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8410 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8411 points[q*2] = points[p]; 8412 points[q*2+1] = points[p+1]; 8413 ++q; 8414 } 8415 } 8416 numPoints = q; 8417 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8418 PetscInt dof, fdof; 8419 8420 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8421 for (f = 0; f < numFields; ++f) { 8422 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8423 offsets[f+1] += fdof; 8424 } 8425 size += dof; 8426 } 8427 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8428 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8429 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8430 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8431 for (p = 0; p < numPoints*2; p += 2) { 8432 PetscInt o = points[p+1]; 8433 PetscInt dof, off, d; 8434 PetscScalar *varr; 8435 8436 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8437 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8438 varr = &vArray[off]; 8439 if (numFields) { 8440 PetscInt fdof, foff, fcomp, f, c; 8441 8442 for (f = 0, foff = 0; f < numFields; ++f) { 8443 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8444 if (o >= 0) { 8445 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8446 array[offsets[f]] = varr[foff+d]; 8447 } 8448 } else { 8449 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8450 for (d = fdof/fcomp-1; d >= 0; --d) { 8451 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8452 array[offsets[f]] = varr[foff+d*fcomp+c]; 8453 } 8454 } 8455 } 8456 foff += fdof; 8457 } 8458 } else { 8459 if (o >= 0) { 8460 for (d = 0; d < dof; ++d, ++offsets[0]) { 8461 array[offsets[0]] = varr[d]; 8462 } 8463 } else { 8464 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8465 array[offsets[0]] = varr[d]; 8466 } 8467 } 8468 } 8469 } 8470 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8471 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8472 if (csize) *csize = size; 8473 *values = array; 8474 PetscFunctionReturn(0); 8475 } 8476 8477 #undef __FUNCT__ 8478 #define __FUNCT__ "DMPlexVecRestoreClosure" 8479 /*@C 8480 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8481 8482 Not collective 8483 8484 Input Parameters: 8485 + dm - The DM 8486 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8487 . v - The local vector 8488 . point - The sieve point in the DM 8489 . csize - The number of values in the closure, or PETSC_NULL 8490 - values - The array of values, which is a borrowed array and should not be freed 8491 8492 Level: intermediate 8493 8494 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8495 @*/ 8496 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8497 { 8498 PetscInt size = 0; 8499 PetscErrorCode ierr; 8500 8501 PetscFunctionBegin; 8502 /* Should work without recalculating size */ 8503 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8504 PetscFunctionReturn(0); 8505 } 8506 8507 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8508 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8509 8510 #undef __FUNCT__ 8511 #define __FUNCT__ "updatePoint_private" 8512 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8513 { 8514 PetscInt cdof; /* The number of constraints on this point */ 8515 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8516 PetscScalar *a; 8517 PetscInt off, cind = 0, k; 8518 PetscErrorCode ierr; 8519 8520 PetscFunctionBegin; 8521 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8522 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8523 a = &array[off]; 8524 if (!cdof || setBC) { 8525 if (orientation >= 0) { 8526 for (k = 0; k < dof; ++k) { 8527 fuse(&a[k], values[k]); 8528 } 8529 } else { 8530 for (k = 0; k < dof; ++k) { 8531 fuse(&a[k], values[dof-k-1]); 8532 } 8533 } 8534 } else { 8535 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8536 if (orientation >= 0) { 8537 for (k = 0; k < dof; ++k) { 8538 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8539 fuse(&a[k], values[k]); 8540 } 8541 } else { 8542 for (k = 0; k < dof; ++k) { 8543 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8544 fuse(&a[k], values[dof-k-1]); 8545 } 8546 } 8547 } 8548 PetscFunctionReturn(0); 8549 } 8550 8551 #undef __FUNCT__ 8552 #define __FUNCT__ "updatePointFields_private" 8553 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8554 { 8555 PetscScalar *a; 8556 PetscInt numFields, off, foff, f; 8557 PetscErrorCode ierr; 8558 8559 PetscFunctionBegin; 8560 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8561 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8562 a = &array[off]; 8563 for (f = 0, foff = 0; f < numFields; ++f) { 8564 PetscInt fdof, fcomp, fcdof; 8565 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8566 PetscInt cind = 0, k, c; 8567 8568 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8569 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8570 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8571 if (!fcdof || setBC) { 8572 if (orientation >= 0) { 8573 for (k = 0; k < fdof; ++k) { 8574 fuse(&a[foff+k], values[foffs[f]+k]); 8575 } 8576 } else { 8577 for (k = fdof/fcomp-1; k >= 0; --k) { 8578 for (c = 0; c < fcomp; ++c) { 8579 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8580 } 8581 } 8582 } 8583 } else { 8584 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8585 if (orientation >= 0) { 8586 for (k = 0; k < fdof; ++k) { 8587 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8588 fuse(&a[foff+k], values[foffs[f]+k]); 8589 } 8590 } else { 8591 for (k = fdof/fcomp-1; k >= 0; --k) { 8592 for (c = 0; c < fcomp; ++c) { 8593 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8594 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8595 } 8596 } 8597 } 8598 } 8599 foff += fdof; 8600 foffs[f] += fdof; 8601 } 8602 PetscFunctionReturn(0); 8603 } 8604 8605 #undef __FUNCT__ 8606 #define __FUNCT__ "DMPlexVecSetClosure" 8607 /*@C 8608 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8609 8610 Not collective 8611 8612 Input Parameters: 8613 + dm - The DM 8614 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8615 . v - The local vector 8616 . point - The sieve point in the DM 8617 . values - The array of values, which is a borrowed array and should not be freed 8618 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8619 8620 Level: intermediate 8621 8622 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8623 @*/ 8624 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8625 { 8626 PetscScalar *array; 8627 PetscInt *points = PETSC_NULL; 8628 PetscInt offsets[32]; 8629 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8630 PetscErrorCode ierr; 8631 8632 PetscFunctionBegin; 8633 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8634 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8635 if (!section) { 8636 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8637 } 8638 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8639 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8640 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8641 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8642 /* Compress out points not in the section */ 8643 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8644 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8645 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8646 points[q*2] = points[p]; 8647 points[q*2+1] = points[p+1]; 8648 ++q; 8649 } 8650 } 8651 numPoints = q; 8652 for (p = 0; p < numPoints*2; p += 2) { 8653 PetscInt fdof; 8654 8655 for (f = 0; f < numFields; ++f) { 8656 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8657 offsets[f+1] += fdof; 8658 } 8659 } 8660 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8661 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8662 if (numFields) { 8663 switch (mode) { 8664 case INSERT_VALUES: 8665 for (p = 0; p < numPoints*2; p += 2) { 8666 PetscInt o = points[p+1]; 8667 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8668 } break; 8669 case INSERT_ALL_VALUES: 8670 for (p = 0; p < numPoints*2; p += 2) { 8671 PetscInt o = points[p+1]; 8672 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8673 } break; 8674 case ADD_VALUES: 8675 for (p = 0; p < numPoints*2; p += 2) { 8676 PetscInt o = points[p+1]; 8677 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8678 } break; 8679 case ADD_ALL_VALUES: 8680 for (p = 0; p < numPoints*2; p += 2) { 8681 PetscInt o = points[p+1]; 8682 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8683 } break; 8684 default: 8685 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8686 } 8687 } else { 8688 switch (mode) { 8689 case INSERT_VALUES: 8690 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8691 PetscInt o = points[p+1]; 8692 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8693 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8694 } break; 8695 case INSERT_ALL_VALUES: 8696 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8697 PetscInt o = points[p+1]; 8698 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8699 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8700 } break; 8701 case ADD_VALUES: 8702 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8703 PetscInt o = points[p+1]; 8704 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8705 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8706 } break; 8707 case ADD_ALL_VALUES: 8708 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8709 PetscInt o = points[p+1]; 8710 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8711 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8712 } break; 8713 default: 8714 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8715 } 8716 } 8717 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8718 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8719 PetscFunctionReturn(0); 8720 } 8721 8722 #undef __FUNCT__ 8723 #define __FUNCT__ "DMPlexPrintMatSetValues" 8724 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8725 { 8726 PetscMPIInt rank; 8727 PetscInt i, j; 8728 PetscErrorCode ierr; 8729 8730 PetscFunctionBegin; 8731 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8732 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8733 for (i = 0; i < numIndices; i++) { 8734 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8735 } 8736 for (i = 0; i < numIndices; i++) { 8737 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8738 for (j = 0; j < numIndices; j++) { 8739 #if defined(PETSC_USE_COMPLEX) 8740 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8741 #else 8742 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8743 #endif 8744 } 8745 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8746 } 8747 PetscFunctionReturn(0); 8748 } 8749 8750 #undef __FUNCT__ 8751 #define __FUNCT__ "indicesPoint_private" 8752 /* . off - The global offset of this point */ 8753 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8754 { 8755 PetscInt dof; /* The number of unknowns on this point */ 8756 PetscInt cdof; /* The number of constraints on this point */ 8757 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8758 PetscInt cind = 0, k; 8759 PetscErrorCode ierr; 8760 8761 PetscFunctionBegin; 8762 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8763 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8764 if (!cdof || setBC) { 8765 if (orientation >= 0) { 8766 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8767 } else { 8768 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8769 } 8770 } else { 8771 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8772 if (orientation >= 0) { 8773 for (k = 0; k < dof; ++k) { 8774 if ((cind < cdof) && (k == cdofs[cind])) { 8775 /* Insert check for returning constrained indices */ 8776 indices[*loff+k] = -(off+k+1); 8777 ++cind; 8778 } else { 8779 indices[*loff+k] = off+k-cind; 8780 } 8781 } 8782 } else { 8783 for (k = 0; k < dof; ++k) { 8784 if ((cind < cdof) && (k == cdofs[cind])) { 8785 /* Insert check for returning constrained indices */ 8786 indices[*loff+dof-k-1] = -(off+k+1); 8787 ++cind; 8788 } else { 8789 indices[*loff+dof-k-1] = off+k-cind; 8790 } 8791 } 8792 } 8793 } 8794 *loff += dof; 8795 PetscFunctionReturn(0); 8796 } 8797 8798 #undef __FUNCT__ 8799 #define __FUNCT__ "indicesPointFields_private" 8800 /* . off - The global offset of this point */ 8801 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8802 { 8803 PetscInt numFields, foff, f; 8804 PetscErrorCode ierr; 8805 8806 PetscFunctionBegin; 8807 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8808 for (f = 0, foff = 0; f < numFields; ++f) { 8809 PetscInt fdof, fcomp, cfdof; 8810 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8811 PetscInt cind = 0, k, c; 8812 8813 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8814 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8815 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8816 if (!cfdof || setBC) { 8817 if (orientation >= 0) { 8818 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8819 } else { 8820 for (k = fdof/fcomp-1; k >= 0; --k) { 8821 for (c = 0; c < fcomp; ++c) { 8822 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8823 } 8824 } 8825 } 8826 } else { 8827 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8828 if (orientation >= 0) { 8829 for (k = 0; k < fdof; ++k) { 8830 if ((cind < cfdof) && (k == fcdofs[cind])) { 8831 indices[foffs[f]+k] = -(off+foff+k+1); 8832 ++cind; 8833 } else { 8834 indices[foffs[f]+k] = off+foff+k-cind; 8835 } 8836 } 8837 } else { 8838 for (k = fdof/fcomp-1; k >= 0; --k) { 8839 for (c = 0; c < fcomp; ++c) { 8840 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8841 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8842 ++cind; 8843 } else { 8844 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8845 } 8846 } 8847 } 8848 } 8849 } 8850 foff += fdof - cfdof; 8851 foffs[f] += fdof; 8852 } 8853 PetscFunctionReturn(0); 8854 } 8855 8856 #undef __FUNCT__ 8857 #define __FUNCT__ "DMPlexMatSetClosure" 8858 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8859 { 8860 DM_Plex *mesh = (DM_Plex*) dm->data; 8861 PetscInt *points = PETSC_NULL; 8862 PetscInt *indices; 8863 PetscInt offsets[32]; 8864 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8865 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8866 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8867 PetscErrorCode ierr; 8868 8869 PetscFunctionBegin; 8870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8871 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8872 if (useDefault) { 8873 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8874 } 8875 if (useGlobalDefault) { 8876 if (useDefault) { 8877 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8878 } else { 8879 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8880 } 8881 } 8882 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8883 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8884 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8885 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8886 /* Compress out points not in the section */ 8887 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8888 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8889 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8890 points[q*2] = points[p]; 8891 points[q*2+1] = points[p+1]; 8892 ++q; 8893 } 8894 } 8895 numPoints = q; 8896 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8897 PetscInt fdof; 8898 8899 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8900 for (f = 0; f < numFields; ++f) { 8901 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8902 offsets[f+1] += fdof; 8903 } 8904 numIndices += dof; 8905 } 8906 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8907 8908 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8909 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8910 if (numFields) { 8911 for (p = 0; p < numPoints*2; p += 2) { 8912 PetscInt o = points[p+1]; 8913 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8914 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8915 } 8916 } else { 8917 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8918 PetscInt o = points[p+1]; 8919 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8920 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8921 } 8922 } 8923 if (useGlobalDefault && !useDefault) { 8924 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8925 } 8926 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8927 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8928 if (ierr) { 8929 PetscMPIInt rank; 8930 PetscErrorCode ierr2; 8931 8932 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8933 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8934 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8935 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8936 CHKERRQ(ierr); 8937 } 8938 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8939 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8940 PetscFunctionReturn(0); 8941 } 8942 8943 #undef __FUNCT__ 8944 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8945 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8946 { 8947 PetscSection coordSection; 8948 Vec coordinates; 8949 const PetscScalar *coords; 8950 const PetscInt dim = 2; 8951 PetscInt d, f; 8952 PetscErrorCode ierr; 8953 8954 PetscFunctionBegin; 8955 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8956 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8957 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8958 if (v0) { 8959 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8960 } 8961 if (J) { 8962 for (d = 0; d < dim; d++) { 8963 for (f = 0; f < dim; f++) { 8964 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8965 } 8966 } 8967 *detJ = J[0]*J[3] - J[1]*J[2]; 8968 #if 0 8969 if (detJ < 0.0) { 8970 const PetscReal xLength = mesh->periodicity[0]; 8971 8972 if (xLength != 0.0) { 8973 PetscReal v0x = coords[0*dim+0]; 8974 8975 if (v0x == 0.0) v0x = v0[0] = xLength; 8976 for (f = 0; f < dim; f++) { 8977 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8978 8979 J[0*dim+f] = 0.5*(px - v0x); 8980 } 8981 } 8982 detJ = J[0]*J[3] - J[1]*J[2]; 8983 } 8984 #endif 8985 PetscLogFlops(8.0 + 3.0); 8986 } 8987 if (invJ) { 8988 const PetscReal invDet = 1.0/(*detJ); 8989 8990 invJ[0] = invDet*J[3]; 8991 invJ[1] = -invDet*J[1]; 8992 invJ[2] = -invDet*J[2]; 8993 invJ[3] = invDet*J[0]; 8994 PetscLogFlops(5.0); 8995 } 8996 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8997 PetscFunctionReturn(0); 8998 } 8999 9000 #undef __FUNCT__ 9001 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9002 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9003 { 9004 PetscSection coordSection; 9005 Vec coordinates; 9006 const PetscScalar *coords; 9007 const PetscInt dim = 2; 9008 PetscInt d, f; 9009 PetscErrorCode ierr; 9010 9011 PetscFunctionBegin; 9012 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9013 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9014 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9015 if (v0) { 9016 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9017 } 9018 if (J) { 9019 for (d = 0; d < dim; d++) { 9020 for (f = 0; f < dim; f++) { 9021 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9022 } 9023 } 9024 *detJ = J[0]*J[3] - J[1]*J[2]; 9025 PetscLogFlops(8.0 + 3.0); 9026 } 9027 if (invJ) { 9028 const PetscReal invDet = 1.0/(*detJ); 9029 9030 invJ[0] = invDet*J[3]; 9031 invJ[1] = -invDet*J[1]; 9032 invJ[2] = -invDet*J[2]; 9033 invJ[3] = invDet*J[0]; 9034 PetscLogFlops(5.0); 9035 } 9036 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9037 PetscFunctionReturn(0); 9038 } 9039 9040 #undef __FUNCT__ 9041 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9042 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9043 { 9044 PetscSection coordSection; 9045 Vec coordinates; 9046 const PetscScalar *coords; 9047 const PetscInt dim = 3; 9048 PetscInt d, f; 9049 PetscErrorCode ierr; 9050 9051 PetscFunctionBegin; 9052 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9053 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9054 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9055 if (v0) { 9056 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9057 } 9058 if (J) { 9059 for (d = 0; d < dim; d++) { 9060 for (f = 0; f < dim; f++) { 9061 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9062 } 9063 } 9064 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9065 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9066 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9067 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9068 PetscLogFlops(18.0 + 12.0); 9069 } 9070 if (invJ) { 9071 const PetscReal invDet = 1.0/(*detJ); 9072 9073 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9074 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9075 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9076 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9077 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9078 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9079 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9080 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9081 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9082 PetscLogFlops(37.0); 9083 } 9084 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9085 PetscFunctionReturn(0); 9086 } 9087 9088 #undef __FUNCT__ 9089 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9090 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9091 { 9092 PetscSection coordSection; 9093 Vec coordinates; 9094 const PetscScalar *coords; 9095 const PetscInt dim = 3; 9096 PetscInt d; 9097 PetscErrorCode ierr; 9098 9099 PetscFunctionBegin; 9100 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9101 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9102 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9103 if (v0) { 9104 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9105 } 9106 if (J) { 9107 for (d = 0; d < dim; d++) { 9108 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9109 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9110 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9111 } 9112 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9113 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9114 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9115 PetscLogFlops(18.0 + 12.0); 9116 } 9117 if (invJ) { 9118 const PetscReal invDet = -1.0/(*detJ); 9119 9120 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9121 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9122 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9123 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9124 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9125 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9126 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9127 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9128 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9129 PetscLogFlops(37.0); 9130 } 9131 *detJ *= 8.0; 9132 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9133 PetscFunctionReturn(0); 9134 } 9135 9136 #undef __FUNCT__ 9137 #define __FUNCT__ "DMPlexComputeCellGeometry" 9138 /*@C 9139 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9140 9141 Collective on DM 9142 9143 Input Arguments: 9144 + dm - the DM 9145 - cell - the cell 9146 9147 Output Arguments: 9148 + v0 - the translation part of this affine transform 9149 . J - the Jacobian of the transform to the reference element 9150 . invJ - the inverse of the Jacobian 9151 - detJ - the Jacobian determinant 9152 9153 Level: advanced 9154 9155 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9156 @*/ 9157 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9158 { 9159 PetscInt dim, coneSize; 9160 PetscErrorCode ierr; 9161 9162 PetscFunctionBegin; 9163 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9164 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9165 switch (dim) { 9166 case 2: 9167 switch (coneSize) { 9168 case 3: 9169 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9170 break; 9171 case 4: 9172 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9173 break; 9174 default: 9175 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9176 } 9177 break; 9178 case 3: 9179 switch (coneSize) { 9180 case 4: 9181 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9182 break; 9183 case 8: 9184 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9185 break; 9186 default: 9187 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9188 } 9189 break; 9190 default: 9191 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9192 } 9193 PetscFunctionReturn(0); 9194 } 9195 9196 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9197 { 9198 switch (i) { 9199 case 0: 9200 switch (j) { 9201 case 0: return 0; 9202 case 1: 9203 switch (k) { 9204 case 0: return 0; 9205 case 1: return 0; 9206 case 2: return 1; 9207 } 9208 case 2: 9209 switch (k) { 9210 case 0: return 0; 9211 case 1: return -1; 9212 case 2: return 0; 9213 } 9214 } 9215 case 1: 9216 switch (j) { 9217 case 0: 9218 switch (k) { 9219 case 0: return 0; 9220 case 1: return 0; 9221 case 2: return -1; 9222 } 9223 case 1: return 0; 9224 case 2: 9225 switch (k) { 9226 case 0: return 1; 9227 case 1: return 0; 9228 case 2: return 0; 9229 } 9230 } 9231 case 2: 9232 switch (j) { 9233 case 0: 9234 switch (k) { 9235 case 0: return 0; 9236 case 1: return 1; 9237 case 2: return 0; 9238 } 9239 case 1: 9240 switch (k) { 9241 case 0: return -1; 9242 case 1: return 0; 9243 case 2: return 0; 9244 } 9245 case 2: return 0; 9246 } 9247 } 9248 return 0; 9249 } 9250 9251 #undef __FUNCT__ 9252 #define __FUNCT__ "DMPlexCreateRigidBody" 9253 /*@C 9254 DMPlexCreateRigidBody - create rigid body modes from coordinates 9255 9256 Collective on DM 9257 9258 Input Arguments: 9259 + dm - the DM 9260 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9261 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9262 9263 Output Argument: 9264 . sp - the null space 9265 9266 Note: This is necessary to take account of Dirichlet conditions on the displacements 9267 9268 Level: advanced 9269 9270 .seealso: MatNullSpaceCreate() 9271 @*/ 9272 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9273 { 9274 MPI_Comm comm = ((PetscObject) dm)->comm; 9275 Vec coordinates, localMode, mode[6]; 9276 PetscSection coordSection; 9277 PetscScalar *coords; 9278 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9279 PetscErrorCode ierr; 9280 9281 PetscFunctionBegin; 9282 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9283 if (dim == 1) { 9284 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9285 PetscFunctionReturn(0); 9286 } 9287 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9288 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9289 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9290 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9291 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9292 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9293 m = (dim*(dim+1))/2; 9294 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9295 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9296 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9297 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9298 /* Assume P1 */ 9299 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9300 for (d = 0; d < dim; ++d) { 9301 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9302 9303 values[d] = 1.0; 9304 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9305 for (v = vStart; v < vEnd; ++v) { 9306 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9307 } 9308 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9309 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9310 } 9311 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9312 for (d = dim; d < dim*(dim+1)/2; ++d) { 9313 PetscInt i, j, k = dim > 2 ? d - dim : d; 9314 9315 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9316 for (v = vStart; v < vEnd; ++v) { 9317 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9318 PetscInt off; 9319 9320 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9321 for (i = 0; i < dim; ++i) { 9322 for (j = 0; j < dim; ++j) { 9323 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9324 } 9325 } 9326 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9327 } 9328 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9329 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9330 } 9331 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9332 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9333 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9334 /* Orthonormalize system */ 9335 for (i = dim; i < m; ++i) { 9336 PetscScalar dots[6]; 9337 9338 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9339 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9340 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9341 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9342 } 9343 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9344 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9345 PetscFunctionReturn(0); 9346 } 9347 9348 #undef __FUNCT__ 9349 #define __FUNCT__ "DMPlexGetHybridBounds" 9350 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9351 { 9352 DM_Plex *mesh = (DM_Plex*) dm->data; 9353 PetscInt dim; 9354 PetscErrorCode ierr; 9355 9356 PetscFunctionBegin; 9357 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9358 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9359 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9360 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9361 if (eMax) *eMax = mesh->hybridPointMax[1]; 9362 if (vMax) *vMax = mesh->hybridPointMax[0]; 9363 PetscFunctionReturn(0); 9364 } 9365 9366 #undef __FUNCT__ 9367 #define __FUNCT__ "DMPlexSetHybridBounds" 9368 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9369 { 9370 DM_Plex *mesh = (DM_Plex*) dm->data; 9371 PetscInt dim; 9372 PetscErrorCode ierr; 9373 9374 PetscFunctionBegin; 9375 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9376 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9377 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9378 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9379 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9380 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9381 PetscFunctionReturn(0); 9382 } 9383 9384 #undef __FUNCT__ 9385 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9386 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9387 { 9388 DM_Plex *mesh = (DM_Plex*) dm->data; 9389 9390 PetscFunctionBegin; 9391 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9392 PetscValidPointer(cellHeight, 2); 9393 *cellHeight = mesh->vtkCellHeight; 9394 PetscFunctionReturn(0); 9395 } 9396 9397 #undef __FUNCT__ 9398 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9399 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9400 { 9401 DM_Plex *mesh = (DM_Plex*) dm->data; 9402 9403 PetscFunctionBegin; 9404 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9405 mesh->vtkCellHeight = cellHeight; 9406 PetscFunctionReturn(0); 9407 } 9408 9409 #undef __FUNCT__ 9410 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9411 /* We can easily have a form that takes an IS instead */ 9412 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9413 { 9414 PetscSection section, globalSection; 9415 PetscInt *numbers, p; 9416 PetscErrorCode ierr; 9417 9418 PetscFunctionBegin; 9419 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9420 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9421 for (p = pStart; p < pEnd; ++p) { 9422 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9423 } 9424 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9425 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9426 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9427 for (p = pStart; p < pEnd; ++p) { 9428 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9429 } 9430 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9431 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9432 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9433 PetscFunctionReturn(0); 9434 } 9435 9436 #undef __FUNCT__ 9437 #define __FUNCT__ "DMPlexGetCellNumbering" 9438 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9439 { 9440 DM_Plex *mesh = (DM_Plex*) dm->data; 9441 PetscInt cellHeight, cStart, cEnd, cMax; 9442 PetscErrorCode ierr; 9443 9444 PetscFunctionBegin; 9445 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9446 if (!mesh->globalCellNumbers) { 9447 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9448 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9449 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 9450 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9451 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9452 } 9453 *globalCellNumbers = mesh->globalCellNumbers; 9454 PetscFunctionReturn(0); 9455 } 9456 9457 #undef __FUNCT__ 9458 #define __FUNCT__ "DMPlexGetVertexNumbering" 9459 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9460 { 9461 DM_Plex *mesh = (DM_Plex*) dm->data; 9462 PetscInt vStart, vEnd, vMax; 9463 PetscErrorCode ierr; 9464 9465 PetscFunctionBegin; 9466 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9467 if (!mesh->globalVertexNumbers) { 9468 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9469 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9470 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9471 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9472 } 9473 *globalVertexNumbers = mesh->globalVertexNumbers; 9474 PetscFunctionReturn(0); 9475 } 9476 9477 #undef __FUNCT__ 9478 #define __FUNCT__ "DMPlexGetScale" 9479 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9480 { 9481 DM_Plex *mesh = (DM_Plex*) dm->data; 9482 9483 PetscFunctionBegin; 9484 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9485 PetscValidPointer(scale, 3); 9486 *scale = mesh->scale[unit]; 9487 PetscFunctionReturn(0); 9488 } 9489 9490 #undef __FUNCT__ 9491 #define __FUNCT__ "DMPlexSetScale" 9492 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9493 { 9494 DM_Plex *mesh = (DM_Plex*) dm->data; 9495 9496 PetscFunctionBegin; 9497 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9498 mesh->scale[unit] = scale; 9499 PetscFunctionReturn(0); 9500 } 9501 9502 9503 /******************************************************************************* 9504 This should be in a separate Discretization object, but I am not sure how to lay 9505 it out yet, so I am stuffing things here while I experiment. 9506 *******************************************************************************/ 9507 #undef __FUNCT__ 9508 #define __FUNCT__ "DMPlexSetFEMIntegration" 9509 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9510 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9511 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9512 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9513 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9514 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9515 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9516 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9517 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9518 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9519 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9520 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9521 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9522 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9523 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9524 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9525 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9526 { 9527 DM_Plex *mesh = (DM_Plex*) dm->data; 9528 9529 PetscFunctionBegin; 9530 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9531 mesh->integrateResidualFEM = integrateResidualFEM; 9532 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9533 mesh->integrateJacobianFEM = integrateJacobianFEM; 9534 PetscFunctionReturn(0); 9535 } 9536 9537 #undef __FUNCT__ 9538 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9539 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9540 { 9541 Vec coordinates; 9542 PetscSection section, cSection; 9543 PetscInt dim, vStart, vEnd, v, c, d; 9544 PetscScalar *values, *cArray; 9545 PetscReal *coords; 9546 PetscErrorCode ierr; 9547 9548 PetscFunctionBegin; 9549 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9550 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9551 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9552 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9553 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9554 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9555 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9556 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9557 for (v = vStart; v < vEnd; ++v) { 9558 PetscInt dof, off; 9559 9560 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9561 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9562 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9563 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9564 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9565 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9566 } 9567 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9568 /* Temporary, must be replaced by a projection on the finite element basis */ 9569 { 9570 PetscInt eStart = 0, eEnd = 0, e, depth; 9571 9572 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9573 --depth; 9574 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9575 for (e = eStart; e < eEnd; ++e) { 9576 const PetscInt *cone = PETSC_NULL; 9577 PetscInt coneSize, d; 9578 PetscScalar *coordsA, *coordsB; 9579 9580 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9581 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9582 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9583 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9584 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9585 for (d = 0; d < dim; ++d) { 9586 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9587 } 9588 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9589 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9590 } 9591 } 9592 9593 ierr = PetscFree(coords);CHKERRQ(ierr); 9594 ierr = PetscFree(values);CHKERRQ(ierr); 9595 #if 0 9596 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9597 PetscReal detJ; 9598 9599 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9600 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9601 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9602 9603 for (PetscInt c = cStart; c < cEnd; ++c) { 9604 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9605 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9606 const int oSize = pV.getSize(); 9607 int v = 0; 9608 9609 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 9610 for (PetscInt cl = 0; cl < oSize; ++cl) { 9611 const PetscInt fDim; 9612 9613 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9614 if (pointDim) { 9615 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9616 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9617 } 9618 } 9619 } 9620 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 9621 pV.clear(); 9622 } 9623 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9624 ierr = PetscFree(values);CHKERRQ(ierr); 9625 #endif 9626 PetscFunctionReturn(0); 9627 } 9628 9629 #undef __FUNCT__ 9630 #define __FUNCT__ "DMPlexProjectFunction" 9631 /*@C 9632 DMPlexProjectFunction - This projects the given function into the function space provided. 9633 9634 Input Parameters: 9635 + dm - The DM 9636 . numComp - The number of components (functions) 9637 . funcs - The coordinate functions to evaluate 9638 - mode - The insertion mode for values 9639 9640 Output Parameter: 9641 . X - vector 9642 9643 Level: developer 9644 9645 Note: 9646 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9647 We will eventually fix it. 9648 9649 ,seealso: DMPlexComputeL2Diff() 9650 */ 9651 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9652 { 9653 Vec localX; 9654 PetscErrorCode ierr; 9655 9656 PetscFunctionBegin; 9657 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9658 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9659 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9660 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9661 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9662 PetscFunctionReturn(0); 9663 } 9664 9665 #undef __FUNCT__ 9666 #define __FUNCT__ "DMPlexComputeL2Diff" 9667 /*@C 9668 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9669 9670 Input Parameters: 9671 + dm - The DM 9672 . quad - The PetscQuadrature object for each field 9673 . funcs - The functions to evaluate for each field component 9674 - X - The coefficient vector u_h 9675 9676 Output Parameter: 9677 . diff - The diff ||u - u_h||_2 9678 9679 Level: developer 9680 9681 .seealso: DMPlexProjectFunction() 9682 */ 9683 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9684 { 9685 const PetscInt debug = 0; 9686 PetscSection section; 9687 Vec localX; 9688 PetscReal *coords, *v0, *J, *invJ, detJ; 9689 PetscReal localDiff = 0.0; 9690 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9691 PetscErrorCode ierr; 9692 9693 PetscFunctionBegin; 9694 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9695 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9696 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9697 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9698 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9699 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9700 for (field = 0; field < numFields; ++field) { 9701 numComponents += quad[field].numComponents; 9702 } 9703 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9704 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9705 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9706 for (c = cStart; c < cEnd; ++c) { 9707 const PetscScalar *x; 9708 PetscReal elemDiff = 0.0; 9709 9710 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9711 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9712 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9713 9714 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9715 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9716 const PetscReal *quadPoints = quad[field].quadPoints; 9717 const PetscReal *quadWeights = quad[field].quadWeights; 9718 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9719 const PetscInt numBasisComps = quad[field].numComponents; 9720 const PetscReal *basis = quad[field].basis; 9721 PetscInt q, d, e, fc, f; 9722 9723 if (debug) { 9724 char title[1024]; 9725 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9726 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9727 } 9728 for (q = 0; q < numQuadPoints; ++q) { 9729 for (d = 0; d < dim; d++) { 9730 coords[d] = v0[d]; 9731 for (e = 0; e < dim; e++) { 9732 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9733 } 9734 } 9735 for (fc = 0; fc < numBasisComps; ++fc) { 9736 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9737 PetscReal interpolant = 0.0; 9738 for (f = 0; f < numBasisFuncs; ++f) { 9739 const PetscInt fidx = f*numBasisComps+fc; 9740 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9741 } 9742 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9743 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9744 } 9745 } 9746 comp += numBasisComps; 9747 fieldOffset += numBasisFuncs*numBasisComps; 9748 } 9749 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9750 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9751 localDiff += elemDiff; 9752 } 9753 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9754 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9755 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9756 *diff = PetscSqrtReal(*diff); 9757 PetscFunctionReturn(0); 9758 } 9759 9760 #undef __FUNCT__ 9761 #define __FUNCT__ "DMPlexComputeResidualFEM" 9762 /*@ 9763 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9764 9765 Input Parameters: 9766 + dm - The mesh 9767 . X - Local input vector 9768 - user - The user context 9769 9770 Output Parameter: 9771 . F - Local output vector 9772 9773 Note: 9774 The second member of the user context must be an FEMContext. 9775 9776 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9777 like a GPU, or vectorize on a multicore machine. 9778 9779 .seealso: DMPlexComputeJacobianActionFEM() 9780 */ 9781 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9782 { 9783 DM_Plex *mesh = (DM_Plex*) dm->data; 9784 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9785 PetscQuadrature *quad = fem->quad; 9786 PetscSection section; 9787 PetscReal *v0, *J, *invJ, *detJ; 9788 PetscScalar *elemVec, *u; 9789 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9790 PetscInt cellDof = 0, numComponents = 0; 9791 PetscErrorCode ierr; 9792 9793 PetscFunctionBegin; 9794 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9795 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9796 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9797 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9798 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9799 numCells = cEnd - cStart; 9800 for (field = 0; field < numFields; ++field) { 9801 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9802 numComponents += quad[field].numComponents; 9803 } 9804 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9805 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9806 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); 9807 for (c = cStart; c < cEnd; ++c) { 9808 const PetscScalar *x; 9809 PetscInt i; 9810 9811 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9812 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9813 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9814 9815 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9816 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9817 } 9818 for (field = 0; field < numFields; ++field) { 9819 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9820 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9821 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9822 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9823 /* Conforming batches */ 9824 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9825 PetscInt numBlocks = 1; 9826 PetscInt batchSize = numBlocks * blockSize; 9827 PetscInt numBatches = numBatchesTmp; 9828 PetscInt numChunks = numCells / (numBatches*batchSize); 9829 /* Remainder */ 9830 PetscInt numRemainder = numCells % (numBatches * batchSize); 9831 PetscInt offset = numCells - numRemainder; 9832 9833 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9834 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9835 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9836 } 9837 for (c = cStart; c < cEnd; ++c) { 9838 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9839 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9840 } 9841 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9842 if (mesh->printFEM) { 9843 PetscMPIInt rank, numProcs; 9844 PetscInt p; 9845 9846 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9847 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9848 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9849 for (p = 0; p < numProcs; ++p) { 9850 if (p == rank) { 9851 Vec f; 9852 9853 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9854 ierr = VecCopy(F, f);CHKERRQ(ierr); 9855 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9856 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9857 ierr = VecDestroy(&f);CHKERRQ(ierr); 9858 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9859 } 9860 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9861 } 9862 } 9863 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9864 PetscFunctionReturn(0); 9865 } 9866 9867 #undef __FUNCT__ 9868 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9869 /*@C 9870 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9871 9872 Input Parameters: 9873 + dm - The mesh 9874 . J - The Jacobian shell matrix 9875 . X - Local input vector 9876 - user - The user context 9877 9878 Output Parameter: 9879 . F - Local output vector 9880 9881 Note: 9882 The second member of the user context must be an FEMContext. 9883 9884 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9885 like a GPU, or vectorize on a multicore machine. 9886 9887 .seealso: DMPlexComputeResidualFEM() 9888 */ 9889 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9890 { 9891 DM_Plex *mesh = (DM_Plex*) dm->data; 9892 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9893 PetscQuadrature *quad = fem->quad; 9894 PetscSection section; 9895 JacActionCtx *jctx; 9896 PetscReal *v0, *J, *invJ, *detJ; 9897 PetscScalar *elemVec, *u, *a; 9898 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9899 PetscInt cellDof = 0; 9900 PetscErrorCode ierr; 9901 9902 PetscFunctionBegin; 9903 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9904 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9905 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9906 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9907 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9908 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9909 numCells = cEnd - cStart; 9910 for (field = 0; field < numFields; ++field) { 9911 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9912 } 9913 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9914 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); 9915 for (c = cStart; c < cEnd; ++c) { 9916 const PetscScalar *x; 9917 PetscInt i; 9918 9919 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9920 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9921 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9922 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9923 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9924 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9925 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9926 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9927 } 9928 for (field = 0; field < numFields; ++field) { 9929 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9930 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9931 /* Conforming batches */ 9932 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9933 PetscInt numBlocks = 1; 9934 PetscInt batchSize = numBlocks * blockSize; 9935 PetscInt numBatches = numBatchesTmp; 9936 PetscInt numChunks = numCells / (numBatches*batchSize); 9937 /* Remainder */ 9938 PetscInt numRemainder = numCells % (numBatches * batchSize); 9939 PetscInt offset = numCells - numRemainder; 9940 9941 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); 9942 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], 9943 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9944 } 9945 for (c = cStart; c < cEnd; ++c) { 9946 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9947 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9948 } 9949 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9950 if (mesh->printFEM) { 9951 PetscMPIInt rank, numProcs; 9952 PetscInt p; 9953 9954 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9955 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9956 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9957 for (p = 0; p < numProcs; ++p) { 9958 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9959 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9960 } 9961 } 9962 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9963 PetscFunctionReturn(0); 9964 } 9965 9966 #undef __FUNCT__ 9967 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9968 /*@ 9969 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9970 9971 Input Parameters: 9972 + dm - The mesh 9973 . X - Local input vector 9974 - user - The user context 9975 9976 Output Parameter: 9977 . Jac - Jacobian matrix 9978 9979 Note: 9980 The second member of the user context must be an FEMContext. 9981 9982 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9983 like a GPU, or vectorize on a multicore machine. 9984 9985 .seealso: FormFunctionLocal() 9986 */ 9987 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9988 { 9989 DM_Plex *mesh = (DM_Plex*) dm->data; 9990 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9991 PetscQuadrature *quad = fem->quad; 9992 PetscSection section; 9993 PetscReal *v0, *J, *invJ, *detJ; 9994 PetscScalar *elemMat, *u; 9995 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9996 PetscInt cellDof = 0, numComponents = 0; 9997 PetscBool isShell; 9998 PetscErrorCode ierr; 9999 10000 PetscFunctionBegin; 10001 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10002 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10003 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10004 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10005 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10006 numCells = cEnd - cStart; 10007 for (field = 0; field < numFields; ++field) { 10008 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10009 numComponents += quad[field].numComponents; 10010 } 10011 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10012 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10013 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); 10014 for (c = cStart; c < cEnd; ++c) { 10015 const PetscScalar *x; 10016 PetscInt i; 10017 10018 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10019 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10020 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10021 10022 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10023 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10024 } 10025 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10026 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10027 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10028 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10029 PetscInt fieldJ; 10030 10031 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10032 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10033 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10034 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10035 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10036 /* Conforming batches */ 10037 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10038 PetscInt numBlocks = 1; 10039 PetscInt batchSize = numBlocks * blockSize; 10040 PetscInt numBatches = numBatchesTmp; 10041 PetscInt numChunks = numCells / (numBatches*batchSize); 10042 /* Remainder */ 10043 PetscInt numRemainder = numCells % (numBatches * batchSize); 10044 PetscInt offset = numCells - numRemainder; 10045 10046 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10047 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10048 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10049 } 10050 } 10051 for (c = cStart; c < cEnd; ++c) { 10052 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10053 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10054 } 10055 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10056 10057 /* Assemble matrix, using the 2-step process: 10058 MatAssemblyBegin(), MatAssemblyEnd(). */ 10059 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10060 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10061 10062 if (mesh->printFEM) { 10063 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10064 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10065 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10066 } 10067 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10068 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10069 if (isShell) { 10070 JacActionCtx *jctx; 10071 10072 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10073 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10074 } 10075 *str = SAME_NONZERO_PATTERN; 10076 PetscFunctionReturn(0); 10077 } 10078 10079 10080 #undef __FUNCT__ 10081 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10082 /*@C 10083 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10084 the local section and an SF describing the section point overlap. 10085 10086 Input Parameters: 10087 + s - The PetscSection for the local field layout 10088 . sf - The SF describing parallel layout of the section points 10089 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10090 . label - The label specifying the points 10091 - labelValue - The label stratum specifying the points 10092 10093 Output Parameter: 10094 . gsection - The PetscSection for the global field layout 10095 10096 Note: This gives negative sizes and offsets to points not owned by this process 10097 10098 Level: developer 10099 10100 .seealso: PetscSectionCreate() 10101 @*/ 10102 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10103 { 10104 PetscInt *neg; 10105 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10106 PetscErrorCode ierr; 10107 10108 PetscFunctionBegin; 10109 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10110 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10111 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10112 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10113 /* Mark ghost points with negative dof */ 10114 for (p = pStart; p < pEnd; ++p) { 10115 PetscInt value; 10116 10117 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10118 if (value != labelValue) continue; 10119 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10120 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10121 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10122 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10123 neg[p-pStart] = -(dof+1); 10124 } 10125 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10126 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10127 if (nroots >= 0) { 10128 if (nroots > pEnd - pStart) { 10129 PetscInt *tmpDof; 10130 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10131 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10132 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10133 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10134 for (p = pStart; p < pEnd; ++p) { 10135 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 10136 } 10137 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10138 } else { 10139 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10140 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10141 } 10142 } 10143 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10144 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10145 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10146 10147 (*gsection)->atlasOff[p] = off; 10148 10149 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10150 } 10151 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10152 globalOff -= off; 10153 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10154 (*gsection)->atlasOff[p] += globalOff; 10155 10156 neg[p] = -((*gsection)->atlasOff[p]+1); 10157 } 10158 /* Put in negative offsets for ghost points */ 10159 if (nroots >= 0) { 10160 if (nroots > pEnd - pStart) { 10161 PetscInt *tmpOff; 10162 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10163 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10164 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10165 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10166 for (p = pStart; p < pEnd; ++p) { 10167 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 10168 } 10169 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10170 } else { 10171 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10172 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10173 } 10174 } 10175 ierr = PetscFree(neg);CHKERRQ(ierr); 10176 PetscFunctionReturn(0); 10177 } 10178