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 = ISDestroy(&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 PetscErrorCode ierr; 898 PetscInt c,cStart,cEnd,pStart,pEnd; 899 PetscInt *tmpClosure,*tmpAdj,*visits; 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; 982 983 if (bs < 0) { 984 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 985 PetscInt pStart, pEnd, p, dof; 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 if (dof) { 991 bs = dof; 992 break; 993 } 994 } 995 } else { 996 bs = 1; 997 } 998 /* Must have same blocksize on all procs (some might have no points) */ 999 bsLocal = bs; 1000 ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1001 } 1002 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1003 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1004 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1005 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1006 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1007 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1008 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1009 } 1010 PetscFunctionReturn(0); 1011 } 1012 1013 #undef __FUNCT__ 1014 #define __FUNCT__ "DMPlexGetDimension" 1015 /*@ 1016 DMPlexGetDimension - Return the topological mesh dimension 1017 1018 Not collective 1019 1020 Input Parameter: 1021 . mesh - The DMPlex 1022 1023 Output Parameter: 1024 . dim - The topological mesh dimension 1025 1026 Level: beginner 1027 1028 .seealso: DMPlexCreate() 1029 @*/ 1030 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1031 { 1032 DM_Plex *mesh = (DM_Plex*) dm->data; 1033 1034 PetscFunctionBegin; 1035 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1036 PetscValidPointer(dim, 2); 1037 *dim = mesh->dim; 1038 PetscFunctionReturn(0); 1039 } 1040 1041 #undef __FUNCT__ 1042 #define __FUNCT__ "DMPlexSetDimension" 1043 /*@ 1044 DMPlexSetDimension - Set the topological mesh dimension 1045 1046 Collective on mesh 1047 1048 Input Parameters: 1049 + mesh - The DMPlex 1050 - dim - The topological mesh dimension 1051 1052 Level: beginner 1053 1054 .seealso: DMPlexCreate() 1055 @*/ 1056 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1057 { 1058 DM_Plex *mesh = (DM_Plex*) dm->data; 1059 1060 PetscFunctionBegin; 1061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1062 PetscValidLogicalCollectiveInt(dm, dim, 2); 1063 mesh->dim = dim; 1064 mesh->preallocCenterDim = dim; 1065 PetscFunctionReturn(0); 1066 } 1067 1068 #undef __FUNCT__ 1069 #define __FUNCT__ "DMPlexGetChart" 1070 /*@ 1071 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1072 1073 Not collective 1074 1075 Input Parameter: 1076 . mesh - The DMPlex 1077 1078 Output Parameters: 1079 + pStart - The first mesh point 1080 - pEnd - The upper bound for mesh points 1081 1082 Level: beginner 1083 1084 .seealso: DMPlexCreate(), DMPlexSetChart() 1085 @*/ 1086 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1087 { 1088 DM_Plex *mesh = (DM_Plex*) dm->data; 1089 PetscErrorCode ierr; 1090 1091 PetscFunctionBegin; 1092 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1093 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1094 PetscFunctionReturn(0); 1095 } 1096 1097 #undef __FUNCT__ 1098 #define __FUNCT__ "DMPlexSetChart" 1099 /*@ 1100 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1101 1102 Not collective 1103 1104 Input Parameters: 1105 + mesh - The DMPlex 1106 . pStart - The first mesh point 1107 - pEnd - The upper bound for mesh points 1108 1109 Output Parameters: 1110 1111 Level: beginner 1112 1113 .seealso: DMPlexCreate(), DMPlexGetChart() 1114 @*/ 1115 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1116 { 1117 DM_Plex *mesh = (DM_Plex*) dm->data; 1118 PetscErrorCode ierr; 1119 1120 PetscFunctionBegin; 1121 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1122 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1123 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1124 PetscFunctionReturn(0); 1125 } 1126 1127 #undef __FUNCT__ 1128 #define __FUNCT__ "DMPlexGetConeSize" 1129 /*@ 1130 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1131 1132 Not collective 1133 1134 Input Parameters: 1135 + mesh - The DMPlex 1136 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1137 1138 Output Parameter: 1139 . size - The cone size for point p 1140 1141 Level: beginner 1142 1143 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1144 @*/ 1145 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1146 { 1147 DM_Plex *mesh = (DM_Plex*) dm->data; 1148 PetscErrorCode ierr; 1149 1150 PetscFunctionBegin; 1151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1152 PetscValidPointer(size, 3); 1153 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1154 PetscFunctionReturn(0); 1155 } 1156 1157 #undef __FUNCT__ 1158 #define __FUNCT__ "DMPlexSetConeSize" 1159 /*@ 1160 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1161 1162 Not collective 1163 1164 Input Parameters: 1165 + mesh - The DMPlex 1166 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1167 - size - The cone size for point p 1168 1169 Output Parameter: 1170 1171 Note: 1172 This should be called after DMPlexSetChart(). 1173 1174 Level: beginner 1175 1176 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1177 @*/ 1178 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1179 { 1180 DM_Plex *mesh = (DM_Plex*) dm->data; 1181 PetscErrorCode ierr; 1182 1183 PetscFunctionBegin; 1184 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1185 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1186 1187 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1188 PetscFunctionReturn(0); 1189 } 1190 1191 #undef __FUNCT__ 1192 #define __FUNCT__ "DMPlexGetCone" 1193 /*@C 1194 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1195 1196 Not collective 1197 1198 Input Parameters: 1199 + mesh - The DMPlex 1200 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1201 1202 Output Parameter: 1203 . cone - An array of points which are on the in-edges for point p 1204 1205 Level: beginner 1206 1207 Note: 1208 This routine is not available in Fortran. 1209 1210 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1211 @*/ 1212 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1213 { 1214 DM_Plex *mesh = (DM_Plex*) dm->data; 1215 PetscInt off; 1216 PetscErrorCode ierr; 1217 1218 PetscFunctionBegin; 1219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1220 PetscValidPointer(cone, 3); 1221 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1222 *cone = &mesh->cones[off]; 1223 PetscFunctionReturn(0); 1224 } 1225 1226 #undef __FUNCT__ 1227 #define __FUNCT__ "DMPlexSetCone" 1228 /*@ 1229 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1230 1231 Not collective 1232 1233 Input Parameters: 1234 + mesh - The DMPlex 1235 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1236 - cone - An array of points which are on the in-edges for point p 1237 1238 Output Parameter: 1239 1240 Note: 1241 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1242 1243 Level: beginner 1244 1245 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1246 @*/ 1247 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1248 { 1249 DM_Plex *mesh = (DM_Plex*) dm->data; 1250 PetscInt pStart, pEnd; 1251 PetscInt dof, off, c; 1252 PetscErrorCode ierr; 1253 1254 PetscFunctionBegin; 1255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1256 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1257 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1258 if (dof) PetscValidPointer(cone, 3); 1259 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1260 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); 1261 for (c = 0; c < dof; ++c) { 1262 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); 1263 mesh->cones[off+c] = cone[c]; 1264 } 1265 PetscFunctionReturn(0); 1266 } 1267 1268 #undef __FUNCT__ 1269 #define __FUNCT__ "DMPlexGetConeOrientation" 1270 /*@C 1271 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1272 1273 Not collective 1274 1275 Input Parameters: 1276 + mesh - The DMPlex 1277 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1278 1279 Output Parameter: 1280 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1281 integer giving the prescription for cone traversal. If it is negative, the cone is 1282 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1283 the index of the cone point on which to start. 1284 1285 Level: beginner 1286 1287 Note: 1288 This routine is not available in Fortran. 1289 1290 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1291 @*/ 1292 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1293 { 1294 DM_Plex *mesh = (DM_Plex*) dm->data; 1295 PetscInt off; 1296 PetscErrorCode ierr; 1297 1298 PetscFunctionBegin; 1299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1300 #if defined(PETSC_USE_DEBUG) 1301 { 1302 PetscInt dof; 1303 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1304 if (dof) PetscValidPointer(coneOrientation, 3); 1305 } 1306 #endif 1307 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1308 1309 *coneOrientation = &mesh->coneOrientations[off]; 1310 PetscFunctionReturn(0); 1311 } 1312 1313 #undef __FUNCT__ 1314 #define __FUNCT__ "DMPlexSetConeOrientation" 1315 /*@ 1316 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1317 1318 Not collective 1319 1320 Input Parameters: 1321 + mesh - The DMPlex 1322 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1323 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1324 integer giving the prescription for cone traversal. If it is negative, the cone is 1325 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1326 the index of the cone point on which to start. 1327 1328 Output Parameter: 1329 1330 Note: 1331 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1332 1333 Level: beginner 1334 1335 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1336 @*/ 1337 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1338 { 1339 DM_Plex *mesh = (DM_Plex*) dm->data; 1340 PetscInt pStart, pEnd; 1341 PetscInt dof, off, c; 1342 PetscErrorCode ierr; 1343 1344 PetscFunctionBegin; 1345 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1346 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1347 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1348 if (dof) PetscValidPointer(coneOrientation, 3); 1349 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1350 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); 1351 for (c = 0; c < dof; ++c) { 1352 PetscInt cdof, o = coneOrientation[c]; 1353 1354 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1355 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); 1356 mesh->coneOrientations[off+c] = o; 1357 } 1358 PetscFunctionReturn(0); 1359 } 1360 1361 #undef __FUNCT__ 1362 #define __FUNCT__ "DMPlexInsertCone" 1363 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1364 { 1365 DM_Plex *mesh = (DM_Plex*) dm->data; 1366 PetscInt pStart, pEnd; 1367 PetscInt dof, off; 1368 PetscErrorCode ierr; 1369 1370 PetscFunctionBegin; 1371 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1372 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1373 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1374 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1375 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); 1376 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); 1377 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); 1378 mesh->cones[off+conePos] = conePoint; 1379 PetscFunctionReturn(0); 1380 } 1381 1382 #undef __FUNCT__ 1383 #define __FUNCT__ "DMPlexGetSupportSize" 1384 /*@ 1385 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1386 1387 Not collective 1388 1389 Input Parameters: 1390 + mesh - The DMPlex 1391 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1392 1393 Output Parameter: 1394 . size - The support size for point p 1395 1396 Level: beginner 1397 1398 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1399 @*/ 1400 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1401 { 1402 DM_Plex *mesh = (DM_Plex*) dm->data; 1403 PetscErrorCode ierr; 1404 1405 PetscFunctionBegin; 1406 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1407 PetscValidPointer(size, 3); 1408 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1409 PetscFunctionReturn(0); 1410 } 1411 1412 #undef __FUNCT__ 1413 #define __FUNCT__ "DMPlexSetSupportSize" 1414 /*@ 1415 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1416 1417 Not collective 1418 1419 Input Parameters: 1420 + mesh - The DMPlex 1421 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1422 - size - The support size for point p 1423 1424 Output Parameter: 1425 1426 Note: 1427 This should be called after DMPlexSetChart(). 1428 1429 Level: beginner 1430 1431 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1432 @*/ 1433 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1434 { 1435 DM_Plex *mesh = (DM_Plex*) dm->data; 1436 PetscErrorCode ierr; 1437 1438 PetscFunctionBegin; 1439 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1440 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1441 1442 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1443 PetscFunctionReturn(0); 1444 } 1445 1446 #undef __FUNCT__ 1447 #define __FUNCT__ "DMPlexGetSupport" 1448 /*@C 1449 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1450 1451 Not collective 1452 1453 Input Parameters: 1454 + mesh - The DMPlex 1455 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1456 1457 Output Parameter: 1458 . support - An array of points which are on the out-edges for point p 1459 1460 Level: beginner 1461 1462 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1463 @*/ 1464 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1465 { 1466 DM_Plex *mesh = (DM_Plex*) dm->data; 1467 PetscInt off; 1468 PetscErrorCode ierr; 1469 1470 PetscFunctionBegin; 1471 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1472 PetscValidPointer(support, 3); 1473 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1474 *support = &mesh->supports[off]; 1475 PetscFunctionReturn(0); 1476 } 1477 1478 #undef __FUNCT__ 1479 #define __FUNCT__ "DMPlexSetSupport" 1480 /*@ 1481 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1482 1483 Not collective 1484 1485 Input Parameters: 1486 + mesh - The DMPlex 1487 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1488 - support - An array of points which are on the in-edges for point p 1489 1490 Output Parameter: 1491 1492 Note: 1493 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1494 1495 Level: beginner 1496 1497 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1498 @*/ 1499 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1500 { 1501 DM_Plex *mesh = (DM_Plex*) dm->data; 1502 PetscInt pStart, pEnd; 1503 PetscInt dof, off, c; 1504 PetscErrorCode ierr; 1505 1506 PetscFunctionBegin; 1507 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1508 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1509 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1510 if (dof) PetscValidPointer(support, 3); 1511 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1512 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); 1513 for (c = 0; c < dof; ++c) { 1514 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); 1515 mesh->supports[off+c] = support[c]; 1516 } 1517 PetscFunctionReturn(0); 1518 } 1519 1520 #undef __FUNCT__ 1521 #define __FUNCT__ "DMPlexInsertSupport" 1522 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1523 { 1524 DM_Plex *mesh = (DM_Plex*) dm->data; 1525 PetscInt pStart, pEnd; 1526 PetscInt dof, off; 1527 PetscErrorCode ierr; 1528 1529 PetscFunctionBegin; 1530 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1531 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1532 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1533 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1534 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); 1535 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); 1536 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); 1537 mesh->supports[off+supportPos] = supportPoint; 1538 PetscFunctionReturn(0); 1539 } 1540 1541 #undef __FUNCT__ 1542 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1543 /*@C 1544 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1545 1546 Not collective 1547 1548 Input Parameters: 1549 + mesh - The DMPlex 1550 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1551 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1552 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1553 1554 Output Parameters: 1555 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1556 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1557 1558 Note: 1559 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1560 1561 Level: beginner 1562 1563 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1564 @*/ 1565 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1566 { 1567 DM_Plex *mesh = (DM_Plex*) dm->data; 1568 PetscInt *closure, *fifo; 1569 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1570 PetscInt tmpSize, t; 1571 PetscInt depth = 0, maxSize; 1572 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1573 PetscErrorCode ierr; 1574 1575 PetscFunctionBegin; 1576 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1577 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1578 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1579 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1580 if (*points) { 1581 closure = *points; 1582 } else { 1583 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1584 } 1585 closure[0] = p; closure[1] = 0; 1586 /* This is only 1-level */ 1587 if (useCone) { 1588 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1589 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1590 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1591 } else { 1592 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1593 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1594 } 1595 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1596 const PetscInt cp = tmp[t]; 1597 const PetscInt co = tmpO ? tmpO[t] : 0; 1598 1599 closure[closureSize] = cp; 1600 closure[closureSize+1] = co; 1601 fifo[fifoSize] = cp; 1602 fifo[fifoSize+1] = co; 1603 } 1604 while (fifoSize - fifoStart) { 1605 const PetscInt q = fifo[fifoStart]; 1606 const PetscInt o = fifo[fifoStart+1]; 1607 const PetscInt rev = o >= 0 ? 0 : 1; 1608 const PetscInt off = rev ? -(o+1) : o; 1609 1610 if (useCone) { 1611 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1612 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1613 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1614 } else { 1615 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1616 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1617 tmpO = PETSC_NULL; 1618 } 1619 for (t = 0; t < tmpSize; ++t) { 1620 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1621 const PetscInt cp = tmp[i]; 1622 /* Must propogate orientation */ 1623 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1624 PetscInt c; 1625 1626 /* Check for duplicate */ 1627 for (c = 0; c < closureSize; c += 2) { 1628 if (closure[c] == cp) break; 1629 } 1630 if (c == closureSize) { 1631 closure[closureSize] = cp; 1632 closure[closureSize+1] = co; 1633 fifo[fifoSize] = cp; 1634 fifo[fifoSize+1] = co; 1635 closureSize += 2; 1636 fifoSize += 2; 1637 } 1638 } 1639 fifoStart += 2; 1640 } 1641 if (numPoints) *numPoints = closureSize/2; 1642 if (points) *points = closure; 1643 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1644 PetscFunctionReturn(0); 1645 } 1646 1647 #undef __FUNCT__ 1648 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1649 /*@C 1650 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1651 1652 Not collective 1653 1654 Input Parameters: 1655 + mesh - The DMPlex 1656 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1657 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1658 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1659 1660 Output Parameters: 1661 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1662 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1663 1664 Note: 1665 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1666 1667 Level: beginner 1668 1669 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1670 @*/ 1671 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1672 { 1673 PetscErrorCode ierr; 1674 1675 PetscFunctionBegin; 1676 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1677 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1678 PetscFunctionReturn(0); 1679 } 1680 1681 #undef __FUNCT__ 1682 #define __FUNCT__ "DMPlexGetFaces" 1683 /* 1684 DMPlexGetFaces - 1685 1686 Note: This will only work for cell-vertex meshes. 1687 */ 1688 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1689 { 1690 DM_Plex *mesh = (DM_Plex*) dm->data; 1691 const PetscInt *cone = PETSC_NULL; 1692 PetscInt depth = 0, dim, coneSize; 1693 PetscErrorCode ierr; 1694 1695 PetscFunctionBegin; 1696 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1697 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1698 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1699 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1700 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1701 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1702 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1703 switch (dim) { 1704 case 2: 1705 switch (coneSize) { 1706 case 3: 1707 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1708 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1709 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1710 *numFaces = 3; 1711 *faceSize = 2; 1712 *faces = mesh->facesTmp; 1713 break; 1714 case 4: 1715 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1716 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1717 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1718 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1719 *numFaces = 4; 1720 *faceSize = 2; 1721 *faces = mesh->facesTmp; 1722 break; 1723 default: 1724 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1725 } 1726 break; 1727 case 3: 1728 switch (coneSize) { 1729 case 3: 1730 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1731 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1732 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1733 *numFaces = 3; 1734 *faceSize = 2; 1735 *faces = mesh->facesTmp; 1736 break; 1737 case 4: 1738 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1739 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1740 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1741 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1742 *numFaces = 4; 1743 *faceSize = 3; 1744 *faces = mesh->facesTmp; 1745 break; 1746 default: 1747 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1748 } 1749 break; 1750 default: 1751 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1752 } 1753 PetscFunctionReturn(0); 1754 } 1755 1756 #undef __FUNCT__ 1757 #define __FUNCT__ "DMPlexGetMaxSizes" 1758 /*@ 1759 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1760 1761 Not collective 1762 1763 Input Parameter: 1764 . mesh - The DMPlex 1765 1766 Output Parameters: 1767 + maxConeSize - The maximum number of in-edges 1768 - maxSupportSize - The maximum number of out-edges 1769 1770 Level: beginner 1771 1772 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1773 @*/ 1774 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1775 { 1776 DM_Plex *mesh = (DM_Plex*) dm->data; 1777 1778 PetscFunctionBegin; 1779 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1780 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1781 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1782 PetscFunctionReturn(0); 1783 } 1784 1785 #undef __FUNCT__ 1786 #define __FUNCT__ "DMSetUp_Plex" 1787 PetscErrorCode DMSetUp_Plex(DM dm) 1788 { 1789 DM_Plex *mesh = (DM_Plex*) dm->data; 1790 PetscInt size; 1791 PetscErrorCode ierr; 1792 1793 PetscFunctionBegin; 1794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1795 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1796 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1797 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1798 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1799 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1800 if (mesh->maxSupportSize) { 1801 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1802 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1803 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1804 } 1805 PetscFunctionReturn(0); 1806 } 1807 1808 #undef __FUNCT__ 1809 #define __FUNCT__ "DMCreateSubDM_Plex" 1810 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1811 { 1812 PetscSection section, sectionGlobal; 1813 PetscInt *subIndices; 1814 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1815 PetscErrorCode ierr; 1816 1817 PetscFunctionBegin; 1818 if (!numFields) PetscFunctionReturn(0); 1819 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1820 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1821 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1822 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1823 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1824 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); 1825 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1826 for (p = pStart; p < pEnd; ++p) { 1827 PetscInt gdof; 1828 1829 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1830 if (gdof > 0) { 1831 for (f = 0; f < numFields; ++f) { 1832 PetscInt fdof, fcdof; 1833 1834 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1835 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1836 subSize += fdof-fcdof; 1837 } 1838 } 1839 } 1840 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1841 for (p = pStart; p < pEnd; ++p) { 1842 PetscInt gdof, goff; 1843 1844 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1845 if (gdof > 0) { 1846 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1847 for (f = 0; f < numFields; ++f) { 1848 PetscInt fdof, fcdof, fc, f2, poff = 0; 1849 1850 /* Can get rid of this loop by storing field information in the global section */ 1851 for (f2 = 0; f2 < fields[f]; ++f2) { 1852 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1853 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1854 poff += fdof-fcdof; 1855 } 1856 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1857 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1858 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1859 subIndices[subOff] = goff+poff+fc; 1860 } 1861 } 1862 } 1863 } 1864 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1865 if (subdm) { 1866 PetscSection subsection; 1867 PetscBool haveNull = PETSC_FALSE; 1868 PetscInt f, nf = 0; 1869 1870 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1871 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1872 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1873 for (f = 0; f < numFields; ++f) { 1874 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1875 if ((*subdm)->nullspaceConstructors[f]) { 1876 haveNull = PETSC_TRUE; 1877 nf = f; 1878 } 1879 } 1880 if (haveNull) { 1881 MatNullSpace nullSpace; 1882 1883 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1884 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1885 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1886 } 1887 if (dm->fields) { 1888 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); 1889 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1890 for (f = 0; f < numFields; ++f) { 1891 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1892 } 1893 if (numFields == 1) { 1894 MatNullSpace space; 1895 Mat pmat; 1896 1897 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1898 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1899 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1900 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1901 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1902 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1903 } 1904 } 1905 } 1906 PetscFunctionReturn(0); 1907 } 1908 1909 #undef __FUNCT__ 1910 #define __FUNCT__ "DMPlexSymmetrize" 1911 /*@ 1912 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1913 1914 Not collective 1915 1916 Input Parameter: 1917 . mesh - The DMPlex 1918 1919 Output Parameter: 1920 1921 Note: 1922 This should be called after all calls to DMPlexSetCone() 1923 1924 Level: beginner 1925 1926 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1927 @*/ 1928 PetscErrorCode DMPlexSymmetrize(DM dm) 1929 { 1930 DM_Plex *mesh = (DM_Plex*) dm->data; 1931 PetscInt *offsets; 1932 PetscInt supportSize; 1933 PetscInt pStart, pEnd, p; 1934 PetscErrorCode ierr; 1935 1936 PetscFunctionBegin; 1937 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1938 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1939 /* Calculate support sizes */ 1940 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1941 for (p = pStart; p < pEnd; ++p) { 1942 PetscInt dof, off, c; 1943 1944 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1945 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1946 for (c = off; c < off+dof; ++c) { 1947 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1948 } 1949 } 1950 for (p = pStart; p < pEnd; ++p) { 1951 PetscInt dof; 1952 1953 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1954 1955 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1956 } 1957 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1958 /* Calculate supports */ 1959 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1960 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1961 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1962 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1963 for (p = pStart; p < pEnd; ++p) { 1964 PetscInt dof, off, c; 1965 1966 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1967 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1968 for (c = off; c < off+dof; ++c) { 1969 const PetscInt q = mesh->cones[c]; 1970 PetscInt offS; 1971 1972 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1973 1974 mesh->supports[offS+offsets[q]] = p; 1975 ++offsets[q]; 1976 } 1977 } 1978 ierr = PetscFree(offsets);CHKERRQ(ierr); 1979 PetscFunctionReturn(0); 1980 } 1981 1982 #undef __FUNCT__ 1983 #define __FUNCT__ "DMPlexSetDepth_Private" 1984 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1985 { 1986 PetscInt d; 1987 PetscErrorCode ierr; 1988 1989 PetscFunctionBegin; 1990 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1991 if (d < 0) { 1992 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1993 const PetscInt *cone = PETSC_NULL; 1994 PetscInt dCone; 1995 1996 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1997 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1998 d = dCone+1; 1999 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2000 } 2001 *depth = d; 2002 PetscFunctionReturn(0); 2003 } 2004 2005 #undef __FUNCT__ 2006 #define __FUNCT__ "DMPlexStratify" 2007 /*@ 2008 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2009 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2010 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2011 the DAG. 2012 2013 Not collective 2014 2015 Input Parameter: 2016 . mesh - The DMPlex 2017 2018 Output Parameter: 2019 2020 Notes: 2021 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2022 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2023 2024 This should be called after all calls to DMPlexSymmetrize() 2025 2026 Level: beginner 2027 2028 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2029 @*/ 2030 PetscErrorCode DMPlexStratify(DM dm) 2031 { 2032 DM_Plex *mesh = (DM_Plex*) dm->data; 2033 PetscInt pStart, pEnd, p; 2034 PetscInt numRoots = 0, numLeaves = 0; 2035 PetscErrorCode ierr; 2036 2037 PetscFunctionBegin; 2038 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2039 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2040 /* Calculate depth */ 2041 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2042 /* Initialize roots and count leaves */ 2043 for (p = pStart; p < pEnd; ++p) { 2044 PetscInt coneSize, supportSize; 2045 2046 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2047 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2048 if (!coneSize && supportSize) { 2049 ++numRoots; 2050 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2051 } else if (!supportSize && coneSize) { 2052 ++numLeaves; 2053 } else if (!supportSize && !coneSize) { 2054 /* Isolated points */ 2055 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2056 } 2057 } 2058 if (numRoots + numLeaves == (pEnd - pStart)) { 2059 for (p = pStart; p < pEnd; ++p) { 2060 PetscInt coneSize, supportSize; 2061 2062 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2063 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2064 if (!supportSize && coneSize) { 2065 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2066 } 2067 } 2068 } else { 2069 /* This might be slow since lookup is not fast */ 2070 for (p = pStart; p < pEnd; ++p) { 2071 PetscInt depth; 2072 2073 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2074 } 2075 } 2076 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2077 PetscFunctionReturn(0); 2078 } 2079 2080 #undef __FUNCT__ 2081 #define __FUNCT__ "DMPlexGetJoin" 2082 /*@C 2083 DMPlexGetJoin - Get an array for the join of the set of points 2084 2085 Not Collective 2086 2087 Input Parameters: 2088 + dm - The DMPlex object 2089 . numPoints - The number of input points for the join 2090 - points - The input points 2091 2092 Output Parameters: 2093 + numCoveredPoints - The number of points in the join 2094 - coveredPoints - The points in the join 2095 2096 Level: intermediate 2097 2098 Note: Currently, this is restricted to a single level join 2099 2100 .keywords: mesh 2101 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2102 @*/ 2103 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2104 { 2105 DM_Plex *mesh = (DM_Plex*) dm->data; 2106 PetscInt *join[2]; 2107 PetscInt joinSize, i = 0; 2108 PetscInt dof, off, p, c, m; 2109 PetscErrorCode ierr; 2110 2111 PetscFunctionBegin; 2112 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2113 PetscValidPointer(points, 2); 2114 PetscValidPointer(numCoveredPoints, 3); 2115 PetscValidPointer(coveredPoints, 4); 2116 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2117 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2118 /* Copy in support of first point */ 2119 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2120 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2121 for (joinSize = 0; joinSize < dof; ++joinSize) { 2122 join[i][joinSize] = mesh->supports[off+joinSize]; 2123 } 2124 /* Check each successive support */ 2125 for (p = 1; p < numPoints; ++p) { 2126 PetscInt newJoinSize = 0; 2127 2128 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2129 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2130 for (c = 0; c < dof; ++c) { 2131 const PetscInt point = mesh->supports[off+c]; 2132 2133 for (m = 0; m < joinSize; ++m) { 2134 if (point == join[i][m]) { 2135 join[1-i][newJoinSize++] = point; 2136 break; 2137 } 2138 } 2139 } 2140 joinSize = newJoinSize; 2141 i = 1-i; 2142 } 2143 *numCoveredPoints = joinSize; 2144 *coveredPoints = join[i]; 2145 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2146 PetscFunctionReturn(0); 2147 } 2148 2149 #undef __FUNCT__ 2150 #define __FUNCT__ "DMPlexRestoreJoin" 2151 /*@C 2152 DMPlexRestoreJoin - Restore an array for the join of the set of points 2153 2154 Not Collective 2155 2156 Input Parameters: 2157 + dm - The DMPlex object 2158 . numPoints - The number of input points for the join 2159 - points - The input points 2160 2161 Output Parameters: 2162 + numCoveredPoints - The number of points in the join 2163 - coveredPoints - The points in the join 2164 2165 Level: intermediate 2166 2167 .keywords: mesh 2168 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2169 @*/ 2170 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2171 { 2172 PetscErrorCode ierr; 2173 2174 PetscFunctionBegin; 2175 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2176 PetscValidPointer(coveredPoints, 4); 2177 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2178 PetscFunctionReturn(0); 2179 } 2180 2181 #undef __FUNCT__ 2182 #define __FUNCT__ "DMPlexGetFullJoin" 2183 /*@C 2184 DMPlexGetFullJoin - Get an array for the join of the set of points 2185 2186 Not Collective 2187 2188 Input Parameters: 2189 + dm - The DMPlex object 2190 . numPoints - The number of input points for the join 2191 - points - The input points 2192 2193 Output Parameters: 2194 + numCoveredPoints - The number of points in the join 2195 - coveredPoints - The points in the join 2196 2197 Level: intermediate 2198 2199 .keywords: mesh 2200 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2201 @*/ 2202 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2203 { 2204 DM_Plex *mesh = (DM_Plex*) dm->data; 2205 PetscInt *offsets, **closures; 2206 PetscInt *join[2]; 2207 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2208 PetscInt p, d, c, m; 2209 PetscErrorCode ierr; 2210 2211 PetscFunctionBegin; 2212 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2213 PetscValidPointer(points, 2); 2214 PetscValidPointer(numCoveredPoints, 3); 2215 PetscValidPointer(coveredPoints, 4); 2216 2217 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2218 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2219 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2220 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2221 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2222 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2223 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2224 2225 for (p = 0; p < numPoints; ++p) { 2226 PetscInt closureSize; 2227 2228 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2229 2230 offsets[p*(depth+2)+0] = 0; 2231 for (d = 0; d < depth+1; ++d) { 2232 PetscInt pStart, pEnd, i; 2233 2234 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2235 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2236 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2237 offsets[p*(depth+2)+d+1] = i; 2238 break; 2239 } 2240 } 2241 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2242 } 2243 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); 2244 } 2245 for (d = 0; d < depth+1; ++d) { 2246 PetscInt dof; 2247 2248 /* Copy in support of first point */ 2249 dof = offsets[d+1] - offsets[d]; 2250 for (joinSize = 0; joinSize < dof; ++joinSize) { 2251 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2252 } 2253 /* Check each successive cone */ 2254 for (p = 1; p < numPoints && joinSize; ++p) { 2255 PetscInt newJoinSize = 0; 2256 2257 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2258 for (c = 0; c < dof; ++c) { 2259 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2260 2261 for (m = 0; m < joinSize; ++m) { 2262 if (point == join[i][m]) { 2263 join[1-i][newJoinSize++] = point; 2264 break; 2265 } 2266 } 2267 } 2268 joinSize = newJoinSize; 2269 i = 1-i; 2270 } 2271 if (joinSize) break; 2272 } 2273 *numCoveredPoints = joinSize; 2274 *coveredPoints = join[i]; 2275 for (p = 0; p < numPoints; ++p) { 2276 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2277 } 2278 ierr = PetscFree(closures);CHKERRQ(ierr); 2279 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2280 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2281 PetscFunctionReturn(0); 2282 } 2283 2284 #undef __FUNCT__ 2285 #define __FUNCT__ "DMPlexGetMeet" 2286 /*@C 2287 DMPlexGetMeet - Get an array for the meet of the set of points 2288 2289 Not Collective 2290 2291 Input Parameters: 2292 + dm - The DMPlex object 2293 . numPoints - The number of input points for the meet 2294 - points - The input points 2295 2296 Output Parameters: 2297 + numCoveredPoints - The number of points in the meet 2298 - coveredPoints - The points in the meet 2299 2300 Level: intermediate 2301 2302 Note: Currently, this is restricted to a single level meet 2303 2304 .keywords: mesh 2305 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2306 @*/ 2307 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2308 { 2309 DM_Plex *mesh = (DM_Plex*) dm->data; 2310 PetscInt *meet[2]; 2311 PetscInt meetSize, i = 0; 2312 PetscInt dof, off, p, c, m; 2313 PetscErrorCode ierr; 2314 2315 PetscFunctionBegin; 2316 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2317 PetscValidPointer(points, 2); 2318 PetscValidPointer(numCoveringPoints, 3); 2319 PetscValidPointer(coveringPoints, 4); 2320 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2321 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2322 /* Copy in cone of first point */ 2323 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2324 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2325 for (meetSize = 0; meetSize < dof; ++meetSize) { 2326 meet[i][meetSize] = mesh->cones[off+meetSize]; 2327 } 2328 /* Check each successive cone */ 2329 for (p = 1; p < numPoints; ++p) { 2330 PetscInt newMeetSize = 0; 2331 2332 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2333 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2334 for (c = 0; c < dof; ++c) { 2335 const PetscInt point = mesh->cones[off+c]; 2336 2337 for (m = 0; m < meetSize; ++m) { 2338 if (point == meet[i][m]) { 2339 meet[1-i][newMeetSize++] = point; 2340 break; 2341 } 2342 } 2343 } 2344 meetSize = newMeetSize; 2345 i = 1-i; 2346 } 2347 *numCoveringPoints = meetSize; 2348 *coveringPoints = meet[i]; 2349 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2350 PetscFunctionReturn(0); 2351 } 2352 2353 #undef __FUNCT__ 2354 #define __FUNCT__ "DMPlexRestoreMeet" 2355 /*@C 2356 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2357 2358 Not Collective 2359 2360 Input Parameters: 2361 + dm - The DMPlex object 2362 . numPoints - The number of input points for the meet 2363 - points - The input points 2364 2365 Output Parameters: 2366 + numCoveredPoints - The number of points in the meet 2367 - coveredPoints - The points in the meet 2368 2369 Level: intermediate 2370 2371 .keywords: mesh 2372 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2373 @*/ 2374 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2375 { 2376 PetscErrorCode ierr; 2377 2378 PetscFunctionBegin; 2379 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2380 PetscValidPointer(coveredPoints, 4); 2381 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2382 PetscFunctionReturn(0); 2383 } 2384 2385 #undef __FUNCT__ 2386 #define __FUNCT__ "DMPlexGetFullMeet" 2387 /*@C 2388 DMPlexGetFullMeet - Get an array for the meet of the set of points 2389 2390 Not Collective 2391 2392 Input Parameters: 2393 + dm - The DMPlex object 2394 . numPoints - The number of input points for the meet 2395 - points - The input points 2396 2397 Output Parameters: 2398 + numCoveredPoints - The number of points in the meet 2399 - coveredPoints - The points in the meet 2400 2401 Level: intermediate 2402 2403 .keywords: mesh 2404 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2405 @*/ 2406 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2407 { 2408 DM_Plex *mesh = (DM_Plex*) dm->data; 2409 PetscInt *offsets, **closures; 2410 PetscInt *meet[2]; 2411 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2412 PetscInt p, h, c, m; 2413 PetscErrorCode ierr; 2414 2415 PetscFunctionBegin; 2416 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2417 PetscValidPointer(points, 2); 2418 PetscValidPointer(numCoveredPoints, 3); 2419 PetscValidPointer(coveredPoints, 4); 2420 2421 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2422 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2423 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2424 maxSize = PetscPowInt(mesh->maxConeSize,height); 2425 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2426 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2427 2428 for (p = 0; p < numPoints; ++p) { 2429 PetscInt closureSize; 2430 2431 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2432 2433 offsets[p*(height+2)+0] = 0; 2434 for (h = 0; h < height+1; ++h) { 2435 PetscInt pStart, pEnd, i; 2436 2437 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2438 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2439 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2440 offsets[p*(height+2)+h+1] = i; 2441 break; 2442 } 2443 } 2444 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2445 } 2446 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); 2447 } 2448 for (h = 0; h < height+1; ++h) { 2449 PetscInt dof; 2450 2451 /* Copy in cone of first point */ 2452 dof = offsets[h+1] - offsets[h]; 2453 for (meetSize = 0; meetSize < dof; ++meetSize) { 2454 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2455 } 2456 /* Check each successive cone */ 2457 for (p = 1; p < numPoints && meetSize; ++p) { 2458 PetscInt newMeetSize = 0; 2459 2460 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2461 for (c = 0; c < dof; ++c) { 2462 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2463 2464 for (m = 0; m < meetSize; ++m) { 2465 if (point == meet[i][m]) { 2466 meet[1-i][newMeetSize++] = point; 2467 break; 2468 } 2469 } 2470 } 2471 meetSize = newMeetSize; 2472 i = 1-i; 2473 } 2474 if (meetSize) break; 2475 } 2476 *numCoveredPoints = meetSize; 2477 *coveredPoints = meet[i]; 2478 for (p = 0; p < numPoints; ++p) { 2479 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2480 } 2481 ierr = PetscFree(closures);CHKERRQ(ierr); 2482 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2483 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2484 PetscFunctionReturn(0); 2485 } 2486 2487 #undef __FUNCT__ 2488 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2489 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2490 { 2491 MPI_Comm comm = ((PetscObject) dm)->comm; 2492 PetscInt cellDim; 2493 PetscErrorCode ierr; 2494 2495 PetscFunctionBegin; 2496 PetscValidPointer(numFaceVertices,3); 2497 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2498 switch (cellDim) { 2499 case 0: 2500 *numFaceVertices = 0; 2501 break; 2502 case 1: 2503 *numFaceVertices = 1; 2504 break; 2505 case 2: 2506 switch (numCorners) { 2507 case 3: /* triangle */ 2508 *numFaceVertices = 2; /* Edge has 2 vertices */ 2509 break; 2510 case 4: /* quadrilateral */ 2511 *numFaceVertices = 2; /* Edge has 2 vertices */ 2512 break; 2513 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2514 *numFaceVertices = 3; /* Edge has 3 vertices */ 2515 break; 2516 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2517 *numFaceVertices = 3; /* Edge has 3 vertices */ 2518 break; 2519 default: 2520 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2521 } 2522 break; 2523 case 3: 2524 switch (numCorners) { 2525 case 4: /* tetradehdron */ 2526 *numFaceVertices = 3; /* Face has 3 vertices */ 2527 break; 2528 case 6: /* tet cohesive cells */ 2529 *numFaceVertices = 4; /* Face has 4 vertices */ 2530 break; 2531 case 8: /* hexahedron */ 2532 *numFaceVertices = 4; /* Face has 4 vertices */ 2533 break; 2534 case 9: /* tet cohesive Lagrange cells */ 2535 *numFaceVertices = 6; /* Face has 6 vertices */ 2536 break; 2537 case 10: /* quadratic tetrahedron */ 2538 *numFaceVertices = 6; /* Face has 6 vertices */ 2539 break; 2540 case 12: /* hex cohesive Lagrange cells */ 2541 *numFaceVertices = 6; /* Face has 6 vertices */ 2542 break; 2543 case 18: /* quadratic tet cohesive Lagrange cells */ 2544 *numFaceVertices = 6; /* Face has 6 vertices */ 2545 break; 2546 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2547 *numFaceVertices = 9; /* Face has 9 vertices */ 2548 break; 2549 default: 2550 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2551 } 2552 break; 2553 default: 2554 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2555 } 2556 PetscFunctionReturn(0); 2557 } 2558 2559 #undef __FUNCT__ 2560 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2561 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2562 { 2563 const PetscInt maxFaceCases = 30; 2564 PetscInt numFaceCases = 0; 2565 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2566 PetscInt *off, *adj; 2567 PetscInt *neighborCells, *tmpClosure; 2568 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2569 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2570 PetscErrorCode ierr; 2571 2572 PetscFunctionBegin; 2573 /* For parallel partitioning, I think you have to communicate supports */ 2574 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2575 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2576 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2577 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2578 if (cEnd - cStart == 0) { 2579 if (numVertices) *numVertices = 0; 2580 if (offsets) *offsets = PETSC_NULL; 2581 if (adjacency) *adjacency = PETSC_NULL; 2582 PetscFunctionReturn(0); 2583 } 2584 numCells = cEnd - cStart; 2585 /* Setup face recognition */ 2586 if (depth == 1) { 2587 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 */ 2588 2589 for (c = cStart; c < cEnd; ++c) { 2590 PetscInt corners; 2591 2592 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2593 if (!cornersSeen[corners]) { 2594 PetscInt nFV; 2595 2596 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2597 cornersSeen[corners] = 1; 2598 2599 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2600 2601 numFaceVertices[numFaceCases++] = nFV; 2602 } 2603 } 2604 } 2605 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2606 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2607 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2608 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2609 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2610 /* Count neighboring cells */ 2611 for (cell = cStart; cell < cEnd; ++cell) { 2612 PetscInt numNeighbors = maxNeighbors, n; 2613 2614 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2615 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2616 for (n = 0; n < numNeighbors; ++n) { 2617 PetscInt cellPair[2]; 2618 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2619 PetscInt meetSize = 0; 2620 const PetscInt *meet = PETSC_NULL; 2621 2622 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2623 if (cellPair[0] == cellPair[1]) continue; 2624 if (!found) { 2625 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2626 if (meetSize) { 2627 PetscInt f; 2628 2629 for (f = 0; f < numFaceCases; ++f) { 2630 if (numFaceVertices[f] == meetSize) { 2631 found = PETSC_TRUE; 2632 break; 2633 } 2634 } 2635 } 2636 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2637 } 2638 if (found) ++off[cell-cStart+1]; 2639 } 2640 } 2641 /* Prefix sum */ 2642 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2643 2644 if (adjacency) { 2645 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2646 /* Get neighboring cells */ 2647 for (cell = cStart; cell < cEnd; ++cell) { 2648 PetscInt numNeighbors = maxNeighbors, n; 2649 PetscInt cellOffset = 0; 2650 2651 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2652 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2653 for (n = 0; n < numNeighbors; ++n) { 2654 PetscInt cellPair[2]; 2655 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2656 PetscInt meetSize = 0; 2657 const PetscInt *meet = PETSC_NULL; 2658 2659 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2660 if (cellPair[0] == cellPair[1]) continue; 2661 if (!found) { 2662 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2663 if (meetSize) { 2664 PetscInt f; 2665 2666 for (f = 0; f < numFaceCases; ++f) { 2667 if (numFaceVertices[f] == meetSize) { 2668 found = PETSC_TRUE; 2669 break; 2670 } 2671 } 2672 } 2673 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2674 } 2675 if (found) { 2676 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2677 ++cellOffset; 2678 } 2679 } 2680 } 2681 } 2682 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2683 if (numVertices) *numVertices = numCells; 2684 if (offsets) *offsets = off; 2685 if (adjacency) *adjacency = adj; 2686 PetscFunctionReturn(0); 2687 } 2688 2689 #if defined(PETSC_HAVE_CHACO) 2690 #if defined(PETSC_HAVE_UNISTD_H) 2691 #include <unistd.h> 2692 #endif 2693 /* Chaco does not have an include file */ 2694 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2695 float *ewgts, float *x, float *y, float *z, char *outassignname, 2696 char *outfilename, short *assignment, int architecture, int ndims_tot, 2697 int mesh_dims[3], double *goal, int global_method, int local_method, 2698 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2699 2700 extern int FREE_GRAPH; 2701 2702 #undef __FUNCT__ 2703 #define __FUNCT__ "DMPlexPartition_Chaco" 2704 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2705 { 2706 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2707 MPI_Comm comm = ((PetscObject) dm)->comm; 2708 int nvtxs = numVertices; /* number of vertices in full graph */ 2709 int *vwgts = NULL; /* weights for all vertices */ 2710 float *ewgts = NULL; /* weights for all edges */ 2711 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2712 char *outassignname = NULL; /* name of assignment output file */ 2713 char *outfilename = NULL; /* output file name */ 2714 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2715 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2716 int mesh_dims[3]; /* dimensions of mesh of processors */ 2717 double *goal = NULL; /* desired set sizes for each set */ 2718 int global_method = 1; /* global partitioning algorithm */ 2719 int local_method = 1; /* local partitioning algorithm */ 2720 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2721 int vmax = 200; /* how many vertices to coarsen down to? */ 2722 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2723 double eigtol = 0.001; /* tolerance on eigenvectors */ 2724 long seed = 123636512; /* for random graph mutations */ 2725 short int *assignment; /* Output partition */ 2726 int fd_stdout, fd_pipe[2]; 2727 PetscInt *points; 2728 PetscMPIInt commSize; 2729 int i, v, p; 2730 PetscErrorCode ierr; 2731 2732 PetscFunctionBegin; 2733 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2734 if (!numVertices) { 2735 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2736 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2737 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2738 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2739 PetscFunctionReturn(0); 2740 } 2741 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2742 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2743 2744 if (global_method == INERTIAL_METHOD) { 2745 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2746 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2747 } 2748 mesh_dims[0] = commSize; 2749 mesh_dims[1] = 1; 2750 mesh_dims[2] = 1; 2751 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2752 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2753 /* TODO: check error codes for UNIX calls */ 2754 #if defined(PETSC_HAVE_UNISTD_H) 2755 { 2756 int piperet; 2757 piperet = pipe(fd_pipe); 2758 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2759 fd_stdout = dup(1); 2760 close(1); 2761 dup2(fd_pipe[1], 1); 2762 } 2763 #endif 2764 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2765 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2766 vmax, ndims, eigtol, seed); 2767 #if defined(PETSC_HAVE_UNISTD_H) 2768 { 2769 char msgLog[10000]; 2770 int count; 2771 2772 fflush(stdout); 2773 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2774 if (count < 0) count = 0; 2775 msgLog[count] = 0; 2776 close(1); 2777 dup2(fd_stdout, 1); 2778 close(fd_stdout); 2779 close(fd_pipe[0]); 2780 close(fd_pipe[1]); 2781 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2782 } 2783 #endif 2784 /* Convert to PetscSection+IS */ 2785 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2786 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2787 for (v = 0; v < nvtxs; ++v) { 2788 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2789 } 2790 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2791 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2792 for (p = 0, i = 0; p < commSize; ++p) { 2793 for (v = 0; v < nvtxs; ++v) { 2794 if (assignment[v] == p) points[i++] = v; 2795 } 2796 } 2797 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2798 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2799 if (global_method == INERTIAL_METHOD) { 2800 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2801 } 2802 ierr = PetscFree(assignment);CHKERRQ(ierr); 2803 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2804 PetscFunctionReturn(0); 2805 } 2806 #endif 2807 2808 #if defined(PETSC_HAVE_PARMETIS) 2809 #undef __FUNCT__ 2810 #define __FUNCT__ "DMPlexPartition_ParMetis" 2811 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2812 { 2813 PetscFunctionBegin; 2814 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2815 PetscFunctionReturn(0); 2816 } 2817 #endif 2818 2819 #undef __FUNCT__ 2820 #define __FUNCT__ "DMPlexEnlargePartition" 2821 /* Expand the partition by BFS on the adjacency graph */ 2822 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2823 { 2824 PetscHashI h; 2825 const PetscInt *points; 2826 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2827 PetscInt pStart, pEnd, part, q; 2828 PetscErrorCode ierr; 2829 2830 PetscFunctionBegin; 2831 PetscHashICreate(h); 2832 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2833 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2834 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2835 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2836 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2837 for (part = pStart; part < pEnd; ++part) { 2838 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2839 2840 PetscHashIClear(h); 2841 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2842 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2843 /* Add all existing points to h */ 2844 for (p = 0; p < numPoints; ++p) { 2845 const PetscInt point = points[off+p]; 2846 PetscHashIAdd(h, point, 1); 2847 } 2848 PetscHashISize(h, nP); 2849 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2850 /* Add all points in next BFS level */ 2851 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2852 for (p = 0; p < numPoints; ++p) { 2853 const PetscInt point = points[off+p]; 2854 PetscInt s = start[point], e = start[point+1], a; 2855 2856 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2857 } 2858 PetscHashISize(h, numNewPoints); 2859 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2860 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2861 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2862 totPoints += numNewPoints; 2863 } 2864 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2865 PetscHashIDestroy(h); 2866 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2867 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2868 for (part = pStart, q = 0; part < pEnd; ++part) { 2869 PetscInt numPoints, p; 2870 2871 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2872 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2873 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2874 } 2875 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2876 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2877 PetscFunctionReturn(0); 2878 } 2879 2880 #undef __FUNCT__ 2881 #define __FUNCT__ "DMPlexCreatePartition" 2882 /* 2883 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2884 2885 Collective on DM 2886 2887 Input Parameters: 2888 + dm - The DM 2889 . height - The height for points in the partition 2890 - enlarge - Expand each partition with neighbors 2891 2892 Output Parameters: 2893 + partSection - The PetscSection giving the division of points by partition 2894 . partition - The list of points by partition 2895 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2896 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2897 2898 Level: developer 2899 2900 .seealso DMPlexDistribute() 2901 */ 2902 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2903 { 2904 PetscMPIInt size; 2905 PetscErrorCode ierr; 2906 2907 PetscFunctionBegin; 2908 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2909 2910 *origPartSection = PETSC_NULL; 2911 *origPartition = PETSC_NULL; 2912 if (size == 1) { 2913 PetscInt *points; 2914 PetscInt cStart, cEnd, c; 2915 2916 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2917 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2918 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2919 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2920 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2921 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2922 for (c = cStart; c < cEnd; ++c) points[c] = c; 2923 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2924 PetscFunctionReturn(0); 2925 } 2926 if (height == 0) { 2927 PetscInt numVertices; 2928 PetscInt *start = PETSC_NULL; 2929 PetscInt *adjacency = PETSC_NULL; 2930 2931 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2932 if (1) { 2933 #if defined(PETSC_HAVE_CHACO) 2934 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2935 #endif 2936 } else { 2937 #if defined(PETSC_HAVE_PARMETIS) 2938 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2939 #endif 2940 } 2941 if (enlarge) { 2942 *origPartSection = *partSection; 2943 *origPartition = *partition; 2944 2945 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2946 } 2947 ierr = PetscFree(start);CHKERRQ(ierr); 2948 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2949 # if 0 2950 } else if (height == 1) { 2951 /* Build the dual graph for faces and partition the hypergraph */ 2952 PetscInt numEdges; 2953 2954 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2955 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2956 destroyCSR(numEdges, start, adjacency); 2957 #endif 2958 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2959 PetscFunctionReturn(0); 2960 } 2961 2962 #undef __FUNCT__ 2963 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2964 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2965 { 2966 /* const PetscInt height = 0; */ 2967 const PetscInt *partArray; 2968 PetscInt *allPoints, *partPoints = PETSC_NULL; 2969 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2970 PetscErrorCode ierr; 2971 2972 PetscFunctionBegin; 2973 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2974 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2975 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2976 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2977 for (rank = rStart; rank < rEnd; ++rank) { 2978 PetscInt partSize = 0; 2979 PetscInt numPoints, offset, p; 2980 2981 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2982 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2983 for (p = 0; p < numPoints; ++p) { 2984 PetscInt point = partArray[offset+p], closureSize, c; 2985 PetscInt *closure = PETSC_NULL; 2986 2987 /* TODO Include support for height > 0 case */ 2988 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2989 /* Merge into existing points */ 2990 if (partSize+closureSize > maxPartSize) { 2991 PetscInt *tmpPoints; 2992 2993 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2994 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2995 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2996 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2997 2998 partPoints = tmpPoints; 2999 } 3000 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3001 partSize += closureSize; 3002 3003 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3004 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3005 } 3006 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3007 } 3008 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3009 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3010 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3011 3012 for (rank = rStart; rank < rEnd; ++rank) { 3013 PetscInt partSize = 0, newOffset; 3014 PetscInt numPoints, offset, p; 3015 3016 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3017 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3018 for (p = 0; p < numPoints; ++p) { 3019 PetscInt point = partArray[offset+p], closureSize, c; 3020 PetscInt *closure = PETSC_NULL; 3021 3022 /* TODO Include support for height > 0 case */ 3023 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3024 /* Merge into existing points */ 3025 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3026 partSize += closureSize; 3027 3028 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3029 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3030 } 3031 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3032 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3033 } 3034 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3035 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3036 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3037 PetscFunctionReturn(0); 3038 } 3039 3040 #undef __FUNCT__ 3041 #define __FUNCT__ "DMPlexDistributeField" 3042 /* 3043 Input Parameters: 3044 . originalSection 3045 , originalVec 3046 3047 Output Parameters: 3048 . newSection 3049 . newVec 3050 */ 3051 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3052 { 3053 PetscSF fieldSF; 3054 PetscInt *remoteOffsets, fieldSize; 3055 PetscScalar *originalValues, *newValues; 3056 PetscErrorCode ierr; 3057 3058 PetscFunctionBegin; 3059 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3060 3061 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3062 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3063 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3064 3065 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3066 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3067 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3068 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3069 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3070 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3071 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3072 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3073 PetscFunctionReturn(0); 3074 } 3075 3076 #undef __FUNCT__ 3077 #define __FUNCT__ "DMPlexDistribute" 3078 /*@C 3079 DMPlexDistribute - Distributes the mesh and any associated sections. 3080 3081 Not Collective 3082 3083 Input Parameter: 3084 + dm - The original DMPlex object 3085 . partitioner - The partitioning package, or NULL for the default 3086 - overlap - The overlap of partitions, 0 is the default 3087 3088 Output Parameter: 3089 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3090 3091 Note: If the mesh was not distributed, the return value is PETSC_NULL 3092 3093 Level: intermediate 3094 3095 .keywords: mesh, elements 3096 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3097 @*/ 3098 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3099 { 3100 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3101 MPI_Comm comm = ((PetscObject) dm)->comm; 3102 const PetscInt height = 0; 3103 PetscInt dim, numRemoteRanks; 3104 IS origCellPart, cellPart, part; 3105 PetscSection origCellPartSection, cellPartSection, partSection; 3106 PetscSFNode *remoteRanks; 3107 PetscSF partSF, pointSF, coneSF; 3108 ISLocalToGlobalMapping renumbering; 3109 PetscSection originalConeSection, newConeSection; 3110 PetscInt *remoteOffsets; 3111 PetscInt *cones, *newCones, newConesSize; 3112 PetscBool flg; 3113 PetscMPIInt rank, numProcs, p; 3114 PetscErrorCode ierr; 3115 3116 PetscFunctionBegin; 3117 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3118 PetscValidPointer(dmParallel,4); 3119 3120 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3121 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3122 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3123 3124 *dmParallel = PETSC_NULL; 3125 if (numProcs == 1) PetscFunctionReturn(0); 3126 3127 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3128 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3129 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3130 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3131 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3132 if (!rank) numRemoteRanks = numProcs; 3133 else numRemoteRanks = 0; 3134 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3135 for (p = 0; p < numRemoteRanks; ++p) { 3136 remoteRanks[p].rank = p; 3137 remoteRanks[p].index = 0; 3138 } 3139 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3140 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3141 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3142 if (flg) { 3143 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3144 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3145 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3146 if (origCellPart) { 3147 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3148 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3149 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3150 } 3151 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3152 } 3153 /* Close the partition over the mesh */ 3154 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3155 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3156 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3157 /* Create new mesh */ 3158 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3159 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3160 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3161 pmesh = (DM_Plex*) (*dmParallel)->data; 3162 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3163 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3164 if (flg) { 3165 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3166 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3167 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3168 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3169 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3170 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3171 } 3172 /* Distribute cone section */ 3173 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3174 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3175 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3176 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3177 { 3178 PetscInt pStart, pEnd, p; 3179 3180 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3181 for (p = pStart; p < pEnd; ++p) { 3182 PetscInt coneSize; 3183 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3184 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3185 } 3186 } 3187 /* Communicate and renumber cones */ 3188 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3189 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3190 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3191 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3192 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3193 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3194 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3195 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3196 if (flg) { 3197 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3198 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3199 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3200 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3201 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3202 } 3203 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3204 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3205 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3206 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3207 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3208 /* Create supports and stratify sieve */ 3209 { 3210 PetscInt pStart, pEnd; 3211 3212 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3213 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3214 } 3215 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3216 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3217 /* Distribute Coordinates */ 3218 { 3219 PetscSection originalCoordSection, newCoordSection; 3220 Vec originalCoordinates, newCoordinates; 3221 const char *name; 3222 3223 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3224 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3225 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3226 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3227 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3228 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3229 3230 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3231 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3232 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3233 } 3234 /* Distribute labels */ 3235 { 3236 DMLabel next = mesh->labels, newNext = pmesh->labels; 3237 PetscInt numLabels = 0, l; 3238 3239 /* Bcast number of labels */ 3240 while (next) { 3241 ++numLabels; next = next->next; 3242 } 3243 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3244 next = mesh->labels; 3245 for (l = 0; l < numLabels; ++l) { 3246 DMLabel newLabel; 3247 const PetscInt *partArray; 3248 char *name; 3249 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3250 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3251 PetscInt nameSize, s, p; 3252 PetscBool isdepth; 3253 size_t len = 0; 3254 3255 /* Bcast name (could filter for no points) */ 3256 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3257 nameSize = len; 3258 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3259 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3260 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3261 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3262 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3263 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3264 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3265 newLabel->name = name; 3266 /* Bcast numStrata (could filter for no points in stratum) */ 3267 if (!rank) newLabel->numStrata = next->numStrata; 3268 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3269 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3270 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3271 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3272 /* Bcast stratumValues (could filter for no points in stratum) */ 3273 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3274 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3275 /* Find size on each process and Scatter */ 3276 if (!rank) { 3277 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3278 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3279 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3280 for (s = 0; s < next->numStrata; ++s) { 3281 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3282 const PetscInt point = next->points[p]; 3283 PetscInt proc; 3284 3285 for (proc = 0; proc < numProcs; ++proc) { 3286 PetscInt dof, off, pPart; 3287 3288 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3289 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3290 for (pPart = off; pPart < off+dof; ++pPart) { 3291 if (partArray[pPart] == point) { 3292 ++stratumSizes[proc*next->numStrata+s]; 3293 break; 3294 } 3295 } 3296 } 3297 } 3298 } 3299 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3300 } 3301 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3302 /* Calculate stratumOffsets */ 3303 newLabel->stratumOffsets[0] = 0; 3304 for (s = 0; s < newLabel->numStrata; ++s) { 3305 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3306 } 3307 /* Pack points and Scatter */ 3308 if (!rank) { 3309 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3310 displs[0] = 0; 3311 for (p = 0; p < numProcs; ++p) { 3312 sendcnts[p] = 0; 3313 for (s = 0; s < next->numStrata; ++s) { 3314 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3315 } 3316 offsets[p] = displs[p]; 3317 displs[p+1] = displs[p] + sendcnts[p]; 3318 } 3319 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3320 for (s = 0; s < next->numStrata; ++s) { 3321 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3322 const PetscInt point = next->points[p]; 3323 PetscInt proc; 3324 3325 for (proc = 0; proc < numProcs; ++proc) { 3326 PetscInt dof, off, pPart; 3327 3328 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3329 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3330 for (pPart = off; pPart < off+dof; ++pPart) { 3331 if (partArray[pPart] == point) { 3332 points[offsets[proc]++] = point; 3333 break; 3334 } 3335 } 3336 } 3337 } 3338 } 3339 } 3340 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3341 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3342 ierr = PetscFree(points);CHKERRQ(ierr); 3343 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3344 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3345 /* Renumber points */ 3346 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3347 /* Sort points */ 3348 for (s = 0; s < newLabel->numStrata; ++s) { 3349 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3350 } 3351 /* Insert into list */ 3352 if (newNext) newNext->next = newLabel; 3353 else pmesh->labels = newLabel; 3354 newNext = newLabel; 3355 if (!rank) next = next->next; 3356 } 3357 } 3358 /* Cleanup Partition */ 3359 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3360 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3361 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3362 ierr = ISDestroy(&part);CHKERRQ(ierr); 3363 /* Create point SF for parallel mesh */ 3364 { 3365 const PetscInt *leaves; 3366 PetscSFNode *remotePoints, *rowners, *lowners; 3367 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3368 PetscInt pStart, pEnd; 3369 3370 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3371 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3372 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3373 for (p=0; p<numRoots; p++) { 3374 rowners[p].rank = -1; 3375 rowners[p].index = -1; 3376 } 3377 if (origCellPart) { 3378 /* Make sure cells in the original partition are not assigned to other procs */ 3379 const PetscInt *origCells; 3380 3381 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3382 for (p = 0; p < numProcs; ++p) { 3383 PetscInt dof, off, d; 3384 3385 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3386 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3387 for (d = off; d < off+dof; ++d) { 3388 rowners[origCells[d]].rank = p; 3389 } 3390 } 3391 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3392 } 3393 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3394 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3395 3396 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3397 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3398 for (p = 0; p < numLeaves; ++p) { 3399 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3400 lowners[p].rank = rank; 3401 lowners[p].index = leaves ? leaves[p] : p; 3402 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3403 lowners[p].rank = -2; 3404 lowners[p].index = -2; 3405 } 3406 } 3407 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3408 rowners[p].rank = -3; 3409 rowners[p].index = -3; 3410 } 3411 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3412 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3413 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3414 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3415 for (p = 0; p < numLeaves; ++p) { 3416 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3417 if (lowners[p].rank != rank) ++numGhostPoints; 3418 } 3419 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3420 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3421 for (p = 0, gp = 0; p < numLeaves; ++p) { 3422 if (lowners[p].rank != rank) { 3423 ghostPoints[gp] = leaves ? leaves[p] : p; 3424 remotePoints[gp].rank = lowners[p].rank; 3425 remotePoints[gp].index = lowners[p].index; 3426 ++gp; 3427 } 3428 } 3429 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3430 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3431 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3432 } 3433 /* Cleanup */ 3434 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3435 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3436 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3437 PetscFunctionReturn(0); 3438 } 3439 3440 #undef __FUNCT__ 3441 #define __FUNCT__ "DMPlexRenumber_Private" 3442 /* 3443 Reasons to renumber: 3444 3445 1) Permute points, e.g. bandwidth reduction (Renumber) 3446 3447 a) Must not mix strata 3448 3449 2) Shift numbers for point insertion (Shift) 3450 3451 a) Want operation brken into parts so that insertion can be interleaved 3452 3453 renumbering - An IS which provides the new numbering 3454 */ 3455 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3456 { 3457 PetscFunctionBegin; 3458 PetscFunctionReturn(0); 3459 } 3460 3461 #undef __FUNCT__ 3462 #define __FUNCT__ "DMPlexShiftPoint_Private" 3463 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3464 { 3465 if (depth < 0) return p; 3466 /* Cells */ if (p < depthEnd[depth]) return p; 3467 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3468 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3469 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3470 } 3471 3472 #undef __FUNCT__ 3473 #define __FUNCT__ "DMPlexShiftSizes_Private" 3474 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3475 { 3476 PetscInt *depthEnd; 3477 PetscInt depth = 0, d, pStart, pEnd, p; 3478 PetscErrorCode ierr; 3479 3480 PetscFunctionBegin; 3481 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3482 if (depth < 0) PetscFunctionReturn(0); 3483 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3484 /* Step 1: Expand chart */ 3485 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3486 for (d = 0; d <= depth; ++d) { 3487 pEnd += depthShift[d]; 3488 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3489 } 3490 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3491 /* Step 2: Set cone and support sizes */ 3492 for (d = 0; d <= depth; ++d) { 3493 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3494 for (p = pStart; p < pEnd; ++p) { 3495 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3496 PetscInt size; 3497 3498 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3499 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3500 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3501 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3502 } 3503 } 3504 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3505 PetscFunctionReturn(0); 3506 } 3507 3508 #undef __FUNCT__ 3509 #define __FUNCT__ "DMPlexShiftPoints_Private" 3510 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3511 { 3512 PetscInt *depthEnd, *newpoints; 3513 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3514 PetscErrorCode ierr; 3515 3516 PetscFunctionBegin; 3517 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3518 if (depth < 0) PetscFunctionReturn(0); 3519 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3520 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3521 for (d = 0; d <= depth; ++d) { 3522 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3523 } 3524 /* Step 5: Set cones and supports */ 3525 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3526 for (p = pStart; p < pEnd; ++p) { 3527 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3528 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3529 3530 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3531 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3532 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3533 for (i = 0; i < size; ++i) { 3534 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3535 } 3536 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3537 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3538 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3539 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3540 for (i = 0; i < size; ++i) { 3541 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3542 } 3543 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3544 } 3545 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3546 PetscFunctionReturn(0); 3547 } 3548 3549 #undef __FUNCT__ 3550 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3551 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3552 { 3553 PetscSection coordSection, newCoordSection; 3554 Vec coordinates, newCoordinates; 3555 PetscScalar *coords, *newCoords; 3556 PetscInt *depthEnd, coordSize; 3557 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3558 PetscErrorCode ierr; 3559 3560 PetscFunctionBegin; 3561 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3562 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3563 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3564 for (d = 0; d <= depth; ++d) { 3565 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3566 } 3567 /* Step 8: Convert coordinates */ 3568 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3569 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3570 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3571 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3572 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3573 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3574 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3575 for (v = vStartNew; v < vEndNew; ++v) { 3576 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3577 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3578 } 3579 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3580 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3581 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3582 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3583 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3584 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3585 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3586 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3587 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3588 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3589 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3590 for (v = vStart; v < vEnd; ++v) { 3591 PetscInt dof, off, noff, d; 3592 3593 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3594 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3595 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3596 for (d = 0; d < dof; ++d) { 3597 newCoords[noff+d] = coords[off+d]; 3598 } 3599 } 3600 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3601 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3602 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3603 PetscFunctionReturn(0); 3604 } 3605 3606 #undef __FUNCT__ 3607 #define __FUNCT__ "DMPlexShiftSF_Private" 3608 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3609 { 3610 PetscInt *depthEnd; 3611 PetscInt depth = 0, d; 3612 PetscSF sfPoint, sfPointNew; 3613 const PetscSFNode *remotePoints; 3614 PetscSFNode *gremotePoints; 3615 const PetscInt *localPoints; 3616 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3617 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3618 PetscMPIInt numProcs; 3619 PetscErrorCode ierr; 3620 3621 PetscFunctionBegin; 3622 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3623 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3624 for (d = 0; d <= depth; ++d) { 3625 totShift += depthShift[d]; 3626 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3627 } 3628 /* Step 9: Convert pointSF */ 3629 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3630 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3631 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3632 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3633 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3634 if (numRoots >= 0) { 3635 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3636 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3637 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3638 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3639 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3640 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3641 for (l = 0; l < numLeaves; ++l) { 3642 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3643 gremotePoints[l].rank = remotePoints[l].rank; 3644 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3645 } 3646 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3647 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3648 } 3649 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3650 PetscFunctionReturn(0); 3651 } 3652 3653 #undef __FUNCT__ 3654 #define __FUNCT__ "DMPlexShiftLabels_Private" 3655 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3656 { 3657 PetscSF sfPoint; 3658 DMLabel vtkLabel, ghostLabel; 3659 PetscInt *depthEnd; 3660 const PetscSFNode *leafRemote; 3661 const PetscInt *leafLocal; 3662 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3663 PetscMPIInt rank; 3664 PetscErrorCode ierr; 3665 3666 PetscFunctionBegin; 3667 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3668 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3669 for (d = 0; d <= depth; ++d) { 3670 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3671 } 3672 /* Step 10: Convert labels */ 3673 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3674 for (l = 0; l < numLabels; ++l) { 3675 DMLabel label, newlabel; 3676 const char *lname; 3677 PetscBool isDepth; 3678 IS valueIS; 3679 const PetscInt *values; 3680 PetscInt numValues, val; 3681 3682 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3683 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3684 if (isDepth) continue; 3685 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3686 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3687 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3688 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3689 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3690 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3691 for (val = 0; val < numValues; ++val) { 3692 IS pointIS; 3693 const PetscInt *points; 3694 PetscInt numPoints, p; 3695 3696 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3697 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3698 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3699 for (p = 0; p < numPoints; ++p) { 3700 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3701 3702 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3703 } 3704 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3705 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3706 } 3707 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3708 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3709 } 3710 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3711 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3712 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3713 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3714 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3715 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3716 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3717 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3718 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3719 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3720 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3721 for (; c < leafLocal[l] && c < cEnd; ++c) { 3722 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3723 } 3724 if (leafLocal[l] >= cEnd) break; 3725 if (leafRemote[l].rank == rank) { 3726 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3727 } else { 3728 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3729 } 3730 } 3731 for (; c < cEnd; ++c) { 3732 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3733 } 3734 if (0) { 3735 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3736 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3737 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3738 } 3739 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3740 for (f = fStart; f < fEnd; ++f) { 3741 PetscInt numCells; 3742 3743 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3744 if (numCells < 2) { 3745 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3746 } else { 3747 const PetscInt *cells = PETSC_NULL; 3748 PetscInt vA, vB; 3749 3750 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3751 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3752 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3753 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3754 } 3755 } 3756 if (0) { 3757 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3758 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3759 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3760 } 3761 PetscFunctionReturn(0); 3762 } 3763 3764 #undef __FUNCT__ 3765 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3766 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3767 { 3768 DMLabel label; 3769 IS valueIS; 3770 const PetscInt *values; 3771 PetscInt *depthShift; 3772 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3773 PetscErrorCode ierr; 3774 3775 PetscFunctionBegin; 3776 /* Count ghost cells */ 3777 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3778 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3779 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3780 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3781 3782 *numGhostCells = 0; 3783 for (fs = 0; fs < numFS; ++fs) { 3784 PetscInt numBdFaces; 3785 3786 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3787 3788 *numGhostCells += numBdFaces; 3789 } 3790 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3791 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3792 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3793 if (depth >= 0) depthShift[depth] = *numGhostCells; 3794 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3795 /* Step 3: Set cone/support sizes for new points */ 3796 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3797 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3798 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3799 } 3800 for (fs = 0; fs < numFS; ++fs) { 3801 IS faceIS; 3802 const PetscInt *faces; 3803 PetscInt numFaces, f; 3804 3805 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3806 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3807 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3808 for (f = 0; f < numFaces; ++f) { 3809 PetscInt size; 3810 3811 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3812 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3813 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3814 } 3815 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3816 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3817 } 3818 /* Step 4: Setup ghosted DM */ 3819 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3820 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3821 /* Step 6: Set cones and supports for new points */ 3822 ghostCell = cEnd; 3823 for (fs = 0; fs < numFS; ++fs) { 3824 IS faceIS; 3825 const PetscInt *faces; 3826 PetscInt numFaces, f; 3827 3828 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3829 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3830 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3831 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3832 PetscInt newFace = faces[f] + *numGhostCells; 3833 3834 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3835 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3836 } 3837 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3838 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3839 } 3840 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3841 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3842 /* Step 7: Stratify */ 3843 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3844 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3845 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3846 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3847 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3848 PetscFunctionReturn(0); 3849 } 3850 3851 #undef __FUNCT__ 3852 #define __FUNCT__ "DMPlexConstructGhostCells" 3853 /*@C 3854 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3855 3856 Collective on dm 3857 3858 Input Parameters: 3859 + dm - The original DM 3860 - labelName - The label specifying the boundary faces (this could be auto-generated) 3861 3862 Output Parameters: 3863 + numGhostCells - The number of ghost cells added to the DM 3864 - dmGhosted - The new DM 3865 3866 Level: developer 3867 3868 .seealso: DMCreate() 3869 */ 3870 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3871 { 3872 DM gdm; 3873 PetscInt dim; 3874 PetscErrorCode ierr; 3875 3876 PetscFunctionBegin; 3877 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3878 PetscValidPointer(numGhostCells, 3); 3879 PetscValidPointer(dmGhosted, 4); 3880 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3881 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3882 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3883 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3884 switch (dim) { 3885 case 2: 3886 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3887 break; 3888 default: 3889 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3890 } 3891 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3892 *dmGhosted = gdm; 3893 PetscFunctionReturn(0); 3894 } 3895 3896 #undef __FUNCT__ 3897 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3898 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, const char labelName[], DM sdm) 3899 { 3900 MPI_Comm comm = ((PetscObject) dm)->comm; 3901 DMLabel label; 3902 IS valueIS, *pointIS; 3903 const PetscInt *values, **splitPoints; 3904 PetscSection coordSection; 3905 Vec coordinates; 3906 PetscScalar *coords; 3907 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3908 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3909 PetscErrorCode ierr; 3910 3911 PetscFunctionBegin; 3912 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3913 /* Count split points and add cohesive cells */ 3914 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 3915 if (label) { 3916 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3917 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3918 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3919 } 3920 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3921 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3922 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3923 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3924 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3925 for (d = 0; d <= depth; ++d) { 3926 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3927 numSplitPoints[d] = 0; 3928 splitPoints[d] = PETSC_NULL; 3929 pointIS[d] = PETSC_NULL; 3930 } 3931 for (sp = 0; sp < numSP; ++sp) { 3932 const PetscInt dep = values[sp]; 3933 3934 if ((dep < 0) || (dep > depth)) continue; 3935 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3936 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3937 if (pointIS[dep]) { 3938 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3939 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3940 } 3941 } 3942 if (depth >= 0) { 3943 /* Calculate number of additional points */ 3944 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3945 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3946 /* Calculate hybrid bound for each dimension */ 3947 pMaxNew[0] += depthShift[depth]; 3948 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3949 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3950 3951 /* Calculate point offset for each dimension */ 3952 depthOffset[depth] = 0; 3953 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3954 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3955 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3956 } 3957 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3958 /* Step 3: Set cone/support sizes for new points */ 3959 for (dep = 0; dep <= depth; ++dep) { 3960 for (p = 0; p < numSplitPoints[dep]; ++p) { 3961 const PetscInt oldp = splitPoints[dep][p]; 3962 const PetscInt newp = depthOffset[dep] + oldp; 3963 const PetscInt splitp = pMaxNew[dep] + p; 3964 const PetscInt *support; 3965 PetscInt coneSize, supportSize, q, e; 3966 3967 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3968 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3969 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3970 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3971 if (dep == depth-1) { 3972 const PetscInt ccell = pMaxNew[depth] + p; 3973 /* Add cohesive cells, they are prisms */ 3974 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3975 } else if (dep == 0) { 3976 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3977 3978 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3979 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3980 for (e = 0, q = 0; e < supportSize; ++e) { 3981 PetscInt val; 3982 3983 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3984 if ((val == 1) || (val == (shift + 1))) ++q; 3985 } 3986 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3987 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3988 for (e = 0, q = 0; e < supportSize; ++e) { 3989 PetscInt val; 3990 3991 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3992 if ((val == 1) || (val == -(shift + 1))) ++q; 3993 } 3994 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3995 /* Add cohesive edges */ 3996 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3997 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3998 } else if (dep == dim-2) { 3999 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4000 /* Split old edge: Faces in positive side cells and old split faces */ 4001 for (e = 0, q = 0; e < supportSize; ++e) { 4002 PetscInt val; 4003 4004 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4005 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4006 } 4007 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4008 /* Split new edge: Faces in negative side cells and new split faces */ 4009 for (e = 0, q = 0; e < supportSize; ++e) { 4010 PetscInt val; 4011 4012 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4013 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4014 } 4015 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4016 } 4017 } 4018 } 4019 /* Step 4: Setup split DM */ 4020 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4021 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4022 /* Step 6: Set cones and supports for new points */ 4023 for (dep = 0; dep <= depth; ++dep) { 4024 for (p = 0; p < numSplitPoints[dep]; ++p) { 4025 const PetscInt oldp = splitPoints[dep][p]; 4026 const PetscInt newp = depthOffset[dep] + oldp; 4027 const PetscInt splitp = pMaxNew[dep] + p; 4028 const PetscInt *cone, *support, *ornt; 4029 PetscInt coneSize, supportSize, q, v, e, s; 4030 4031 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4032 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4033 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4034 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4035 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4036 if (dep == depth-1) { 4037 const PetscInt ccell = pMaxNew[depth] + p; 4038 const PetscInt *supportF; 4039 4040 /* Split face: copy in old face to new face to start */ 4041 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4042 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4043 /* Split old face: old vertices/edges in cone so no change */ 4044 /* Split new face: new vertices/edges in cone */ 4045 for (q = 0; q < coneSize; ++q) { 4046 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4047 4048 coneNew[2+q] = pMaxNew[dim-2] + v; 4049 } 4050 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4051 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4052 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4053 coneNew[0] = newp; 4054 coneNew[1] = splitp; 4055 for (q = 0; q < coneSize; ++q) { 4056 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4057 } 4058 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4059 4060 4061 for (s = 0; s < supportSize; ++s) { 4062 PetscInt val; 4063 4064 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4065 if (val < 0) { 4066 /* Split old face: Replace negative side cell with cohesive cell */ 4067 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4068 } else { 4069 /* Split new face: Replace positive side cell with cohesive cell */ 4070 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4071 } 4072 } 4073 } else if (dep == 0) { 4074 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4075 4076 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4077 for (e = 0, q = 0; e < supportSize; ++e) { 4078 PetscInt val; 4079 4080 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4081 if ((val == 1) || (val == (shift + 1))) { 4082 supportNew[q++] = depthOffset[1] + support[e]; 4083 } 4084 } 4085 supportNew[q] = cedge; 4086 4087 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4088 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4089 for (e = 0, q = 0; e < supportSize; ++e) { 4090 PetscInt val, edge; 4091 4092 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4093 if (val == 1) { 4094 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4095 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4096 supportNew[q++] = pMaxNew[1] + edge; 4097 } else if (val == -(shift + 1)) { 4098 supportNew[q++] = depthOffset[1] + support[e]; 4099 } 4100 } 4101 supportNew[q] = cedge; 4102 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4103 /* Cohesive edge: Old and new split vertex, punting on support */ 4104 coneNew[0] = newp; 4105 coneNew[1] = splitp; 4106 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4107 } else if (dep == dim-2) { 4108 /* Split old edge: old vertices in cone so no change */ 4109 /* Split new edge: new vertices in cone */ 4110 for (q = 0; q < coneSize; ++q) { 4111 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4112 4113 coneNew[q] = pMaxNew[dim-3] + v; 4114 } 4115 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4116 /* Split old edge: Faces in positive side cells and old split faces */ 4117 for (e = 0, q = 0; e < supportSize; ++e) { 4118 PetscInt val; 4119 4120 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4121 if ((val == dim-1) || (val == (shift + dim-1))) { 4122 supportNew[q++] = depthOffset[dim-1] + support[e]; 4123 } 4124 } 4125 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4126 /* Split new edge: Faces in negative side cells and new split faces */ 4127 for(e = 0, q = 0; e < supportSize; ++e) { 4128 PetscInt val, face; 4129 4130 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4131 if (val == dim-1) { 4132 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4133 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4134 supportNew[q++] = pMaxNew[dim-1] + face; 4135 } else if (val == -(shift + dim-1)) { 4136 supportNew[q++] = depthOffset[dim-1] + support[e]; 4137 } 4138 } 4139 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4140 } 4141 } 4142 } 4143 /* Step 6b: Replace split points in negative side cones */ 4144 for (sp = 0; sp < numSP; ++sp) { 4145 PetscInt dep = values[sp]; 4146 IS pIS; 4147 PetscInt numPoints; 4148 const PetscInt *points; 4149 4150 if (dep >= 0) continue; 4151 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4152 if (!pIS) continue; 4153 dep = -dep - shift; 4154 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4155 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4156 for (p = 0; p < numPoints; ++p) { 4157 const PetscInt oldp = points[p]; 4158 const PetscInt newp = depthOffset[dep] + oldp; 4159 const PetscInt *cone; 4160 PetscInt coneSize, c; 4161 PetscBool replaced = PETSC_FALSE; 4162 4163 /* Negative edge: replace split vertex */ 4164 /* Negative cell: replace split face */ 4165 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4166 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4167 for (c = 0; c < coneSize; ++c) { 4168 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4169 PetscInt csplitp, cp, val; 4170 4171 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4172 if (val == dep-1) { 4173 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4174 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4175 csplitp = pMaxNew[dep-1] + cp; 4176 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4177 replaced = PETSC_TRUE; 4178 } 4179 } 4180 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4181 } 4182 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4183 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4184 } 4185 /* Step 7: Stratify */ 4186 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4187 /* Step 8: Coordinates */ 4188 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4189 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4190 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4191 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4192 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4193 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4194 const PetscInt splitp = pMaxNew[0] + v; 4195 PetscInt dof, off, soff, d; 4196 4197 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4198 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4199 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4200 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4201 } 4202 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4203 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4204 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4205 /* Step 10: Labels */ 4206 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4207 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4208 for (dep = 0; dep <= depth; ++dep) { 4209 for (p = 0; p < numSplitPoints[dep]; ++p) { 4210 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4211 const PetscInt splitp = pMaxNew[dep] + p; 4212 PetscInt l; 4213 4214 for (l = 0; l < numLabels; ++l) { 4215 DMLabel label; 4216 const char *lname; 4217 PetscInt val; 4218 4219 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4220 ierr = DMPlexGetLabel(sdm, lname, &label);CHKERRQ(ierr); 4221 ierr = DMLabelGetValue(label, newp, &val);CHKERRQ(ierr); 4222 if (val >= 0) { 4223 ierr = DMLabelSetValue(label, splitp, val);CHKERRQ(ierr); 4224 if (dep == 0) { 4225 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4226 ierr = DMLabelSetValue(label, cedge, val);CHKERRQ(ierr); 4227 } 4228 } 4229 } 4230 } 4231 } 4232 for (sp = 0; sp < numSP; ++sp) { 4233 const PetscInt dep = values[sp]; 4234 4235 if ((dep < 0) || (dep > depth)) continue; 4236 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4237 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4238 } 4239 if (label) { 4240 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4241 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4242 } 4243 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4244 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4245 PetscFunctionReturn(0); 4246 } 4247 4248 #undef __FUNCT__ 4249 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4250 /*@C 4251 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4252 4253 Collective on dm 4254 4255 Input Parameters: 4256 + dm - The original DM 4257 - labelName - The label specifying the boundary faces (this could be auto-generated) 4258 4259 Output Parameters: 4260 - dmSplit - The new DM 4261 4262 Level: developer 4263 4264 .seealso: DMCreate() 4265 */ 4266 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, const char labelName[], DM *dmSplit) 4267 { 4268 DM sdm; 4269 PetscInt dim; 4270 PetscErrorCode ierr; 4271 4272 PetscFunctionBegin; 4273 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4274 PetscValidPointer(dmSplit, 4); 4275 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4276 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4277 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4278 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4279 switch (dim) { 4280 case 2: 4281 case 3: 4282 ierr = DMPlexConstructCohesiveCells_Private(dm, labelName, sdm);CHKERRQ(ierr); 4283 break; 4284 default: 4285 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4286 } 4287 *dmSplit = sdm; 4288 PetscFunctionReturn(0); 4289 } 4290 4291 #undef __FUNCT__ 4292 #define __FUNCT__ "DMLabelCohesiveComplete" 4293 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4294 { 4295 IS dimIS; 4296 const PetscInt *points; 4297 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4298 PetscErrorCode ierr; 4299 4300 PetscFunctionBegin; 4301 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4302 /* Cell orientation for face gives the side of the fault */ 4303 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4304 if (!dimIS) PetscFunctionReturn(0); 4305 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4306 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4307 for (p = 0; p < numPoints; ++p) { 4308 const PetscInt *support; 4309 PetscInt supportSize, s; 4310 4311 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4312 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4313 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4314 for (s = 0; s < supportSize; ++s) { 4315 const PetscInt *cone, *ornt; 4316 PetscInt coneSize, c; 4317 PetscBool pos = PETSC_TRUE; 4318 4319 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4320 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4321 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4322 for(c = 0; c < coneSize; ++c) { 4323 if (cone[c] == points[p]) { 4324 if (ornt[c] >= 0) { 4325 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4326 } else { 4327 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4328 pos = PETSC_FALSE; 4329 } 4330 break; 4331 } 4332 } 4333 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]); 4334 /* Put faces touching the fault in the label */ 4335 for (c = 0; c < coneSize; ++c) { 4336 const PetscInt point = cone[c]; 4337 4338 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4339 if (val == -1) { 4340 PetscInt *closure = PETSC_NULL; 4341 PetscInt closureSize, cl; 4342 4343 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4344 for (cl = 0; cl < closureSize*2; cl += 2) { 4345 const PetscInt clp = closure[cl]; 4346 4347 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4348 if ((val >= 0) && (val < dim-1)) { 4349 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4350 break; 4351 } 4352 } 4353 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4354 } 4355 } 4356 } 4357 } 4358 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4359 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4360 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4361 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4362 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4363 if (!dimIS) PetscFunctionReturn(0); 4364 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4365 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4366 for (p = 0; p < numPoints; ++p) { 4367 PetscInt *star = PETSC_NULL; 4368 PetscInt starSize, s; 4369 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4370 4371 /* First mark cells connected to the fault */ 4372 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4373 while (again) { 4374 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4375 again = 0; 4376 for (s = 0; s < starSize*2; s += 2) { 4377 const PetscInt point = star[s]; 4378 const PetscInt *cone; 4379 PetscInt coneSize, c; 4380 4381 if ((point < cStart) || (point >= cEnd)) continue; 4382 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4383 if (val != -1) continue; 4384 again = 2; 4385 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4386 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4387 for (c = 0; c < coneSize; ++c) { 4388 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4389 if (val != -1) { 4390 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); 4391 if (val > 0) { 4392 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4393 } else { 4394 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4395 } 4396 again = 1; 4397 break; 4398 } 4399 } 4400 } 4401 } 4402 /* Classify the rest by cell membership */ 4403 for (s = 0; s < starSize*2; s += 2) { 4404 const PetscInt point = star[s]; 4405 4406 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4407 if (val == -1) { 4408 PetscInt *sstar = PETSC_NULL; 4409 PetscInt sstarSize, ss; 4410 PetscBool marked = PETSC_FALSE; 4411 4412 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4413 for (ss = 0; ss < sstarSize*2; ss += 2) { 4414 const PetscInt spoint = sstar[ss]; 4415 4416 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4417 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4418 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4419 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4420 if (val > 0) { 4421 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4422 } else { 4423 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4424 } 4425 marked = PETSC_TRUE; 4426 break; 4427 } 4428 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4429 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4430 } 4431 } 4432 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4433 } 4434 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4435 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4436 PetscFunctionReturn(0); 4437 } 4438 4439 #undef __FUNCT__ 4440 #define __FUNCT__ "DMPlexInterpolate_2D" 4441 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4442 { 4443 DM idm; 4444 DM_Plex *mesh; 4445 PetscHashIJ edgeTable; 4446 PetscInt *off; 4447 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4448 PetscInt numEdges, firstEdge, edge, e; 4449 PetscErrorCode ierr; 4450 4451 PetscFunctionBegin; 4452 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4453 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4454 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4455 numCells = cEnd - cStart; 4456 numVertices = vEnd - vStart; 4457 firstEdge = numCells + numVertices; 4458 numEdges = 0; 4459 /* Count edges using algorithm from CreateNeighborCSR */ 4460 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4461 if (off) { 4462 PetscInt numCorners = 0; 4463 4464 numEdges = off[numCells]/2; 4465 #if 0 4466 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4467 numEdges += 3*numCells - off[numCells]; 4468 #else 4469 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4470 for (c = cStart; c < cEnd; ++c) { 4471 PetscInt coneSize; 4472 4473 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4474 numCorners += coneSize; 4475 } 4476 numEdges += numCorners - off[numCells]; 4477 #endif 4478 } 4479 #if 0 4480 /* Check Euler characteristic V - E + F = 1 */ 4481 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4482 #endif 4483 /* Create interpolated mesh */ 4484 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4485 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4486 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4487 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4488 for (c = 0; c < numCells; ++c) { 4489 PetscInt numCorners; 4490 4491 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4492 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4493 } 4494 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4495 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4496 } 4497 ierr = DMSetUp(idm);CHKERRQ(ierr); 4498 /* Get edge cones from subsets of cell vertices */ 4499 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4500 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4501 4502 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4503 const PetscInt *cellFaces; 4504 PetscInt numCellFaces, faceSize, cf; 4505 4506 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4507 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4508 for (cf = 0; cf < numCellFaces; ++cf) { 4509 #if 1 4510 PetscHashIJKey key; 4511 4512 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4513 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4514 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4515 if (e < 0) { 4516 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4517 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4518 e = edge++; 4519 } 4520 #else 4521 PetscBool found = PETSC_FALSE; 4522 4523 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4524 for (e = firstEdge; e < edge; ++e) { 4525 const PetscInt *cone; 4526 4527 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4528 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4529 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4530 found = PETSC_TRUE; 4531 break; 4532 } 4533 } 4534 if (!found) { 4535 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4536 ++edge; 4537 } 4538 #endif 4539 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4540 } 4541 } 4542 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4543 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4544 ierr = PetscFree(off);CHKERRQ(ierr); 4545 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4546 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4547 mesh = (DM_Plex*) (idm)->data; 4548 /* Orient edges */ 4549 for (c = 0; c < numCells; ++c) { 4550 const PetscInt *cone = PETSC_NULL, *cellFaces; 4551 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4552 4553 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4554 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4555 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4556 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4557 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4558 for (cf = 0; cf < numCellFaces; ++cf) { 4559 const PetscInt *econe = PETSC_NULL; 4560 PetscInt esize; 4561 4562 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4563 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4564 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]); 4565 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4566 /* Correctly oriented */ 4567 mesh->coneOrientations[coff+cf] = 0; 4568 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4569 /* Start at index 1, and reverse orientation */ 4570 mesh->coneOrientations[coff+cf] = -(1+1); 4571 } 4572 } 4573 } 4574 *dmInt = idm; 4575 PetscFunctionReturn(0); 4576 } 4577 4578 #undef __FUNCT__ 4579 #define __FUNCT__ "DMPlexInterpolate_3D" 4580 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4581 { 4582 DM idm, fdm; 4583 DM_Plex *mesh; 4584 PetscInt *off; 4585 const PetscInt numCorners = 4; 4586 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4587 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4588 PetscErrorCode ierr; 4589 4590 PetscFunctionBegin; 4591 { 4592 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4593 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4594 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4595 } 4596 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4597 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4598 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4599 numCells = cEnd - cStart; 4600 numVertices = vEnd - vStart; 4601 firstFace = numCells + numVertices; 4602 numFaces = 0; 4603 /* Count faces using algorithm from CreateNeighborCSR */ 4604 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4605 if (off) { 4606 numFaces = off[numCells]/2; 4607 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4608 numFaces += 4*numCells - off[numCells]; 4609 } 4610 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4611 firstEdge = firstFace + numFaces; 4612 numEdges = numVertices + numFaces - numCells - 1; 4613 /* Create interpolated mesh */ 4614 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4615 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4616 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4617 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4618 for (c = 0; c < numCells; ++c) { 4619 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4620 } 4621 for (f = firstFace; f < firstFace+numFaces; ++f) { 4622 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4623 } 4624 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4625 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4626 } 4627 ierr = DMSetUp(idm);CHKERRQ(ierr); 4628 /* Get face cones from subsets of cell vertices */ 4629 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4630 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4631 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4632 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4633 for (f = firstFace; f < firstFace+numFaces; ++f) { 4634 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4635 } 4636 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4637 for (c = 0, face = firstFace; c < numCells; ++c) { 4638 const PetscInt *cellFaces; 4639 PetscInt numCellFaces, faceSize, cf; 4640 4641 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4642 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4643 for (cf = 0; cf < numCellFaces; ++cf) { 4644 PetscBool found = PETSC_FALSE; 4645 4646 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4647 for (f = firstFace; f < face; ++f) { 4648 const PetscInt *cone = PETSC_NULL; 4649 4650 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4651 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4652 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4653 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4654 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4655 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4656 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4657 found = PETSC_TRUE; 4658 break; 4659 } 4660 } 4661 if (!found) { 4662 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4663 /* Save the vertices for orientation calculation */ 4664 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4665 ++face; 4666 } 4667 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4668 } 4669 } 4670 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4671 /* Get edge cones from subsets of face vertices */ 4672 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4673 const PetscInt *cellFaces; 4674 PetscInt numCellFaces, faceSize, cf; 4675 4676 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4677 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4678 for (cf = 0; cf < numCellFaces; ++cf) { 4679 PetscBool found = PETSC_FALSE; 4680 4681 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4682 for (e = firstEdge; e < edge; ++e) { 4683 const PetscInt *cone = PETSC_NULL; 4684 4685 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4686 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4687 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4688 found = PETSC_TRUE; 4689 break; 4690 } 4691 } 4692 if (!found) { 4693 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4694 ++edge; 4695 } 4696 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4697 } 4698 } 4699 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4700 ierr = PetscFree(off);CHKERRQ(ierr); 4701 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4702 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4703 mesh = (DM_Plex*) (idm)->data; 4704 /* Orient edges */ 4705 for (f = firstFace; f < firstFace+numFaces; ++f) { 4706 const PetscInt *cone, *cellFaces; 4707 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4708 4709 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4710 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4711 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4712 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4713 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4714 for (cf = 0; cf < numCellFaces; ++cf) { 4715 const PetscInt *econe; 4716 PetscInt esize; 4717 4718 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4719 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4720 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]); 4721 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4722 /* Correctly oriented */ 4723 mesh->coneOrientations[coff+cf] = 0; 4724 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4725 /* Start at index 1, and reverse orientation */ 4726 mesh->coneOrientations[coff+cf] = -(1+1); 4727 } 4728 } 4729 } 4730 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4731 /* Orient faces */ 4732 for (c = 0; c < numCells; ++c) { 4733 const PetscInt *cone, *cellFaces; 4734 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4735 4736 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4737 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4738 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4739 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4740 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4741 for (cf = 0; cf < numCellFaces; ++cf) { 4742 PetscInt *origClosure = PETSC_NULL, *closure; 4743 PetscInt closureSize, i; 4744 4745 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4746 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4747 for (i = 4; i < 7; ++i) { 4748 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); 4749 } 4750 closure = &origClosure[4*2]; 4751 /* Remember that this is the orientation for edges, not vertices */ 4752 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4753 /* Correctly oriented */ 4754 mesh->coneOrientations[coff+cf] = 0; 4755 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4756 /* Shifted by 1 */ 4757 mesh->coneOrientations[coff+cf] = 1; 4758 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4759 /* Shifted by 2 */ 4760 mesh->coneOrientations[coff+cf] = 2; 4761 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4762 /* Start at edge 1, and reverse orientation */ 4763 mesh->coneOrientations[coff+cf] = -(1+1); 4764 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4765 /* Start at index 0, and reverse orientation */ 4766 mesh->coneOrientations[coff+cf] = -(0+1); 4767 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4768 /* Start at index 2, and reverse orientation */ 4769 mesh->coneOrientations[coff+cf] = -(2+1); 4770 } 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); 4771 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4772 } 4773 } 4774 { 4775 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4776 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4777 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4778 } 4779 *dmInt = idm; 4780 PetscFunctionReturn(0); 4781 } 4782 4783 #undef __FUNCT__ 4784 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4785 /* 4786 This takes as input the common mesh generator output, a list of the vertices for each cell 4787 */ 4788 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4789 { 4790 PetscInt *cone, c, p; 4791 PetscErrorCode ierr; 4792 4793 PetscFunctionBegin; 4794 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4795 for (c = 0; c < numCells; ++c) { 4796 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4797 } 4798 ierr = DMSetUp(dm);CHKERRQ(ierr); 4799 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4800 for (c = 0; c < numCells; ++c) { 4801 for (p = 0; p < numCorners; ++p) { 4802 cone[p] = cells[c*numCorners+p]+numCells; 4803 } 4804 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4805 } 4806 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4807 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4808 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4809 PetscFunctionReturn(0); 4810 } 4811 4812 #undef __FUNCT__ 4813 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4814 /* 4815 This takes as input the coordinates for each vertex 4816 */ 4817 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4818 { 4819 PetscSection coordSection; 4820 Vec coordinates; 4821 PetscScalar *coords; 4822 PetscInt coordSize, v, d; 4823 PetscErrorCode ierr; 4824 4825 PetscFunctionBegin; 4826 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4827 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4828 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4829 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4830 for (v = numCells; v < numCells+numVertices; ++v) { 4831 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4832 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4833 } 4834 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4835 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4836 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4837 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4838 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4839 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4840 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4841 for (v = 0; v < numVertices; ++v) { 4842 for (d = 0; d < spaceDim; ++d) { 4843 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4844 } 4845 } 4846 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4847 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4848 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4849 PetscFunctionReturn(0); 4850 } 4851 4852 #undef __FUNCT__ 4853 #define __FUNCT__ "DMPlexCreateFromCellList" 4854 /* 4855 This takes as input the common mesh generator output, a list of the vertices for each cell 4856 */ 4857 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4858 { 4859 PetscErrorCode ierr; 4860 4861 PetscFunctionBegin; 4862 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4863 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4864 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4865 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4866 if (interpolate) { 4867 DM idm; 4868 4869 switch (dim) { 4870 case 2: 4871 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4872 case 3: 4873 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4874 default: 4875 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4876 } 4877 ierr = DMDestroy(dm);CHKERRQ(ierr); 4878 *dm = idm; 4879 } 4880 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4881 PetscFunctionReturn(0); 4882 } 4883 4884 #if defined(PETSC_HAVE_TRIANGLE) 4885 #include <triangle.h> 4886 4887 #undef __FUNCT__ 4888 #define __FUNCT__ "InitInput_Triangle" 4889 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4890 { 4891 PetscFunctionBegin; 4892 inputCtx->numberofpoints = 0; 4893 inputCtx->numberofpointattributes = 0; 4894 inputCtx->pointlist = PETSC_NULL; 4895 inputCtx->pointattributelist = PETSC_NULL; 4896 inputCtx->pointmarkerlist = PETSC_NULL; 4897 inputCtx->numberofsegments = 0; 4898 inputCtx->segmentlist = PETSC_NULL; 4899 inputCtx->segmentmarkerlist = PETSC_NULL; 4900 inputCtx->numberoftriangleattributes = 0; 4901 inputCtx->trianglelist = PETSC_NULL; 4902 inputCtx->numberofholes = 0; 4903 inputCtx->holelist = PETSC_NULL; 4904 inputCtx->numberofregions = 0; 4905 inputCtx->regionlist = PETSC_NULL; 4906 PetscFunctionReturn(0); 4907 } 4908 4909 #undef __FUNCT__ 4910 #define __FUNCT__ "InitOutput_Triangle" 4911 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4912 { 4913 PetscFunctionBegin; 4914 outputCtx->numberofpoints = 0; 4915 outputCtx->pointlist = PETSC_NULL; 4916 outputCtx->pointattributelist = PETSC_NULL; 4917 outputCtx->pointmarkerlist = PETSC_NULL; 4918 outputCtx->numberoftriangles = 0; 4919 outputCtx->trianglelist = PETSC_NULL; 4920 outputCtx->triangleattributelist = PETSC_NULL; 4921 outputCtx->neighborlist = PETSC_NULL; 4922 outputCtx->segmentlist = PETSC_NULL; 4923 outputCtx->segmentmarkerlist = PETSC_NULL; 4924 outputCtx->numberofedges = 0; 4925 outputCtx->edgelist = PETSC_NULL; 4926 outputCtx->edgemarkerlist = PETSC_NULL; 4927 PetscFunctionReturn(0); 4928 } 4929 4930 #undef __FUNCT__ 4931 #define __FUNCT__ "FiniOutput_Triangle" 4932 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4933 { 4934 PetscFunctionBegin; 4935 free(outputCtx->pointmarkerlist); 4936 free(outputCtx->edgelist); 4937 free(outputCtx->edgemarkerlist); 4938 free(outputCtx->trianglelist); 4939 free(outputCtx->neighborlist); 4940 PetscFunctionReturn(0); 4941 } 4942 4943 #undef __FUNCT__ 4944 #define __FUNCT__ "DMPlexGenerate_Triangle" 4945 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4946 { 4947 MPI_Comm comm = ((PetscObject) boundary)->comm; 4948 PetscInt dim = 2; 4949 const PetscBool createConvexHull = PETSC_FALSE; 4950 const PetscBool constrained = PETSC_FALSE; 4951 struct triangulateio in; 4952 struct triangulateio out; 4953 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4954 PetscMPIInt rank; 4955 PetscErrorCode ierr; 4956 4957 PetscFunctionBegin; 4958 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4959 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4960 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4961 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4962 4963 in.numberofpoints = vEnd - vStart; 4964 if (in.numberofpoints > 0) { 4965 PetscSection coordSection; 4966 Vec coordinates; 4967 PetscScalar *array; 4968 4969 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4970 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4971 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4972 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4973 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4974 for (v = vStart; v < vEnd; ++v) { 4975 const PetscInt idx = v - vStart; 4976 PetscInt off, d; 4977 4978 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4979 for (d = 0; d < dim; ++d) { 4980 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4981 } 4982 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4983 } 4984 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4985 } 4986 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4987 in.numberofsegments = eEnd - eStart; 4988 if (in.numberofsegments > 0) { 4989 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4990 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4991 for (e = eStart; e < eEnd; ++e) { 4992 const PetscInt idx = e - eStart; 4993 const PetscInt *cone; 4994 4995 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4996 4997 in.segmentlist[idx*2+0] = cone[0] - vStart; 4998 in.segmentlist[idx*2+1] = cone[1] - vStart; 4999 5000 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5001 } 5002 } 5003 #if 0 /* Do not currently support holes */ 5004 PetscReal *holeCoords; 5005 PetscInt h, d; 5006 5007 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5008 if (in.numberofholes > 0) { 5009 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5010 for (h = 0; h < in.numberofholes; ++h) { 5011 for (d = 0; d < dim; ++d) { 5012 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5013 } 5014 } 5015 } 5016 #endif 5017 if (!rank) { 5018 char args[32]; 5019 5020 /* Take away 'Q' for verbose output */ 5021 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5022 if (createConvexHull) { 5023 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5024 } 5025 if (constrained) { 5026 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5027 } 5028 triangulate(args, &in, &out, PETSC_NULL); 5029 } 5030 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5031 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5032 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5033 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5034 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5035 5036 { 5037 const PetscInt numCorners = 3; 5038 const PetscInt numCells = out.numberoftriangles; 5039 const PetscInt numVertices = out.numberofpoints; 5040 const int *cells = out.trianglelist; 5041 const double *meshCoords = out.pointlist; 5042 5043 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5044 /* Set labels */ 5045 for (v = 0; v < numVertices; ++v) { 5046 if (out.pointmarkerlist[v]) { 5047 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5048 } 5049 } 5050 if (interpolate) { 5051 for (e = 0; e < out.numberofedges; e++) { 5052 if (out.edgemarkerlist[e]) { 5053 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5054 const PetscInt *edges; 5055 PetscInt numEdges; 5056 5057 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5058 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5059 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5060 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5061 } 5062 } 5063 } 5064 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5065 } 5066 #if 0 /* Do not currently support holes */ 5067 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5068 #endif 5069 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5070 PetscFunctionReturn(0); 5071 } 5072 5073 #undef __FUNCT__ 5074 #define __FUNCT__ "DMPlexRefine_Triangle" 5075 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5076 { 5077 MPI_Comm comm = ((PetscObject) dm)->comm; 5078 PetscInt dim = 2; 5079 struct triangulateio in; 5080 struct triangulateio out; 5081 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5082 PetscMPIInt rank; 5083 PetscErrorCode ierr; 5084 5085 PetscFunctionBegin; 5086 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5087 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5088 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5089 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5090 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5091 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5092 5093 in.numberofpoints = vEnd - vStart; 5094 if (in.numberofpoints > 0) { 5095 PetscSection coordSection; 5096 Vec coordinates; 5097 PetscScalar *array; 5098 5099 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5100 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5101 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5102 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5103 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5104 for (v = vStart; v < vEnd; ++v) { 5105 const PetscInt idx = v - vStart; 5106 PetscInt off, d; 5107 5108 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5109 for (d = 0; d < dim; ++d) { 5110 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5111 } 5112 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5113 } 5114 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5115 } 5116 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5117 5118 in.numberofcorners = 3; 5119 in.numberoftriangles = cEnd - cStart; 5120 5121 in.trianglearealist = (double*) maxVolumes; 5122 if (in.numberoftriangles > 0) { 5123 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5124 for (c = cStart; c < cEnd; ++c) { 5125 const PetscInt idx = c - cStart; 5126 PetscInt *closure = PETSC_NULL; 5127 PetscInt closureSize; 5128 5129 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5130 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5131 for (v = 0; v < 3; ++v) { 5132 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5133 } 5134 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5135 } 5136 } 5137 /* TODO: Segment markers are missing on input */ 5138 #if 0 /* Do not currently support holes */ 5139 PetscReal *holeCoords; 5140 PetscInt h, d; 5141 5142 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5143 if (in.numberofholes > 0) { 5144 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5145 for (h = 0; h < in.numberofholes; ++h) { 5146 for (d = 0; d < dim; ++d) { 5147 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5148 } 5149 } 5150 } 5151 #endif 5152 if (!rank) { 5153 char args[32]; 5154 5155 /* Take away 'Q' for verbose output */ 5156 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5157 triangulate(args, &in, &out, PETSC_NULL); 5158 } 5159 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5160 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5161 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5162 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5163 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5164 5165 { 5166 const PetscInt numCorners = 3; 5167 const PetscInt numCells = out.numberoftriangles; 5168 const PetscInt numVertices = out.numberofpoints; 5169 const int *cells = out.trianglelist; 5170 const double *meshCoords = out.pointlist; 5171 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5172 5173 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5174 /* Set labels */ 5175 for (v = 0; v < numVertices; ++v) { 5176 if (out.pointmarkerlist[v]) { 5177 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5178 } 5179 } 5180 if (interpolate) { 5181 PetscInt e; 5182 5183 for (e = 0; e < out.numberofedges; e++) { 5184 if (out.edgemarkerlist[e]) { 5185 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5186 const PetscInt *edges; 5187 PetscInt numEdges; 5188 5189 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5190 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5191 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5192 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5193 } 5194 } 5195 } 5196 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5197 } 5198 #if 0 /* Do not currently support holes */ 5199 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5200 #endif 5201 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5202 PetscFunctionReturn(0); 5203 } 5204 #endif 5205 5206 #if defined(PETSC_HAVE_TETGEN) 5207 #include <tetgen.h> 5208 #undef __FUNCT__ 5209 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5210 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5211 { 5212 MPI_Comm comm = ((PetscObject) boundary)->comm; 5213 const PetscInt dim = 3; 5214 ::tetgenio in; 5215 ::tetgenio out; 5216 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5217 PetscMPIInt rank; 5218 PetscErrorCode ierr; 5219 5220 PetscFunctionBegin; 5221 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5222 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5223 in.numberofpoints = vEnd - vStart; 5224 if (in.numberofpoints > 0) { 5225 PetscSection coordSection; 5226 Vec coordinates; 5227 PetscScalar *array; 5228 5229 in.pointlist = new double[in.numberofpoints*dim]; 5230 in.pointmarkerlist = new int[in.numberofpoints]; 5231 5232 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5233 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5234 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5235 for (v = vStart; v < vEnd; ++v) { 5236 const PetscInt idx = v - vStart; 5237 PetscInt off, d; 5238 5239 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5240 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5241 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5242 } 5243 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5244 } 5245 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5246 5247 in.numberoffacets = fEnd - fStart; 5248 if (in.numberoffacets > 0) { 5249 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5250 in.facetmarkerlist = new int[in.numberoffacets]; 5251 for (f = fStart; f < fEnd; ++f) { 5252 const PetscInt idx = f - fStart; 5253 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5254 5255 in.facetlist[idx].numberofpolygons = 1; 5256 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5257 in.facetlist[idx].numberofholes = 0; 5258 in.facetlist[idx].holelist = NULL; 5259 5260 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5261 for (p = 0; p < numPoints*2; p += 2) { 5262 const PetscInt point = points[p]; 5263 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5264 } 5265 5266 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5267 poly->numberofvertices = numVertices; 5268 poly->vertexlist = new int[poly->numberofvertices]; 5269 for (v = 0; v < numVertices; ++v) { 5270 const PetscInt vIdx = points[v] - vStart; 5271 poly->vertexlist[v] = vIdx; 5272 } 5273 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5274 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5275 } 5276 } 5277 if (!rank) { 5278 char args[32]; 5279 5280 /* Take away 'Q' for verbose output */ 5281 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5282 ::tetrahedralize(args, &in, &out); 5283 } 5284 { 5285 const PetscInt numCorners = 4; 5286 const PetscInt numCells = out.numberoftetrahedra; 5287 const PetscInt numVertices = out.numberofpoints; 5288 const int *cells = out.tetrahedronlist; 5289 const double *meshCoords = out.pointlist; 5290 5291 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5292 /* Set labels */ 5293 for (v = 0; v < numVertices; ++v) { 5294 if (out.pointmarkerlist[v]) { 5295 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5296 } 5297 } 5298 if (interpolate) { 5299 PetscInt e; 5300 5301 for (e = 0; e < out.numberofedges; e++) { 5302 if (out.edgemarkerlist[e]) { 5303 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5304 const PetscInt *edges; 5305 PetscInt numEdges; 5306 5307 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5308 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5309 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5310 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5311 } 5312 } 5313 for (f = 0; f < out.numberoftrifaces; f++) { 5314 if (out.trifacemarkerlist[f]) { 5315 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5316 const PetscInt *faces; 5317 PetscInt numFaces; 5318 5319 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5320 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5321 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5322 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5323 } 5324 } 5325 } 5326 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5327 } 5328 PetscFunctionReturn(0); 5329 } 5330 5331 #undef __FUNCT__ 5332 #define __FUNCT__ "DMPlexRefine_Tetgen" 5333 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5334 { 5335 MPI_Comm comm = ((PetscObject) dm)->comm; 5336 const PetscInt dim = 3; 5337 ::tetgenio in; 5338 ::tetgenio out; 5339 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5340 PetscMPIInt rank; 5341 PetscErrorCode ierr; 5342 5343 PetscFunctionBegin; 5344 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5345 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5346 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5347 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5348 5349 in.numberofpoints = vEnd - vStart; 5350 if (in.numberofpoints > 0) { 5351 PetscSection coordSection; 5352 Vec coordinates; 5353 PetscScalar *array; 5354 5355 in.pointlist = new double[in.numberofpoints*dim]; 5356 in.pointmarkerlist = new int[in.numberofpoints]; 5357 5358 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5359 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5360 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5361 for (v = vStart; v < vEnd; ++v) { 5362 const PetscInt idx = v - vStart; 5363 PetscInt off, d; 5364 5365 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5366 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5367 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5368 } 5369 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5370 } 5371 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5372 5373 in.numberofcorners = 4; 5374 in.numberoftetrahedra = cEnd - cStart; 5375 in.tetrahedronvolumelist = (double*) maxVolumes; 5376 if (in.numberoftetrahedra > 0) { 5377 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5378 for (c = cStart; c < cEnd; ++c) { 5379 const PetscInt idx = c - cStart; 5380 PetscInt *closure = PETSC_NULL; 5381 PetscInt closureSize; 5382 5383 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5384 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5385 for (v = 0; v < 4; ++v) { 5386 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5387 } 5388 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5389 } 5390 } 5391 /* TODO: Put in boundary faces with markers */ 5392 if (!rank) { 5393 char args[32]; 5394 5395 /* Take away 'Q' for verbose output */ 5396 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5397 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5398 ::tetrahedralize(args, &in, &out); 5399 } 5400 in.tetrahedronvolumelist = NULL; 5401 5402 { 5403 const PetscInt numCorners = 4; 5404 const PetscInt numCells = out.numberoftetrahedra; 5405 const PetscInt numVertices = out.numberofpoints; 5406 const int *cells = out.tetrahedronlist; 5407 const double *meshCoords = out.pointlist; 5408 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5409 5410 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5411 /* Set labels */ 5412 for (v = 0; v < numVertices; ++v) { 5413 if (out.pointmarkerlist[v]) { 5414 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5415 } 5416 } 5417 if (interpolate) { 5418 PetscInt e, f; 5419 5420 for (e = 0; e < out.numberofedges; e++) { 5421 if (out.edgemarkerlist[e]) { 5422 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5423 const PetscInt *edges; 5424 PetscInt numEdges; 5425 5426 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5427 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5428 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5429 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5430 } 5431 } 5432 for (f = 0; f < out.numberoftrifaces; f++) { 5433 if (out.trifacemarkerlist[f]) { 5434 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5435 const PetscInt *faces; 5436 PetscInt numFaces; 5437 5438 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5439 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5440 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5441 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5442 } 5443 } 5444 } 5445 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5446 } 5447 PetscFunctionReturn(0); 5448 } 5449 #endif 5450 5451 #if defined(PETSC_HAVE_CTETGEN) 5452 #include "ctetgen.h" 5453 5454 #undef __FUNCT__ 5455 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5456 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5457 { 5458 MPI_Comm comm = ((PetscObject) boundary)->comm; 5459 const PetscInt dim = 3; 5460 PLC *in, *out; 5461 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5462 PetscMPIInt rank; 5463 PetscErrorCode ierr; 5464 5465 PetscFunctionBegin; 5466 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5467 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5468 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5469 ierr = PLCCreate(&in);CHKERRQ(ierr); 5470 ierr = PLCCreate(&out);CHKERRQ(ierr); 5471 5472 in->numberofpoints = vEnd - vStart; 5473 if (in->numberofpoints > 0) { 5474 PetscSection coordSection; 5475 Vec coordinates; 5476 PetscScalar *array; 5477 5478 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5479 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5480 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5481 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5482 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5483 for (v = vStart; v < vEnd; ++v) { 5484 const PetscInt idx = v - vStart; 5485 PetscInt off, d, m; 5486 5487 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5488 for (d = 0; d < dim; ++d) { 5489 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5490 } 5491 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5492 5493 in->pointmarkerlist[idx] = (int) m; 5494 } 5495 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5496 } 5497 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5498 5499 in->numberoffacets = fEnd - fStart; 5500 if (in->numberoffacets > 0) { 5501 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5502 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5503 for (f = fStart; f < fEnd; ++f) { 5504 const PetscInt idx = f - fStart; 5505 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5506 polygon *poly; 5507 5508 in->facetlist[idx].numberofpolygons = 1; 5509 5510 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5511 5512 in->facetlist[idx].numberofholes = 0; 5513 in->facetlist[idx].holelist = PETSC_NULL; 5514 5515 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5516 for (p = 0; p < numPoints*2; p += 2) { 5517 const PetscInt point = points[p]; 5518 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5519 } 5520 5521 poly = in->facetlist[idx].polygonlist; 5522 poly->numberofvertices = numVertices; 5523 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5524 for (v = 0; v < numVertices; ++v) { 5525 const PetscInt vIdx = points[v] - vStart; 5526 poly->vertexlist[v] = vIdx; 5527 } 5528 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5529 in->facetmarkerlist[idx] = (int) m; 5530 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5531 } 5532 } 5533 if (!rank) { 5534 TetGenOpts t; 5535 5536 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5537 t.in = boundary; /* Should go away */ 5538 t.plc = 1; 5539 t.quality = 1; 5540 t.edgesout = 1; 5541 t.zeroindex = 1; 5542 t.quiet = 1; 5543 t.verbose = verbose; 5544 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5545 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5546 } 5547 { 5548 const PetscInt numCorners = 4; 5549 const PetscInt numCells = out->numberoftetrahedra; 5550 const PetscInt numVertices = out->numberofpoints; 5551 const int *cells = out->tetrahedronlist; 5552 const double *meshCoords = out->pointlist; 5553 5554 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5555 /* Set labels */ 5556 for (v = 0; v < numVertices; ++v) { 5557 if (out->pointmarkerlist[v]) { 5558 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5559 } 5560 } 5561 if (interpolate) { 5562 PetscInt e; 5563 5564 for (e = 0; e < out->numberofedges; e++) { 5565 if (out->edgemarkerlist[e]) { 5566 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5567 const PetscInt *edges; 5568 PetscInt numEdges; 5569 5570 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5571 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5572 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5573 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5574 } 5575 } 5576 for (f = 0; f < out->numberoftrifaces; f++) { 5577 if (out->trifacemarkerlist[f]) { 5578 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5579 const PetscInt *faces; 5580 PetscInt numFaces; 5581 5582 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5583 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5584 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5585 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5586 } 5587 } 5588 } 5589 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5590 } 5591 5592 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5593 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5594 PetscFunctionReturn(0); 5595 } 5596 5597 #undef __FUNCT__ 5598 #define __FUNCT__ "DMPlexRefine_CTetgen" 5599 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5600 { 5601 MPI_Comm comm = ((PetscObject) dm)->comm; 5602 const PetscInt dim = 3; 5603 PLC *in, *out; 5604 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5605 PetscMPIInt rank; 5606 PetscErrorCode ierr; 5607 5608 PetscFunctionBegin; 5609 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5610 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5611 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5612 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5613 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5614 ierr = PLCCreate(&in);CHKERRQ(ierr); 5615 ierr = PLCCreate(&out);CHKERRQ(ierr); 5616 5617 in->numberofpoints = vEnd - vStart; 5618 if (in->numberofpoints > 0) { 5619 PetscSection coordSection; 5620 Vec coordinates; 5621 PetscScalar *array; 5622 5623 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5624 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5625 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5626 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5627 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5628 for (v = vStart; v < vEnd; ++v) { 5629 const PetscInt idx = v - vStart; 5630 PetscInt off, d, m; 5631 5632 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5633 for (d = 0; d < dim; ++d) { 5634 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5635 } 5636 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5637 5638 in->pointmarkerlist[idx] = (int) m; 5639 } 5640 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5641 } 5642 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5643 5644 in->numberofcorners = 4; 5645 in->numberoftetrahedra = cEnd - cStart; 5646 in->tetrahedronvolumelist = maxVolumes; 5647 if (in->numberoftetrahedra > 0) { 5648 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5649 for (c = cStart; c < cEnd; ++c) { 5650 const PetscInt idx = c - cStart; 5651 PetscInt *closure = PETSC_NULL; 5652 PetscInt closureSize; 5653 5654 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5655 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5656 for (v = 0; v < 4; ++v) { 5657 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5658 } 5659 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5660 } 5661 } 5662 if (!rank) { 5663 TetGenOpts t; 5664 5665 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5666 5667 t.in = dm; /* Should go away */ 5668 t.refine = 1; 5669 t.varvolume = 1; 5670 t.quality = 1; 5671 t.edgesout = 1; 5672 t.zeroindex = 1; 5673 t.quiet = 1; 5674 t.verbose = verbose; /* Change this */ 5675 5676 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5677 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5678 } 5679 { 5680 const PetscInt numCorners = 4; 5681 const PetscInt numCells = out->numberoftetrahedra; 5682 const PetscInt numVertices = out->numberofpoints; 5683 const int *cells = out->tetrahedronlist; 5684 const double *meshCoords = out->pointlist; 5685 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5686 5687 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5688 /* Set labels */ 5689 for (v = 0; v < numVertices; ++v) { 5690 if (out->pointmarkerlist[v]) { 5691 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5692 } 5693 } 5694 if (interpolate) { 5695 PetscInt e, f; 5696 5697 for (e = 0; e < out->numberofedges; e++) { 5698 if (out->edgemarkerlist[e]) { 5699 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5700 const PetscInt *edges; 5701 PetscInt numEdges; 5702 5703 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5704 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5705 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5706 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5707 } 5708 } 5709 for (f = 0; f < out->numberoftrifaces; f++) { 5710 if (out->trifacemarkerlist[f]) { 5711 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5712 const PetscInt *faces; 5713 PetscInt numFaces; 5714 5715 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5716 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5717 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5718 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5719 } 5720 } 5721 } 5722 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5723 } 5724 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5725 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5726 PetscFunctionReturn(0); 5727 } 5728 #endif 5729 5730 #undef __FUNCT__ 5731 #define __FUNCT__ "DMPlexGenerate" 5732 /*@C 5733 DMPlexGenerate - Generates a mesh. 5734 5735 Not Collective 5736 5737 Input Parameters: 5738 + boundary - The DMPlex boundary object 5739 . name - The mesh generation package name 5740 - interpolate - Flag to create intermediate mesh elements 5741 5742 Output Parameter: 5743 . mesh - The DMPlex object 5744 5745 Level: intermediate 5746 5747 .keywords: mesh, elements 5748 .seealso: DMPlexCreate(), DMRefine() 5749 @*/ 5750 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5751 { 5752 PetscInt dim; 5753 char genname[1024]; 5754 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5755 PetscErrorCode ierr; 5756 5757 PetscFunctionBegin; 5758 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5759 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5760 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5761 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5762 if (flg) name = genname; 5763 if (name) { 5764 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5765 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5766 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5767 } 5768 switch (dim) { 5769 case 1: 5770 if (!name || isTriangle) { 5771 #if defined(PETSC_HAVE_TRIANGLE) 5772 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5773 #else 5774 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5775 #endif 5776 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5777 break; 5778 case 2: 5779 if (!name || isCTetgen) { 5780 #if defined(PETSC_HAVE_CTETGEN) 5781 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5782 #else 5783 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5784 #endif 5785 } else if (isTetgen) { 5786 #if defined(PETSC_HAVE_TETGEN) 5787 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5788 #else 5789 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5790 #endif 5791 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5792 break; 5793 default: 5794 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5795 } 5796 PetscFunctionReturn(0); 5797 } 5798 5799 typedef PetscInt CellRefiner; 5800 5801 #undef __FUNCT__ 5802 #define __FUNCT__ "GetDepthStart_Private" 5803 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5804 { 5805 PetscFunctionBegin; 5806 if (cStart) *cStart = 0; 5807 if (vStart) *vStart = depthSize[depth]; 5808 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5809 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5810 PetscFunctionReturn(0); 5811 } 5812 5813 #undef __FUNCT__ 5814 #define __FUNCT__ "GetDepthEnd_Private" 5815 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5816 { 5817 PetscFunctionBegin; 5818 if (cEnd) *cEnd = depthSize[depth]; 5819 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5820 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5821 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5822 PetscFunctionReturn(0); 5823 } 5824 5825 #undef __FUNCT__ 5826 #define __FUNCT__ "CellRefinerGetSizes" 5827 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5828 { 5829 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5830 PetscErrorCode ierr; 5831 5832 PetscFunctionBegin; 5833 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5834 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5835 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5836 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5837 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5838 switch (refiner) { 5839 case 1: 5840 /* Simplicial 2D */ 5841 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5842 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5843 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5844 break; 5845 case 3: 5846 /* Hybrid 2D */ 5847 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5848 cMax = PetscMin(cEnd, cMax); 5849 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5850 fMax = PetscMin(fEnd, fMax); 5851 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5852 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 */ 5853 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5854 break; 5855 case 2: 5856 /* Hex 2D */ 5857 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5858 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5859 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5860 break; 5861 default: 5862 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5863 } 5864 PetscFunctionReturn(0); 5865 } 5866 5867 #undef __FUNCT__ 5868 #define __FUNCT__ "CellRefinerSetConeSizes" 5869 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5870 { 5871 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5872 PetscErrorCode ierr; 5873 5874 PetscFunctionBegin; 5875 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5876 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5877 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5878 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5879 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5880 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5881 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5882 switch (refiner) { 5883 case 1: 5884 /* Simplicial 2D */ 5885 /* All cells have 3 faces */ 5886 for (c = cStart; c < cEnd; ++c) { 5887 for (r = 0; r < 4; ++r) { 5888 const PetscInt newp = (c - cStart)*4 + r; 5889 5890 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5891 } 5892 } 5893 /* Split faces have 2 vertices and the same cells as the parent */ 5894 for (f = fStart; f < fEnd; ++f) { 5895 for (r = 0; r < 2; ++r) { 5896 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5897 PetscInt size; 5898 5899 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5900 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5901 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5902 } 5903 } 5904 /* Interior faces have 2 vertices and 2 cells */ 5905 for (c = cStart; c < cEnd; ++c) { 5906 for (r = 0; r < 3; ++r) { 5907 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5908 5909 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5910 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5911 } 5912 } 5913 /* Old vertices have identical supports */ 5914 for (v = vStart; v < vEnd; ++v) { 5915 const PetscInt newp = vStartNew + (v - vStart); 5916 PetscInt size; 5917 5918 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5919 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5920 } 5921 /* Face vertices have 2 + cells*2 supports */ 5922 for (f = fStart; f < fEnd; ++f) { 5923 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5924 PetscInt size; 5925 5926 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5927 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5928 } 5929 break; 5930 case 2: 5931 /* Hex 2D */ 5932 /* All cells have 4 faces */ 5933 for (c = cStart; c < cEnd; ++c) { 5934 for (r = 0; r < 4; ++r) { 5935 const PetscInt newp = (c - cStart)*4 + r; 5936 5937 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5938 } 5939 } 5940 /* Split faces have 2 vertices and the same cells as the parent */ 5941 for (f = fStart; f < fEnd; ++f) { 5942 for (r = 0; r < 2; ++r) { 5943 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5944 PetscInt size; 5945 5946 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5947 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5948 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5949 } 5950 } 5951 /* Interior faces have 2 vertices and 2 cells */ 5952 for (c = cStart; c < cEnd; ++c) { 5953 for (r = 0; r < 4; ++r) { 5954 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5955 5956 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5957 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5958 } 5959 } 5960 /* Old vertices have identical supports */ 5961 for (v = vStart; v < vEnd; ++v) { 5962 const PetscInt newp = vStartNew + (v - vStart); 5963 PetscInt size; 5964 5965 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5966 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5967 } 5968 /* Face vertices have 2 + cells supports */ 5969 for (f = fStart; f < fEnd; ++f) { 5970 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5971 PetscInt size; 5972 5973 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5974 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5975 } 5976 /* Cell vertices have 4 supports */ 5977 for (c = cStart; c < cEnd; ++c) { 5978 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5979 5980 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5981 } 5982 break; 5983 case 3: 5984 /* Hybrid 2D */ 5985 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5986 cMax = PetscMin(cEnd, cMax); 5987 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5988 fMax = PetscMin(fEnd, fMax); 5989 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5990 /* Interior cells have 3 faces */ 5991 for (c = cStart; c < cMax; ++c) { 5992 for (r = 0; r < 4; ++r) { 5993 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5994 5995 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5996 } 5997 } 5998 /* Hybrid cells have 4 faces */ 5999 for (c = cMax; c < cEnd; ++c) { 6000 for (r = 0; r < 2; ++r) { 6001 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6002 6003 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6004 } 6005 } 6006 /* Interior split faces have 2 vertices and the same cells as the parent */ 6007 for (f = fStart; f < fMax; ++f) { 6008 for (r = 0; r < 2; ++r) { 6009 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6010 PetscInt size; 6011 6012 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6013 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6014 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6015 } 6016 } 6017 /* Interior cell faces have 2 vertices and 2 cells */ 6018 for (c = cStart; c < cMax; ++c) { 6019 for (r = 0; r < 3; ++r) { 6020 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6021 6022 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6023 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6024 } 6025 } 6026 /* Hybrid faces have 2 vertices and the same cells */ 6027 for (f = fMax; f < fEnd; ++f) { 6028 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6029 PetscInt size; 6030 6031 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6032 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6033 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6034 } 6035 /* Hybrid cell faces have 2 vertices and 2 cells */ 6036 for (c = cMax; c < cEnd; ++c) { 6037 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6038 6039 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6040 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6041 } 6042 /* Old vertices have identical supports */ 6043 for (v = vStart; v < vEnd; ++v) { 6044 const PetscInt newp = vStartNew + (v - vStart); 6045 PetscInt size; 6046 6047 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6048 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6049 } 6050 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6051 for (f = fStart; f < fMax; ++f) { 6052 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6053 const PetscInt *support; 6054 PetscInt size, newSize = 2, s; 6055 6056 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6057 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6058 for (s = 0; s < size; ++s) { 6059 if (support[s] >= cMax) newSize += 1; 6060 else newSize += 2; 6061 } 6062 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6063 } 6064 break; 6065 default: 6066 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6067 } 6068 PetscFunctionReturn(0); 6069 } 6070 6071 #undef __FUNCT__ 6072 #define __FUNCT__ "CellRefinerSetCones" 6073 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6074 { 6075 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; 6076 PetscInt maxSupportSize, *supportRef; 6077 PetscErrorCode ierr; 6078 6079 PetscFunctionBegin; 6080 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6081 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6082 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6083 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6084 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6085 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6086 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6087 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6088 switch (refiner) { 6089 case 1: 6090 /* Simplicial 2D */ 6091 /* 6092 2 6093 |\ 6094 | \ 6095 | \ 6096 | \ 6097 | C \ 6098 | \ 6099 | \ 6100 2---1---1 6101 |\ D / \ 6102 | 2 0 \ 6103 |A \ / B \ 6104 0---0-------1 6105 */ 6106 /* All cells have 3 faces */ 6107 for (c = cStart; c < cEnd; ++c) { 6108 const PetscInt newp = cStartNew + (c - cStart)*4; 6109 const PetscInt *cone, *ornt; 6110 PetscInt coneNew[3], orntNew[3]; 6111 6112 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6113 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6114 /* A triangle */ 6115 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6116 orntNew[0] = ornt[0]; 6117 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6118 orntNew[1] = -2; 6119 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6120 orntNew[2] = ornt[2]; 6121 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6122 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6123 #if 1 6124 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); 6125 for (p = 0; p < 3; ++p) { 6126 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); 6127 } 6128 #endif 6129 /* B triangle */ 6130 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6131 orntNew[0] = ornt[0]; 6132 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6133 orntNew[1] = ornt[1]; 6134 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6135 orntNew[2] = -2; 6136 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6137 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6138 #if 1 6139 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); 6140 for (p = 0; p < 3; ++p) { 6141 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); 6142 } 6143 #endif 6144 /* C triangle */ 6145 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6146 orntNew[0] = -2; 6147 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6148 orntNew[1] = ornt[1]; 6149 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6150 orntNew[2] = ornt[2]; 6151 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6152 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6153 #if 1 6154 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); 6155 for (p = 0; p < 3; ++p) { 6156 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); 6157 } 6158 #endif 6159 /* D triangle */ 6160 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6161 orntNew[0] = 0; 6162 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6163 orntNew[1] = 0; 6164 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6165 orntNew[2] = 0; 6166 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6167 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6168 #if 1 6169 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); 6170 for (p = 0; p < 3; ++p) { 6171 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); 6172 } 6173 #endif 6174 } 6175 /* Split faces have 2 vertices and the same cells as the parent */ 6176 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6177 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6178 for (f = fStart; f < fEnd; ++f) { 6179 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6180 6181 for (r = 0; r < 2; ++r) { 6182 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6183 const PetscInt *cone, *support; 6184 PetscInt coneNew[2], coneSize, c, supportSize, s; 6185 6186 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6187 coneNew[0] = vStartNew + (cone[0] - vStart); 6188 coneNew[1] = vStartNew + (cone[1] - vStart); 6189 coneNew[(r+1)%2] = newv; 6190 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6191 #if 1 6192 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6193 for (p = 0; p < 2; ++p) { 6194 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); 6195 } 6196 #endif 6197 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6198 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6199 for (s = 0; s < supportSize; ++s) { 6200 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6201 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6202 for (c = 0; c < coneSize; ++c) { 6203 if (cone[c] == f) break; 6204 } 6205 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6206 } 6207 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6208 #if 1 6209 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6210 for (p = 0; p < supportSize; ++p) { 6211 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); 6212 } 6213 #endif 6214 } 6215 } 6216 /* Interior faces have 2 vertices and 2 cells */ 6217 for (c = cStart; c < cEnd; ++c) { 6218 const PetscInt *cone; 6219 6220 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6221 for (r = 0; r < 3; ++r) { 6222 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6223 PetscInt coneNew[2]; 6224 PetscInt supportNew[2]; 6225 6226 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6227 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6228 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6229 #if 1 6230 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6231 for (p = 0; p < 2; ++p) { 6232 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); 6233 } 6234 #endif 6235 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6236 supportNew[1] = (c - cStart)*4 + 3; 6237 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6238 #if 1 6239 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6240 for (p = 0; p < 2; ++p) { 6241 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); 6242 } 6243 #endif 6244 } 6245 } 6246 /* Old vertices have identical supports */ 6247 for (v = vStart; v < vEnd; ++v) { 6248 const PetscInt newp = vStartNew + (v - vStart); 6249 const PetscInt *support, *cone; 6250 PetscInt size, s; 6251 6252 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6253 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6254 for (s = 0; s < size; ++s) { 6255 PetscInt r = 0; 6256 6257 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6258 if (cone[1] == v) r = 1; 6259 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6260 } 6261 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6262 #if 1 6263 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6264 for (p = 0; p < size; ++p) { 6265 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); 6266 } 6267 #endif 6268 } 6269 /* Face vertices have 2 + cells*2 supports */ 6270 for (f = fStart; f < fEnd; ++f) { 6271 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6272 const PetscInt *cone, *support; 6273 PetscInt size, s; 6274 6275 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6276 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6277 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6278 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6279 for (s = 0; s < size; ++s) { 6280 PetscInt r = 0; 6281 6282 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6283 if (cone[1] == f) r = 1; 6284 else if (cone[2] == f) r = 2; 6285 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6286 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6287 } 6288 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6289 #if 1 6290 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6291 for (p = 0; p < 2+size*2; ++p) { 6292 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); 6293 } 6294 #endif 6295 } 6296 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6297 break; 6298 case 2: 6299 /* Hex 2D */ 6300 /* 6301 3---------2---------2 6302 | | | 6303 | D 2 C | 6304 | | | 6305 3----3----0----1----1 6306 | | | 6307 | A 0 B | 6308 | | | 6309 0---------0---------1 6310 */ 6311 /* All cells have 4 faces */ 6312 for (c = cStart; c < cEnd; ++c) { 6313 const PetscInt newp = (c - cStart)*4; 6314 const PetscInt *cone, *ornt; 6315 PetscInt coneNew[4], orntNew[4]; 6316 6317 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6318 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6319 /* A quad */ 6320 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6321 orntNew[0] = ornt[0]; 6322 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6323 orntNew[1] = 0; 6324 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6325 orntNew[2] = -2; 6326 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6327 orntNew[3] = ornt[3]; 6328 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6329 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6330 #if 1 6331 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); 6332 for (p = 0; p < 4; ++p) { 6333 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); 6334 } 6335 #endif 6336 /* B quad */ 6337 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6338 orntNew[0] = ornt[0]; 6339 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6340 orntNew[1] = ornt[1]; 6341 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6342 orntNew[2] = 0; 6343 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6344 orntNew[3] = -2; 6345 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6346 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6347 #if 1 6348 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); 6349 for (p = 0; p < 4; ++p) { 6350 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); 6351 } 6352 #endif 6353 /* C quad */ 6354 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6355 orntNew[0] = -2; 6356 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6357 orntNew[1] = ornt[1]; 6358 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6359 orntNew[2] = ornt[2]; 6360 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6361 orntNew[3] = 0; 6362 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6363 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6364 #if 1 6365 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); 6366 for (p = 0; p < 4; ++p) { 6367 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); 6368 } 6369 #endif 6370 /* D quad */ 6371 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6372 orntNew[0] = 0; 6373 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6374 orntNew[1] = -2; 6375 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6376 orntNew[2] = ornt[2]; 6377 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6378 orntNew[3] = ornt[3]; 6379 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6380 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6381 #if 1 6382 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); 6383 for (p = 0; p < 4; ++p) { 6384 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); 6385 } 6386 #endif 6387 } 6388 /* Split faces have 2 vertices and the same cells as the parent */ 6389 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6390 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6391 for (f = fStart; f < fEnd; ++f) { 6392 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6393 6394 for (r = 0; r < 2; ++r) { 6395 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6396 const PetscInt *cone, *support; 6397 PetscInt coneNew[2], coneSize, c, supportSize, s; 6398 6399 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6400 coneNew[0] = vStartNew + (cone[0] - vStart); 6401 coneNew[1] = vStartNew + (cone[1] - vStart); 6402 coneNew[(r+1)%2] = newv; 6403 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6404 #if 1 6405 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6406 for (p = 0; p < 2; ++p) { 6407 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); 6408 } 6409 #endif 6410 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6411 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6412 for (s = 0; s < supportSize; ++s) { 6413 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6414 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6415 for (c = 0; c < coneSize; ++c) { 6416 if (cone[c] == f) break; 6417 } 6418 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6419 } 6420 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6421 #if 1 6422 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6423 for (p = 0; p < supportSize; ++p) { 6424 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); 6425 } 6426 #endif 6427 } 6428 } 6429 /* Interior faces have 2 vertices and 2 cells */ 6430 for (c = cStart; c < cEnd; ++c) { 6431 const PetscInt *cone; 6432 PetscInt coneNew[2], supportNew[2]; 6433 6434 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6435 for (r = 0; r < 4; ++r) { 6436 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6437 6438 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6439 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6440 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6441 #if 1 6442 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6443 for (p = 0; p < 2; ++p) { 6444 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); 6445 } 6446 #endif 6447 supportNew[0] = (c - cStart)*4 + r; 6448 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6449 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6450 #if 1 6451 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6452 for (p = 0; p < 2; ++p) { 6453 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); 6454 } 6455 #endif 6456 } 6457 } 6458 /* Old vertices have identical supports */ 6459 for (v = vStart; v < vEnd; ++v) { 6460 const PetscInt newp = vStartNew + (v - vStart); 6461 const PetscInt *support, *cone; 6462 PetscInt size, s; 6463 6464 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6465 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6466 for (s = 0; s < size; ++s) { 6467 PetscInt r = 0; 6468 6469 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6470 if (cone[1] == v) r = 1; 6471 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6472 } 6473 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6474 #if 1 6475 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6476 for (p = 0; p < size; ++p) { 6477 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); 6478 } 6479 #endif 6480 } 6481 /* Face vertices have 2 + cells supports */ 6482 for (f = fStart; f < fEnd; ++f) { 6483 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6484 const PetscInt *cone, *support; 6485 PetscInt size, s; 6486 6487 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6488 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6489 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6490 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6491 for (s = 0; s < size; ++s) { 6492 PetscInt r = 0; 6493 6494 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6495 if (cone[1] == f) r = 1; 6496 else if (cone[2] == f) r = 2; 6497 else if (cone[3] == f) r = 3; 6498 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6499 } 6500 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6501 #if 1 6502 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6503 for (p = 0; p < 2+size; ++p) { 6504 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); 6505 } 6506 #endif 6507 } 6508 /* Cell vertices have 4 supports */ 6509 for (c = cStart; c < cEnd; ++c) { 6510 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6511 PetscInt supportNew[4]; 6512 6513 for (r = 0; r < 4; ++r) { 6514 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6515 } 6516 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6517 } 6518 break; 6519 case 3: 6520 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6521 cMax = PetscMin(cEnd, cMax); 6522 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6523 fMax = PetscMin(fEnd, fMax); 6524 /* Interior cells have 3 faces */ 6525 for (c = cStart; c < cMax; ++c) { 6526 const PetscInt newp = cStartNew + (c - cStart)*4; 6527 const PetscInt *cone, *ornt; 6528 PetscInt coneNew[3], orntNew[3]; 6529 6530 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6531 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6532 /* A triangle */ 6533 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6534 orntNew[0] = ornt[0]; 6535 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6536 orntNew[1] = -2; 6537 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6538 orntNew[2] = ornt[2]; 6539 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6540 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6541 #if 1 6542 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); 6543 for (p = 0; p < 3; ++p) { 6544 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); 6545 } 6546 #endif 6547 /* B triangle */ 6548 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6549 orntNew[0] = ornt[0]; 6550 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6551 orntNew[1] = ornt[1]; 6552 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6553 orntNew[2] = -2; 6554 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6555 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6556 #if 1 6557 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); 6558 for (p = 0; p < 3; ++p) { 6559 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); 6560 } 6561 #endif 6562 /* C triangle */ 6563 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6564 orntNew[0] = -2; 6565 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6566 orntNew[1] = ornt[1]; 6567 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6568 orntNew[2] = ornt[2]; 6569 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6570 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6571 #if 1 6572 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); 6573 for (p = 0; p < 3; ++p) { 6574 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); 6575 } 6576 #endif 6577 /* D triangle */ 6578 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6579 orntNew[0] = 0; 6580 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6581 orntNew[1] = 0; 6582 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6583 orntNew[2] = 0; 6584 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6585 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6586 #if 1 6587 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); 6588 for (p = 0; p < 3; ++p) { 6589 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); 6590 } 6591 #endif 6592 } 6593 /* 6594 2----3----3 6595 | | 6596 | B | 6597 | | 6598 0----4--- 1 6599 | | 6600 | A | 6601 | | 6602 0----2----1 6603 */ 6604 /* Hybrid cells have 4 faces */ 6605 for (c = cMax; c < cEnd; ++c) { 6606 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6607 const PetscInt *cone, *ornt; 6608 PetscInt coneNew[4], orntNew[4]; 6609 6610 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6611 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6612 /* A quad */ 6613 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6614 orntNew[0] = ornt[0]; 6615 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6616 orntNew[1] = ornt[1]; 6617 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6618 orntNew[2] = 0; 6619 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6620 orntNew[3] = 0; 6621 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6622 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6623 #if 1 6624 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); 6625 for (p = 0; p < 4; ++p) { 6626 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); 6627 } 6628 #endif 6629 /* B quad */ 6630 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6631 orntNew[0] = ornt[0]; 6632 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6633 orntNew[1] = ornt[1]; 6634 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6635 orntNew[2] = 0; 6636 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6637 orntNew[3] = 0; 6638 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6639 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6640 #if 1 6641 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); 6642 for (p = 0; p < 4; ++p) { 6643 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); 6644 } 6645 #endif 6646 } 6647 /* Interior split faces have 2 vertices and the same cells as the parent */ 6648 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6649 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6650 for (f = fStart; f < fMax; ++f) { 6651 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6652 6653 for (r = 0; r < 2; ++r) { 6654 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6655 const PetscInt *cone, *support; 6656 PetscInt coneNew[2], coneSize, c, supportSize, s; 6657 6658 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6659 coneNew[0] = vStartNew + (cone[0] - vStart); 6660 coneNew[1] = vStartNew + (cone[1] - vStart); 6661 coneNew[(r+1)%2] = newv; 6662 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6663 #if 1 6664 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6665 for (p = 0; p < 2; ++p) { 6666 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); 6667 } 6668 #endif 6669 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6670 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6671 for (s = 0; s < supportSize; ++s) { 6672 if (support[s] >= cMax) { 6673 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6674 } else { 6675 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6676 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6677 for (c = 0; c < coneSize; ++c) { 6678 if (cone[c] == f) break; 6679 } 6680 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6681 } 6682 } 6683 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6684 #if 1 6685 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6686 for (p = 0; p < supportSize; ++p) { 6687 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); 6688 } 6689 #endif 6690 } 6691 } 6692 /* Interior cell faces have 2 vertices and 2 cells */ 6693 for (c = cStart; c < cMax; ++c) { 6694 const PetscInt *cone; 6695 6696 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6697 for (r = 0; r < 3; ++r) { 6698 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6699 PetscInt coneNew[2]; 6700 PetscInt supportNew[2]; 6701 6702 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6703 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6704 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6705 #if 1 6706 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6707 for (p = 0; p < 2; ++p) { 6708 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); 6709 } 6710 #endif 6711 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6712 supportNew[1] = (c - cStart)*4 + 3; 6713 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6714 #if 1 6715 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6716 for (p = 0; p < 2; ++p) { 6717 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); 6718 } 6719 #endif 6720 } 6721 } 6722 /* Interior hybrid faces have 2 vertices and the same cells */ 6723 for (f = fMax; f < fEnd; ++f) { 6724 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6725 const PetscInt *cone; 6726 const PetscInt *support; 6727 PetscInt coneNew[2]; 6728 PetscInt supportNew[2]; 6729 PetscInt size, s, r; 6730 6731 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6732 coneNew[0] = vStartNew + (cone[0] - vStart); 6733 coneNew[1] = vStartNew + (cone[1] - vStart); 6734 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6735 #if 1 6736 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6737 for (p = 0; p < 2; ++p) { 6738 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); 6739 } 6740 #endif 6741 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6742 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6743 for (s = 0; s < size; ++s) { 6744 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6745 for (r = 0; r < 2; ++r) { 6746 if (cone[r+2] == f) break; 6747 } 6748 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6749 } 6750 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6751 #if 1 6752 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6753 for (p = 0; p < size; ++p) { 6754 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); 6755 } 6756 #endif 6757 } 6758 /* Cell hybrid faces have 2 vertices and 2 cells */ 6759 for (c = cMax; c < cEnd; ++c) { 6760 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6761 const PetscInt *cone; 6762 PetscInt coneNew[2]; 6763 PetscInt supportNew[2]; 6764 6765 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6766 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6767 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6768 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6769 #if 1 6770 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6771 for (p = 0; p < 2; ++p) { 6772 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); 6773 } 6774 #endif 6775 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6776 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6777 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6778 #if 1 6779 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6780 for (p = 0; p < 2; ++p) { 6781 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); 6782 } 6783 #endif 6784 } 6785 /* Old vertices have identical supports */ 6786 for (v = vStart; v < vEnd; ++v) { 6787 const PetscInt newp = vStartNew + (v - vStart); 6788 const PetscInt *support, *cone; 6789 PetscInt size, s; 6790 6791 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6792 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6793 for (s = 0; s < size; ++s) { 6794 if (support[s] >= fMax) { 6795 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6796 } else { 6797 PetscInt r = 0; 6798 6799 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6800 if (cone[1] == v) r = 1; 6801 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6802 } 6803 } 6804 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6805 #if 1 6806 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6807 for (p = 0; p < size; ++p) { 6808 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); 6809 } 6810 #endif 6811 } 6812 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6813 for (f = fStart; f < fMax; ++f) { 6814 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6815 const PetscInt *cone, *support; 6816 PetscInt size, newSize = 2, s; 6817 6818 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6819 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6820 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6821 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6822 for (s = 0; s < size; ++s) { 6823 PetscInt r = 0; 6824 6825 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6826 if (support[s] >= cMax) { 6827 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6828 6829 newSize += 1; 6830 } else { 6831 if (cone[1] == f) r = 1; 6832 else if (cone[2] == f) r = 2; 6833 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6834 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6835 6836 newSize += 2; 6837 } 6838 } 6839 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6840 #if 1 6841 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6842 for (p = 0; p < newSize; ++p) { 6843 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); 6844 } 6845 #endif 6846 } 6847 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6848 break; 6849 default: 6850 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6851 } 6852 PetscFunctionReturn(0); 6853 } 6854 6855 #undef __FUNCT__ 6856 #define __FUNCT__ "CellRefinerSetCoordinates" 6857 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6858 { 6859 PetscSection coordSection, coordSectionNew; 6860 Vec coordinates, coordinatesNew; 6861 PetscScalar *coords, *coordsNew; 6862 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6863 PetscErrorCode ierr; 6864 6865 PetscFunctionBegin; 6866 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6867 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6868 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6869 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6870 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6871 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6872 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6873 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6874 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6875 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6876 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6877 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6878 if (fMax < 0) fMax = fEnd; 6879 switch (refiner) { 6880 case 1: 6881 case 2: 6882 case 3: 6883 /* Simplicial and Hex 2D */ 6884 /* All vertices have the dim coordinates */ 6885 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6886 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6887 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6888 } 6889 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6890 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6891 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6892 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6893 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6894 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6895 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6896 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6897 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6898 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6899 /* Old vertices have the same coordinates */ 6900 for (v = vStart; v < vEnd; ++v) { 6901 const PetscInt newv = vStartNew + (v - vStart); 6902 PetscInt off, offnew, d; 6903 6904 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6905 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6906 for (d = 0; d < dim; ++d) { 6907 coordsNew[offnew+d] = coords[off+d]; 6908 } 6909 } 6910 /* Face vertices have the average of endpoint coordinates */ 6911 for (f = fStart; f < fMax; ++f) { 6912 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6913 const PetscInt *cone; 6914 PetscInt coneSize, offA, offB, offnew, d; 6915 6916 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6917 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6918 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6919 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6920 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6921 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6922 for (d = 0; d < dim; ++d) { 6923 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6924 } 6925 } 6926 /* Just Hex 2D */ 6927 if (refiner == 2) { 6928 /* Cell vertices have the average of corner coordinates */ 6929 for (c = cStart; c < cEnd; ++c) { 6930 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6931 PetscInt *cone = PETSC_NULL; 6932 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6933 6934 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6935 for (p = 0; p < closureSize*2; p += 2) { 6936 const PetscInt point = cone[p]; 6937 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6938 } 6939 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6940 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6941 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6942 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6943 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6944 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6945 for (d = 0; d < dim; ++d) { 6946 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6947 } 6948 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6949 } 6950 } 6951 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6952 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6953 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6954 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6955 break; 6956 default: 6957 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6958 } 6959 PetscFunctionReturn(0); 6960 } 6961 6962 #undef __FUNCT__ 6963 #define __FUNCT__ "DMPlexCreateProcessSF" 6964 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6965 { 6966 PetscInt numRoots, numLeaves, l; 6967 const PetscInt *localPoints; 6968 const PetscSFNode *remotePoints; 6969 PetscInt *localPointsNew; 6970 PetscSFNode *remotePointsNew; 6971 PetscInt *ranks, *ranksNew; 6972 PetscErrorCode ierr; 6973 6974 PetscFunctionBegin; 6975 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6976 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6977 for (l = 0; l < numLeaves; ++l) { 6978 ranks[l] = remotePoints[l].rank; 6979 } 6980 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6981 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6982 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6983 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6984 for (l = 0; l < numLeaves; ++l) { 6985 ranksNew[l] = ranks[l]; 6986 localPointsNew[l] = l; 6987 remotePointsNew[l].index = 0; 6988 remotePointsNew[l].rank = ranksNew[l]; 6989 } 6990 ierr = PetscFree(ranks);CHKERRQ(ierr); 6991 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6992 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6993 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6994 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6995 PetscFunctionReturn(0); 6996 } 6997 6998 #undef __FUNCT__ 6999 #define __FUNCT__ "CellRefinerCreateSF" 7000 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7001 { 7002 PetscSF sf, sfNew, sfProcess; 7003 IS processRanks; 7004 MPI_Datatype depthType; 7005 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7006 const PetscInt *localPoints, *neighbors; 7007 const PetscSFNode *remotePoints; 7008 PetscInt *localPointsNew; 7009 PetscSFNode *remotePointsNew; 7010 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7011 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7012 PetscErrorCode ierr; 7013 7014 PetscFunctionBegin; 7015 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7016 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7017 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7018 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7019 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7020 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7021 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7022 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7023 switch (refiner) { 7024 case 3: 7025 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7026 cMax = PetscMin(cEnd, cMax); 7027 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7028 fMax = PetscMin(fEnd, fMax); 7029 } 7030 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7031 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7032 /* Caculate size of new SF */ 7033 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7034 if (numRoots < 0) PetscFunctionReturn(0); 7035 for (l = 0; l < numLeaves; ++l) { 7036 const PetscInt p = localPoints[l]; 7037 7038 switch (refiner) { 7039 case 1: 7040 /* Simplicial 2D */ 7041 if ((p >= vStart) && (p < vEnd)) { 7042 /* Old vertices stay the same */ 7043 ++numLeavesNew; 7044 } else if ((p >= fStart) && (p < fEnd)) { 7045 /* Old faces add new faces and vertex */ 7046 numLeavesNew += 1 + 2; 7047 } else if ((p >= cStart) && (p < cEnd)) { 7048 /* Old cells add new cells and interior faces */ 7049 numLeavesNew += 4 + 3; 7050 } 7051 break; 7052 case 2: 7053 /* Hex 2D */ 7054 if ((p >= vStart) && (p < vEnd)) { 7055 /* Old vertices stay the same */ 7056 ++numLeavesNew; 7057 } else if ((p >= fStart) && (p < fEnd)) { 7058 /* Old faces add new faces and vertex */ 7059 numLeavesNew += 1 + 2; 7060 } else if ((p >= cStart) && (p < cEnd)) { 7061 /* Old cells add new cells and interior faces */ 7062 numLeavesNew += 4 + 4; 7063 } 7064 break; 7065 default: 7066 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7067 } 7068 } 7069 /* Communicate depthSizes for each remote rank */ 7070 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7071 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7072 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7073 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); 7074 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7075 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7076 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7077 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7078 for (n = 0; n < numNeighbors; ++n) { 7079 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7080 } 7081 depthSizeOld[depth] = cMax; 7082 depthSizeOld[0] = vMax; 7083 depthSizeOld[depth-1] = fMax; 7084 depthSizeOld[1] = eMax; 7085 7086 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7087 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7088 7089 depthSizeOld[depth] = cEnd - cStart; 7090 depthSizeOld[0] = vEnd - vStart; 7091 depthSizeOld[depth-1] = fEnd - fStart; 7092 depthSizeOld[1] = eEnd - eStart; 7093 7094 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7095 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7096 for (n = 0; n < numNeighbors; ++n) { 7097 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7098 } 7099 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7100 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7101 /* Calculate new point SF */ 7102 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7103 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7104 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7105 for (l = 0, m = 0; l < numLeaves; ++l) { 7106 PetscInt p = localPoints[l]; 7107 PetscInt rp = remotePoints[l].index, n; 7108 PetscMPIInt rrank = remotePoints[l].rank; 7109 7110 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7111 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7112 switch (refiner) { 7113 case 1: 7114 /* Simplicial 2D */ 7115 if ((p >= vStart) && (p < vEnd)) { 7116 /* Old vertices stay the same */ 7117 localPointsNew[m] = vStartNew + (p - vStart); 7118 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7119 remotePointsNew[m].rank = rrank; 7120 ++m; 7121 } else if ((p >= fStart) && (p < fEnd)) { 7122 /* Old faces add new faces and vertex */ 7123 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7124 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7125 remotePointsNew[m].rank = rrank; 7126 ++m; 7127 for (r = 0; r < 2; ++r, ++m) { 7128 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7129 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7130 remotePointsNew[m].rank = rrank; 7131 } 7132 } else if ((p >= cStart) && (p < cEnd)) { 7133 /* Old cells add new cells and interior faces */ 7134 for (r = 0; r < 4; ++r, ++m) { 7135 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7136 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7137 remotePointsNew[m].rank = rrank; 7138 } 7139 for (r = 0; r < 3; ++r, ++m) { 7140 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7141 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7142 remotePointsNew[m].rank = rrank; 7143 } 7144 } 7145 break; 7146 case 2: 7147 /* Hex 2D */ 7148 if ((p >= vStart) && (p < vEnd)) { 7149 /* Old vertices stay the same */ 7150 localPointsNew[m] = vStartNew + (p - vStart); 7151 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7152 remotePointsNew[m].rank = rrank; 7153 ++m; 7154 } else if ((p >= fStart) && (p < fEnd)) { 7155 /* Old faces add new faces and vertex */ 7156 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7157 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7158 remotePointsNew[m].rank = rrank; 7159 ++m; 7160 for (r = 0; r < 2; ++r, ++m) { 7161 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7162 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7163 remotePointsNew[m].rank = rrank; 7164 } 7165 } else if ((p >= cStart) && (p < cEnd)) { 7166 /* Old cells add new cells and interior faces */ 7167 for (r = 0; r < 4; ++r, ++m) { 7168 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7169 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7170 remotePointsNew[m].rank = rrank; 7171 } 7172 for (r = 0; r < 4; ++r, ++m) { 7173 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7174 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7175 remotePointsNew[m].rank = rrank; 7176 } 7177 } 7178 break; 7179 case 3: 7180 /* Hybrid simplicial 2D */ 7181 if ((p >= vStart) && (p < vEnd)) { 7182 /* Old vertices stay the same */ 7183 localPointsNew[m] = vStartNew + (p - vStart); 7184 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7185 remotePointsNew[m].rank = rrank; 7186 ++m; 7187 } else if ((p >= fStart) && (p < fMax)) { 7188 /* Old interior faces add new faces and vertex */ 7189 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7190 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7191 remotePointsNew[m].rank = rrank; 7192 ++m; 7193 for (r = 0; r < 2; ++r, ++m) { 7194 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7195 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7196 remotePointsNew[m].rank = rrank; 7197 } 7198 } else if ((p >= fMax) && (p < fEnd)) { 7199 /* Old hybrid faces stay the same */ 7200 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7201 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7202 remotePointsNew[m].rank = rrank; 7203 ++m; 7204 } else if ((p >= cStart) && (p < cMax)) { 7205 /* Old interior cells add new cells and interior faces */ 7206 for (r = 0; r < 4; ++r, ++m) { 7207 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7208 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7209 remotePointsNew[m].rank = rrank; 7210 } 7211 for (r = 0; r < 3; ++r, ++m) { 7212 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7213 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7214 remotePointsNew[m].rank = rrank; 7215 } 7216 } else if ((p >= cStart) && (p < cMax)) { 7217 /* Old hybrid cells add new cells and hybrid face */ 7218 for (r = 0; r < 2; ++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 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7224 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]); 7225 remotePointsNew[m].rank = rrank; 7226 ++m; 7227 } 7228 break; 7229 default: 7230 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7231 } 7232 } 7233 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7234 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7235 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7236 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7237 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7238 PetscFunctionReturn(0); 7239 } 7240 7241 #undef __FUNCT__ 7242 #define __FUNCT__ "CellRefinerCreateLabels" 7243 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7244 { 7245 PetscInt numLabels, l; 7246 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7247 PetscErrorCode ierr; 7248 7249 PetscFunctionBegin; 7250 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7251 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7252 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7253 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7254 7255 cStartNew = 0; 7256 vStartNew = depthSize[2]; 7257 fStartNew = depthSize[2] + depthSize[0]; 7258 7259 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7260 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7261 switch (refiner) { 7262 case 3: 7263 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7264 cMax = PetscMin(cEnd, cMax); 7265 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7266 fMax = PetscMin(fEnd, fMax); 7267 } 7268 for (l = 0; l < numLabels; ++l) { 7269 DMLabel label, labelNew; 7270 const char *lname; 7271 PetscBool isDepth; 7272 IS valueIS; 7273 const PetscInt *values; 7274 PetscInt numValues, val; 7275 7276 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7277 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7278 if (isDepth) continue; 7279 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7280 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7281 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7282 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7283 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7284 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7285 for (val = 0; val < numValues; ++val) { 7286 IS pointIS; 7287 const PetscInt *points; 7288 PetscInt numPoints, n; 7289 7290 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7291 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7292 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7293 for (n = 0; n < numPoints; ++n) { 7294 const PetscInt p = points[n]; 7295 switch (refiner) { 7296 case 1: 7297 /* Simplicial 2D */ 7298 if ((p >= vStart) && (p < vEnd)) { 7299 /* Old vertices stay the same */ 7300 newp = vStartNew + (p - vStart); 7301 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7302 } else if ((p >= fStart) && (p < fEnd)) { 7303 /* Old faces add new faces and vertex */ 7304 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7305 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7306 for (r = 0; r < 2; ++r) { 7307 newp = fStartNew + (p - fStart)*2 + r; 7308 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7309 } 7310 } else if ((p >= cStart) && (p < cEnd)) { 7311 /* Old cells add new cells and interior faces */ 7312 for (r = 0; r < 4; ++r) { 7313 newp = cStartNew + (p - cStart)*4 + r; 7314 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7315 } 7316 for (r = 0; r < 3; ++r) { 7317 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7318 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7319 } 7320 } 7321 break; 7322 case 2: 7323 /* Hex 2D */ 7324 if ((p >= vStart) && (p < vEnd)) { 7325 /* Old vertices stay the same */ 7326 newp = vStartNew + (p - vStart); 7327 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7328 } else if ((p >= fStart) && (p < fEnd)) { 7329 /* Old faces add new faces and vertex */ 7330 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7331 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7332 for (r = 0; r < 2; ++r) { 7333 newp = fStartNew + (p - fStart)*2 + r; 7334 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7335 } 7336 } else if ((p >= cStart) && (p < cEnd)) { 7337 /* Old cells add new cells and interior faces and vertex */ 7338 for (r = 0; r < 4; ++r) { 7339 newp = cStartNew + (p - cStart)*4 + r; 7340 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7341 } 7342 for (r = 0; r < 4; ++r) { 7343 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7344 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7345 } 7346 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7347 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7348 } 7349 break; 7350 case 3: 7351 /* Hybrid simplicial 2D */ 7352 if ((p >= vStart) && (p < vEnd)) { 7353 /* Old vertices stay the same */ 7354 newp = vStartNew + (p - vStart); 7355 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7356 } else if ((p >= fStart) && (p < fMax)) { 7357 /* Old interior faces add new faces and vertex */ 7358 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7359 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7360 for (r = 0; r < 2; ++r) { 7361 newp = fStartNew + (p - fStart)*2 + r; 7362 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7363 } 7364 } else if ((p >= fMax) && (p < fEnd)) { 7365 /* Old hybrid faces stay the same */ 7366 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7367 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7368 } else if ((p >= cStart) && (p < cMax)) { 7369 /* Old interior cells add new cells and interior faces */ 7370 for (r = 0; r < 4; ++r) { 7371 newp = cStartNew + (p - cStart)*4 + r; 7372 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7373 } 7374 for (r = 0; r < 3; ++r) { 7375 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7376 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7377 } 7378 } else if ((p >= cMax) && (p < cEnd)) { 7379 /* Old hybrid cells add new cells and hybrid face */ 7380 for (r = 0; r < 2; ++r) { 7381 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7382 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7383 } 7384 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7385 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7386 } 7387 break; 7388 default: 7389 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7390 } 7391 } 7392 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7393 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7394 } 7395 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7396 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7397 if (0) { 7398 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7399 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7400 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7401 } 7402 } 7403 PetscFunctionReturn(0); 7404 } 7405 7406 #undef __FUNCT__ 7407 #define __FUNCT__ "DMPlexRefine_Uniform" 7408 /* This will only work for interpolated meshes */ 7409 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7410 { 7411 DM rdm; 7412 PetscInt *depthSize; 7413 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7414 PetscErrorCode ierr; 7415 7416 PetscFunctionBegin; 7417 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7418 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7419 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7420 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7421 /* Calculate number of new points of each depth */ 7422 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7423 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7424 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7425 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7426 /* Step 1: Set chart */ 7427 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7428 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7429 /* Step 2: Set cone/support sizes */ 7430 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7431 /* Step 3: Setup refined DM */ 7432 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7433 /* Step 4: Set cones and supports */ 7434 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7435 /* Step 5: Stratify */ 7436 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7437 /* Step 6: Set coordinates for vertices */ 7438 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7439 /* Step 7: Create pointSF */ 7440 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7441 /* Step 8: Create labels */ 7442 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7443 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7444 7445 *dmRefined = rdm; 7446 #if 0 7447 DM_Plex *mesh = (DM_Plex*) dm->data; 7448 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 7449 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 7450 7451 PetscFunctionBegin; 7452 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7453 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 7454 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7455 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7456 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 7457 7458 /* Count number of new cells which are normal and extra */ 7459 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 7460 7461 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 7462 for (c = cStart; c < cEnd2; ++c) { 7463 PetscInt n; 7464 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7465 7466 newNumCellsNormal += n; 7467 } 7468 for (c = cEnd2; c < cEnd; ++c) { 7469 PetscInt n; 7470 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7471 7472 newNumCellsExtra += n; 7473 } 7474 newNumCells = newNumCellsNormal + newNumCellsExtra; 7475 /* Count number of new vertices which are normal and extra */ 7476 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 7477 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 7478 for (c = cStart; c < cEnd; ++c) { 7479 PetscInt *closure = PETSC_NULL; 7480 PetscInt closureSize, numCorners = 0, p; 7481 7482 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7483 for (p = 0; p < closureSize*2; p += 2) { 7484 const PetscInt point = closure[p]; 7485 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 7486 } 7487 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 7488 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7489 } 7490 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 7491 for (c = cEnd2; c < cEnd; ++c) { 7492 PetscInt *closure = PETSC_NULL; 7493 PetscInt closureSize, numCorners = 0, p; 7494 7495 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7496 for (p = 0; p < closureSize*2; p += 2) { 7497 const PetscInt point = closure[p]; 7498 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 7499 } 7500 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 7501 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7502 } /* for */ 7503 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 7504 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 7505 7506 #if 1 7507 PetscInt oldNumCellsNormal = cEnd2 - cStart; 7508 PetscInt oldNumCellsExtra = cEnd - cEnd2; 7509 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 7510 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 7511 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 7512 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 7513 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 7514 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 7515 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 7516 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 7517 ierr = PetscSynchronizedFlush(comm); 7518 #endif 7519 7520 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 7521 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 7522 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 7523 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 7524 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 7525 /* Set cone and support sizes for new normal cells */ 7526 PetscInt newCell = 0; 7527 for (c = cStart; c < cEnd2; ++c) { 7528 PetscInt coneSize, n, i; 7529 7530 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7531 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7532 for (i = 0; i < n; ++i, ++newCell) { 7533 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 7534 } 7535 7536 PetscInt *closure = PETSC_NULL; 7537 PetscInt closureSize, numCorners = 0, p; 7538 7539 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7540 for (p = 0; p < closureSize*2; p += 2) { 7541 const PetscInt point = closure[p]; 7542 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 7543 } 7544 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); */ /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7545 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7546 } 7547 7548 /* Reset current new cell value and loop over censored cells. */ 7549 curNewCell = _orderNewMesh->cellsCensored().min(); 7550 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7551 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7552 /* Set new cone and support sizes */ 7553 cV.clear(); 7554 sieve->cone(*c_iter, cV); 7555 const point_type * cone = cV.getPoints(); 7556 const int coneSize = cV.getSize(); 7557 7558 const point_type * newCells; 7559 int numNewCells = 0; 7560 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7561 7562 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7563 newSieve->setConeSize(curNewCell, coneSize); 7564 for (int iVertex=0; iVertex < coneSize; ++iVertex) { 7565 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7566 } /* for */ 7567 } /* for */ 7568 } /* for */ 7569 newSieve->allocate(); 7570 7571 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7572 7573 /* Create refined cells in new sieve. */ 7574 curNewCell = _orderNewMesh->cellsNormal().min(); 7575 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7576 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7577 cV.clear(); 7578 sieve->cone(*c_iter, cV); 7579 const point_type *cone = cV.getPoints(); 7580 const int coneSize = cV.getSize(); 7581 7582 const point_type * newCells; 7583 int numNewCells = 0; 7584 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7585 7586 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7587 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7588 } /* for */ 7589 } /* for */ 7590 curNewCell = _orderNewMesh->cellsCensored().min(); 7591 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7592 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7593 cV.clear(); 7594 sieve->cone(*c_iter, cV); 7595 const point_type *cone = cV.getPoints(); 7596 const int coneSize = cV.getSize(); 7597 7598 const point_type *newCells; 7599 int numNewCells = 0; 7600 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7601 7602 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7603 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7604 } /* for */ 7605 } /* for */ 7606 newSieve->symmetrize(); 7607 7608 /* Set coordinates in refined mesh. */ 7609 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7610 assert(!coordinates.isNull()); 7611 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7612 assert(!newCoordinates.isNull()); 7613 7614 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7615 assert(vertices->size() > 0); 7616 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7617 assert(spaceDim > 0); 7618 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7619 7620 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7621 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7622 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7623 } /* for */ 7624 newCoordinates->allocatePoint(); 7625 7626 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7627 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7628 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7629 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7630 } /* for */ 7631 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7632 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7633 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7634 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7635 } /* for */ 7636 7637 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7638 7639 /* Create sensored depth */ 7640 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7641 assert(!censoredLabel.isNull()); 7642 7643 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7644 7645 newSieve->roots(depthVisitor); 7646 while (depthVisitor.isModified()) { 7647 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7648 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7649 7650 depthVisitor.clear(); 7651 newSieve->support(modifiedPoints, depthVisitor); 7652 } /* while */ 7653 7654 /* Stratify refined mesh */ 7655 /* Calculate new point SF */ 7656 _calcNewOverlap(newMesh, mesh, refiner); 7657 /* Calculate new labels */ 7658 _createLabels(newMesh, mesh, refiner); 7659 #endif 7660 PetscFunctionReturn(0); 7661 } 7662 7663 #undef __FUNCT__ 7664 #define __FUNCT__ "DMPlexSetRefinementUniform" 7665 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7666 { 7667 DM_Plex *mesh = (DM_Plex*) dm->data; 7668 7669 PetscFunctionBegin; 7670 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7671 mesh->refinementUniform = refinementUniform; 7672 PetscFunctionReturn(0); 7673 } 7674 7675 #undef __FUNCT__ 7676 #define __FUNCT__ "DMPlexGetRefinementUniform" 7677 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7678 { 7679 DM_Plex *mesh = (DM_Plex*) dm->data; 7680 7681 PetscFunctionBegin; 7682 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7683 PetscValidPointer(refinementUniform, 2); 7684 *refinementUniform = mesh->refinementUniform; 7685 PetscFunctionReturn(0); 7686 } 7687 7688 #undef __FUNCT__ 7689 #define __FUNCT__ "DMPlexSetRefinementLimit" 7690 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7691 { 7692 DM_Plex *mesh = (DM_Plex*) dm->data; 7693 7694 PetscFunctionBegin; 7695 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7696 mesh->refinementLimit = refinementLimit; 7697 PetscFunctionReturn(0); 7698 } 7699 7700 #undef __FUNCT__ 7701 #define __FUNCT__ "DMPlexGetRefinementLimit" 7702 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7703 { 7704 DM_Plex *mesh = (DM_Plex*) dm->data; 7705 7706 PetscFunctionBegin; 7707 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7708 PetscValidPointer(refinementLimit, 2); 7709 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7710 *refinementLimit = mesh->refinementLimit; 7711 PetscFunctionReturn(0); 7712 } 7713 7714 #undef __FUNCT__ 7715 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7716 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7717 { 7718 PetscInt dim, cStart, coneSize, cMax; 7719 PetscErrorCode ierr; 7720 7721 PetscFunctionBegin; 7722 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7723 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7724 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7725 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7726 switch (dim) { 7727 case 2: 7728 switch (coneSize) { 7729 case 3: 7730 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7731 else *cellRefiner = 1; /* Triangular */ 7732 break; 7733 case 4: 7734 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7735 else *cellRefiner = 2; /* Quadrilateral */ 7736 break; 7737 default: 7738 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7739 } 7740 break; 7741 default: 7742 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7743 } 7744 PetscFunctionReturn(0); 7745 } 7746 7747 #undef __FUNCT__ 7748 #define __FUNCT__ "DMRefine_Plex" 7749 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7750 { 7751 PetscReal refinementLimit; 7752 PetscInt dim, cStart, cEnd; 7753 char genname[1024], *name = PETSC_NULL; 7754 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7755 PetscErrorCode ierr; 7756 7757 PetscFunctionBegin; 7758 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7759 if (isUniform) { 7760 CellRefiner cellRefiner; 7761 7762 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7763 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7764 PetscFunctionReturn(0); 7765 } 7766 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7767 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7768 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7769 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7770 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7771 if (flg) name = genname; 7772 if (name) { 7773 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7774 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7775 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7776 } 7777 switch (dim) { 7778 case 2: 7779 if (!name || isTriangle) { 7780 #if defined(PETSC_HAVE_TRIANGLE) 7781 double *maxVolumes; 7782 PetscInt c; 7783 7784 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7785 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7786 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7787 #else 7788 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7789 #endif 7790 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7791 break; 7792 case 3: 7793 if (!name || isCTetgen) { 7794 #if defined(PETSC_HAVE_CTETGEN) 7795 PetscReal *maxVolumes; 7796 PetscInt c; 7797 7798 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7799 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7800 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7801 #else 7802 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7803 #endif 7804 } else if (isTetgen) { 7805 #if defined(PETSC_HAVE_TETGEN) 7806 double *maxVolumes; 7807 PetscInt c; 7808 7809 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7810 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7811 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7812 #else 7813 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7814 #endif 7815 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7816 break; 7817 default: 7818 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7819 } 7820 PetscFunctionReturn(0); 7821 } 7822 7823 #undef __FUNCT__ 7824 #define __FUNCT__ "DMPlexGetDepth" 7825 /*@ 7826 DMPlexGetDepth - get the number of strata 7827 7828 Not Collective 7829 7830 Input Parameters: 7831 . dm - The DMPlex object 7832 7833 Output Parameters: 7834 . depth - number of strata 7835 7836 Level: developer 7837 7838 Notes: 7839 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7840 7841 .keywords: mesh, points 7842 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7843 @*/ 7844 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7845 { 7846 PetscInt d; 7847 PetscErrorCode ierr; 7848 7849 PetscFunctionBegin; 7850 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7851 PetscValidPointer(depth, 2); 7852 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7853 *depth = d-1; 7854 PetscFunctionReturn(0); 7855 } 7856 7857 #undef __FUNCT__ 7858 #define __FUNCT__ "DMPlexGetDepthStratum" 7859 /*@ 7860 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7861 7862 Not Collective 7863 7864 Input Parameters: 7865 + dm - The DMPlex object 7866 - stratumValue - The requested depth 7867 7868 Output Parameters: 7869 + start - The first point at this depth 7870 - end - One beyond the last point at this depth 7871 7872 Level: developer 7873 7874 .keywords: mesh, points 7875 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7876 @*/ 7877 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7878 { 7879 DM_Plex *mesh = (DM_Plex*) dm->data; 7880 DMLabel next = mesh->labels; 7881 PetscBool flg = PETSC_FALSE; 7882 PetscInt depth; 7883 PetscErrorCode ierr; 7884 7885 PetscFunctionBegin; 7886 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7887 if (stratumValue < 0) { 7888 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7889 PetscFunctionReturn(0); 7890 } else { 7891 PetscInt pStart, pEnd; 7892 7893 if (start) *start = 0; 7894 if (end) *end = 0; 7895 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7896 if (pStart == pEnd) PetscFunctionReturn(0); 7897 } 7898 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7899 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7900 /* We should have a generic GetLabel() and a Label class */ 7901 while (next) { 7902 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7903 if (flg) break; 7904 next = next->next; 7905 } 7906 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7907 depth = stratumValue; 7908 if ((depth < 0) || (depth >= next->numStrata)) { 7909 if (start) *start = 0; 7910 if (end) *end = 0; 7911 } else { 7912 if (start) *start = next->points[next->stratumOffsets[depth]]; 7913 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7914 } 7915 PetscFunctionReturn(0); 7916 } 7917 7918 #undef __FUNCT__ 7919 #define __FUNCT__ "DMPlexGetHeightStratum" 7920 /*@ 7921 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7922 7923 Not Collective 7924 7925 Input Parameters: 7926 + dm - The DMPlex object 7927 - stratumValue - The requested height 7928 7929 Output Parameters: 7930 + start - The first point at this height 7931 - end - One beyond the last point at this height 7932 7933 Level: developer 7934 7935 .keywords: mesh, points 7936 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7937 @*/ 7938 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7939 { 7940 DM_Plex *mesh = (DM_Plex*) dm->data; 7941 DMLabel next = mesh->labels; 7942 PetscBool flg = PETSC_FALSE; 7943 PetscInt depth; 7944 PetscErrorCode ierr; 7945 7946 PetscFunctionBegin; 7947 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7948 if (stratumValue < 0) { 7949 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7950 } else { 7951 PetscInt pStart, pEnd; 7952 7953 if (start) *start = 0; 7954 if (end) *end = 0; 7955 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7956 if (pStart == pEnd) PetscFunctionReturn(0); 7957 } 7958 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7959 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7960 /* We should have a generic GetLabel() and a Label class */ 7961 while (next) { 7962 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7963 if (flg) break; 7964 next = next->next; 7965 } 7966 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7967 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7968 if ((depth < 0) || (depth >= next->numStrata)) { 7969 if (start) *start = 0; 7970 if (end) *end = 0; 7971 } else { 7972 if (start) *start = next->points[next->stratumOffsets[depth]]; 7973 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7974 } 7975 PetscFunctionReturn(0); 7976 } 7977 7978 #undef __FUNCT__ 7979 #define __FUNCT__ "DMPlexCreateSectionInitial" 7980 /* Set the number of dof on each point and separate by fields */ 7981 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7982 { 7983 PetscInt *numDofTot; 7984 PetscInt pStart = 0, pEnd = 0; 7985 PetscInt p, d, f; 7986 PetscErrorCode ierr; 7987 7988 PetscFunctionBegin; 7989 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7990 for (d = 0; d <= dim; ++d) { 7991 numDofTot[d] = 0; 7992 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7993 } 7994 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7995 if (numFields > 0) { 7996 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7997 if (numComp) { 7998 for (f = 0; f < numFields; ++f) { 7999 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 8000 } 8001 } 8002 } 8003 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8004 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 8005 for (d = 0; d <= dim; ++d) { 8006 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 8007 for (p = pStart; p < pEnd; ++p) { 8008 for (f = 0; f < numFields; ++f) { 8009 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 8010 } 8011 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 8012 } 8013 } 8014 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 8015 PetscFunctionReturn(0); 8016 } 8017 8018 #undef __FUNCT__ 8019 #define __FUNCT__ "DMPlexCreateSectionBCDof" 8020 /* Set the number of dof on each point and separate by fields 8021 If constDof is PETSC_DETERMINE, constrain every dof on the point 8022 */ 8023 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 8024 { 8025 PetscInt numFields; 8026 PetscInt bc; 8027 PetscErrorCode ierr; 8028 8029 PetscFunctionBegin; 8030 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8031 for (bc = 0; bc < numBC; ++bc) { 8032 PetscInt field = 0; 8033 const PetscInt *idx; 8034 PetscInt n, i; 8035 8036 if (numFields) field = bcField[bc]; 8037 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 8038 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8039 for (i = 0; i < n; ++i) { 8040 const PetscInt p = idx[i]; 8041 PetscInt numConst = constDof; 8042 8043 /* Constrain every dof on the point */ 8044 if (numConst < 0) { 8045 if (numFields) { 8046 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 8047 } else { 8048 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 8049 } 8050 } 8051 if (numFields) { 8052 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 8053 } 8054 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 8055 } 8056 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8057 } 8058 PetscFunctionReturn(0); 8059 } 8060 8061 #undef __FUNCT__ 8062 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 8063 /* Set the constrained indices on each point and separate by fields */ 8064 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 8065 { 8066 PetscInt *maxConstraints; 8067 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 8068 PetscErrorCode ierr; 8069 8070 PetscFunctionBegin; 8071 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8072 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8073 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 8074 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 8075 for (p = pStart; p < pEnd; ++p) { 8076 PetscInt cdof; 8077 8078 if (numFields) { 8079 for (f = 0; f < numFields; ++f) { 8080 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 8081 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 8082 } 8083 } else { 8084 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8085 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 8086 } 8087 } 8088 for (f = 0; f < numFields; ++f) { 8089 maxConstraints[numFields] += maxConstraints[f]; 8090 } 8091 if (maxConstraints[numFields]) { 8092 PetscInt *indices; 8093 8094 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8095 for (p = pStart; p < pEnd; ++p) { 8096 PetscInt cdof, d; 8097 8098 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8099 if (cdof) { 8100 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 8101 if (numFields) { 8102 PetscInt numConst = 0, foff = 0; 8103 8104 for (f = 0; f < numFields; ++f) { 8105 PetscInt cfdof, fdof; 8106 8107 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8108 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 8109 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 8110 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 8111 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 8112 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 8113 numConst += cfdof; 8114 foff += fdof; 8115 } 8116 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8117 } else { 8118 for (d = 0; d < cdof; ++d) indices[d] = d; 8119 } 8120 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8121 } 8122 } 8123 ierr = PetscFree(indices);CHKERRQ(ierr); 8124 } 8125 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 8126 PetscFunctionReturn(0); 8127 } 8128 8129 #undef __FUNCT__ 8130 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 8131 /* Set the constrained field indices on each point */ 8132 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 8133 { 8134 const PetscInt *points, *indices; 8135 PetscInt numFields, maxDof, numPoints, p, numConstraints; 8136 PetscErrorCode ierr; 8137 8138 PetscFunctionBegin; 8139 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8140 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 8141 8142 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 8143 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 8144 if (!constraintIndices) { 8145 PetscInt *idx, i; 8146 8147 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8148 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 8149 for (i = 0; i < maxDof; ++i) idx[i] = i; 8150 for (p = 0; p < numPoints; ++p) { 8151 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 8152 } 8153 ierr = PetscFree(idx);CHKERRQ(ierr); 8154 } else { 8155 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 8156 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 8157 for (p = 0; p < numPoints; ++p) { 8158 PetscInt fcdof; 8159 8160 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 8161 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); 8162 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 8163 } 8164 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 8165 } 8166 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 8167 PetscFunctionReturn(0); 8168 } 8169 8170 #undef __FUNCT__ 8171 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 8172 /* Set the constrained indices on each point and separate by fields */ 8173 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 8174 { 8175 PetscInt *indices; 8176 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 8177 PetscErrorCode ierr; 8178 8179 PetscFunctionBegin; 8180 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8181 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8182 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8183 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 8184 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8185 for (p = pStart; p < pEnd; ++p) { 8186 PetscInt cdof, d; 8187 8188 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8189 if (cdof) { 8190 PetscInt numConst = 0, foff = 0; 8191 8192 for (f = 0; f < numFields; ++f) { 8193 const PetscInt *fcind; 8194 PetscInt fdof, fcdof; 8195 8196 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8197 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8198 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 8199 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8200 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 8201 foff += fdof; 8202 numConst += fcdof; 8203 } 8204 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8205 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8206 } 8207 } 8208 ierr = PetscFree(indices);CHKERRQ(ierr); 8209 PetscFunctionReturn(0); 8210 } 8211 8212 #undef __FUNCT__ 8213 #define __FUNCT__ "DMPlexCreateSection" 8214 /*@C 8215 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8216 8217 Not Collective 8218 8219 Input Parameters: 8220 + dm - The DMPlex object 8221 . dim - The spatial dimension of the problem 8222 . numFields - The number of fields in the problem 8223 . numComp - An array of size numFields that holds the number of components for each field 8224 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8225 . numBC - The number of boundary conditions 8226 . bcField - An array of size numBC giving the field number for each boundry condition 8227 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8228 8229 Output Parameter: 8230 . section - The PetscSection object 8231 8232 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 8233 nubmer of dof for field 0 on each edge. 8234 8235 Level: developer 8236 8237 .keywords: mesh, elements 8238 .seealso: DMPlexCreate(), PetscSectionCreate() 8239 @*/ 8240 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8241 { 8242 PetscErrorCode ierr; 8243 8244 PetscFunctionBegin; 8245 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8246 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8247 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8248 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8249 { 8250 PetscBool view = PETSC_FALSE; 8251 8252 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8253 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8254 } 8255 PetscFunctionReturn(0); 8256 } 8257 8258 #undef __FUNCT__ 8259 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8260 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8261 { 8262 PetscSection section; 8263 PetscErrorCode ierr; 8264 8265 PetscFunctionBegin; 8266 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8267 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8268 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8269 PetscFunctionReturn(0); 8270 } 8271 8272 #undef __FUNCT__ 8273 #define __FUNCT__ "DMPlexGetCoordinateSection" 8274 /*@ 8275 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8276 8277 Not Collective 8278 8279 Input Parameter: 8280 . dm - The DMPlex object 8281 8282 Output Parameter: 8283 . section - The PetscSection object 8284 8285 Level: intermediate 8286 8287 .keywords: mesh, coordinates 8288 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8289 @*/ 8290 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8291 { 8292 DM cdm; 8293 PetscErrorCode ierr; 8294 8295 PetscFunctionBegin; 8296 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8297 PetscValidPointer(section, 2); 8298 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8299 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8300 PetscFunctionReturn(0); 8301 } 8302 8303 #undef __FUNCT__ 8304 #define __FUNCT__ "DMPlexSetCoordinateSection" 8305 /*@ 8306 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8307 8308 Not Collective 8309 8310 Input Parameters: 8311 + dm - The DMPlex object 8312 - section - The PetscSection object 8313 8314 Level: intermediate 8315 8316 .keywords: mesh, coordinates 8317 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8318 @*/ 8319 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8320 { 8321 DM cdm; 8322 PetscErrorCode ierr; 8323 8324 PetscFunctionBegin; 8325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8326 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8327 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8328 PetscFunctionReturn(0); 8329 } 8330 8331 #undef __FUNCT__ 8332 #define __FUNCT__ "DMPlexGetConeSection" 8333 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8334 { 8335 DM_Plex *mesh = (DM_Plex*) dm->data; 8336 8337 PetscFunctionBegin; 8338 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8339 if (section) *section = mesh->coneSection; 8340 PetscFunctionReturn(0); 8341 } 8342 8343 #undef __FUNCT__ 8344 #define __FUNCT__ "DMPlexGetCones" 8345 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8346 { 8347 DM_Plex *mesh = (DM_Plex*) dm->data; 8348 8349 PetscFunctionBegin; 8350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8351 if (cones) *cones = mesh->cones; 8352 PetscFunctionReturn(0); 8353 } 8354 8355 #undef __FUNCT__ 8356 #define __FUNCT__ "DMPlexGetConeOrientations" 8357 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8358 { 8359 DM_Plex *mesh = (DM_Plex*) dm->data; 8360 8361 PetscFunctionBegin; 8362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8363 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8364 PetscFunctionReturn(0); 8365 } 8366 8367 #undef __FUNCT__ 8368 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8369 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8370 { 8371 const PetscInt embedDim = 2; 8372 PetscReal x = PetscRealPart(point[0]); 8373 PetscReal y = PetscRealPart(point[1]); 8374 PetscReal v0[2], J[4], invJ[4], detJ; 8375 PetscReal xi, eta; 8376 PetscErrorCode ierr; 8377 8378 PetscFunctionBegin; 8379 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8380 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8381 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8382 8383 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8384 else *cell = -1; 8385 PetscFunctionReturn(0); 8386 } 8387 8388 #undef __FUNCT__ 8389 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8390 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8391 { 8392 PetscSection coordSection; 8393 Vec coordsLocal; 8394 const PetscScalar *coords; 8395 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8396 PetscReal x = PetscRealPart(point[0]); 8397 PetscReal y = PetscRealPart(point[1]); 8398 PetscInt crossings = 0, f; 8399 PetscErrorCode ierr; 8400 8401 PetscFunctionBegin; 8402 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8403 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8404 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8405 for (f = 0; f < 4; ++f) { 8406 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8407 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8408 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8409 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8410 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8411 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8412 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8413 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8414 if ((cond1 || cond2) && above) ++crossings; 8415 } 8416 if (crossings % 2) *cell = c; 8417 else *cell = -1; 8418 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8419 PetscFunctionReturn(0); 8420 } 8421 8422 #undef __FUNCT__ 8423 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8424 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8425 { 8426 const PetscInt embedDim = 3; 8427 PetscReal v0[3], J[9], invJ[9], detJ; 8428 PetscReal x = PetscRealPart(point[0]); 8429 PetscReal y = PetscRealPart(point[1]); 8430 PetscReal z = PetscRealPart(point[2]); 8431 PetscReal xi, eta, zeta; 8432 PetscErrorCode ierr; 8433 8434 PetscFunctionBegin; 8435 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8436 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8437 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8438 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8439 8440 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8441 else *cell = -1; 8442 PetscFunctionReturn(0); 8443 } 8444 8445 #undef __FUNCT__ 8446 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8447 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8448 { 8449 PetscSection coordSection; 8450 Vec coordsLocal; 8451 const PetscScalar *coords; 8452 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8453 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8454 PetscBool found = PETSC_TRUE; 8455 PetscInt f; 8456 PetscErrorCode ierr; 8457 8458 PetscFunctionBegin; 8459 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8460 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8461 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8462 for (f = 0; f < 6; ++f) { 8463 /* Check the point is under plane */ 8464 /* Get face normal */ 8465 PetscReal v_i[3]; 8466 PetscReal v_j[3]; 8467 PetscReal normal[3]; 8468 PetscReal pp[3]; 8469 PetscReal dot; 8470 8471 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8472 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8473 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8474 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8475 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8476 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8477 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8478 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8479 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8480 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8481 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8482 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8483 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8484 8485 /* Check that projected point is in face (2D location problem) */ 8486 if (dot < 0.0) { 8487 found = PETSC_FALSE; 8488 break; 8489 } 8490 } 8491 if (found) *cell = c; 8492 else *cell = -1; 8493 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8494 PetscFunctionReturn(0); 8495 } 8496 8497 #undef __FUNCT__ 8498 #define __FUNCT__ "DMLocatePoints_Plex" 8499 /* 8500 Need to implement using the guess 8501 */ 8502 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8503 { 8504 PetscInt cell = -1 /*, guess = -1*/; 8505 PetscInt bs, numPoints, p; 8506 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8507 PetscInt *cells; 8508 PetscScalar *a; 8509 PetscErrorCode ierr; 8510 8511 PetscFunctionBegin; 8512 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8513 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8514 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8515 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8516 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8517 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8518 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8519 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); 8520 numPoints /= bs; 8521 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8522 for (p = 0; p < numPoints; ++p) { 8523 const PetscScalar *point = &a[p*bs]; 8524 8525 switch (dim) { 8526 case 2: 8527 for (c = cStart; c < cEnd; ++c) { 8528 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8529 switch (coneSize) { 8530 case 3: 8531 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8532 break; 8533 case 4: 8534 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8535 break; 8536 default: 8537 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8538 } 8539 if (cell >= 0) break; 8540 } 8541 break; 8542 case 3: 8543 for (c = cStart; c < cEnd; ++c) { 8544 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8545 switch (coneSize) { 8546 case 4: 8547 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8548 break; 8549 case 8: 8550 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8551 break; 8552 default: 8553 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8554 } 8555 if (cell >= 0) break; 8556 } 8557 break; 8558 default: 8559 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8560 } 8561 cells[p] = cell; 8562 } 8563 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8564 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8565 PetscFunctionReturn(0); 8566 } 8567 8568 /******************************** FEM Support **********************************/ 8569 8570 #undef __FUNCT__ 8571 #define __FUNCT__ "DMPlexVecGetClosure" 8572 /*@C 8573 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8574 8575 Not collective 8576 8577 Input Parameters: 8578 + dm - The DM 8579 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8580 . v - The local vector 8581 - point - The sieve point in the DM 8582 8583 Output Parameters: 8584 + csize - The number of values in the closure, or PETSC_NULL 8585 - values - The array of values, which is a borrowed array and should not be freed 8586 8587 Level: intermediate 8588 8589 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8590 @*/ 8591 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8592 { 8593 PetscScalar *array, *vArray; 8594 PetscInt *points = PETSC_NULL; 8595 PetscInt offsets[32]; 8596 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8597 PetscErrorCode ierr; 8598 8599 PetscFunctionBegin; 8600 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8601 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8602 if (!section) { 8603 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8604 } 8605 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8606 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8607 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8608 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8609 /* Compress out points not in the section */ 8610 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8611 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8612 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8613 points[q*2] = points[p]; 8614 points[q*2+1] = points[p+1]; 8615 ++q; 8616 } 8617 } 8618 numPoints = q; 8619 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8620 PetscInt dof, fdof; 8621 8622 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8623 for (f = 0; f < numFields; ++f) { 8624 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8625 offsets[f+1] += fdof; 8626 } 8627 size += dof; 8628 } 8629 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8630 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8631 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8632 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8633 for (p = 0; p < numPoints*2; p += 2) { 8634 PetscInt o = points[p+1]; 8635 PetscInt dof, off, d; 8636 PetscScalar *varr; 8637 8638 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8639 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8640 varr = &vArray[off]; 8641 if (numFields) { 8642 PetscInt fdof, foff, fcomp, f, c; 8643 8644 for (f = 0, foff = 0; f < numFields; ++f) { 8645 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8646 if (o >= 0) { 8647 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8648 array[offsets[f]] = varr[foff+d]; 8649 } 8650 } else { 8651 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8652 for (d = fdof/fcomp-1; d >= 0; --d) { 8653 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8654 array[offsets[f]] = varr[foff+d*fcomp+c]; 8655 } 8656 } 8657 } 8658 foff += fdof; 8659 } 8660 } else { 8661 if (o >= 0) { 8662 for (d = 0; d < dof; ++d, ++offsets[0]) { 8663 array[offsets[0]] = varr[d]; 8664 } 8665 } else { 8666 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8667 array[offsets[0]] = varr[d]; 8668 } 8669 } 8670 } 8671 } 8672 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8673 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8674 if (csize) *csize = size; 8675 *values = array; 8676 PetscFunctionReturn(0); 8677 } 8678 8679 #undef __FUNCT__ 8680 #define __FUNCT__ "DMPlexVecRestoreClosure" 8681 /*@C 8682 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8683 8684 Not collective 8685 8686 Input Parameters: 8687 + dm - The DM 8688 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8689 . v - The local vector 8690 . point - The sieve point in the DM 8691 . csize - The number of values in the closure, or PETSC_NULL 8692 - values - The array of values, which is a borrowed array and should not be freed 8693 8694 Level: intermediate 8695 8696 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8697 @*/ 8698 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8699 { 8700 PetscInt size = 0; 8701 PetscErrorCode ierr; 8702 8703 PetscFunctionBegin; 8704 /* Should work without recalculating size */ 8705 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8706 PetscFunctionReturn(0); 8707 } 8708 8709 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8710 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8711 8712 #undef __FUNCT__ 8713 #define __FUNCT__ "updatePoint_private" 8714 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8715 { 8716 PetscInt cdof; /* The number of constraints on this point */ 8717 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8718 PetscScalar *a; 8719 PetscInt off, cind = 0, k; 8720 PetscErrorCode ierr; 8721 8722 PetscFunctionBegin; 8723 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8724 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8725 a = &array[off]; 8726 if (!cdof || setBC) { 8727 if (orientation >= 0) { 8728 for (k = 0; k < dof; ++k) { 8729 fuse(&a[k], values[k]); 8730 } 8731 } else { 8732 for (k = 0; k < dof; ++k) { 8733 fuse(&a[k], values[dof-k-1]); 8734 } 8735 } 8736 } else { 8737 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8738 if (orientation >= 0) { 8739 for (k = 0; k < dof; ++k) { 8740 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8741 fuse(&a[k], values[k]); 8742 } 8743 } else { 8744 for (k = 0; k < dof; ++k) { 8745 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8746 fuse(&a[k], values[dof-k-1]); 8747 } 8748 } 8749 } 8750 PetscFunctionReturn(0); 8751 } 8752 8753 #undef __FUNCT__ 8754 #define __FUNCT__ "updatePointFields_private" 8755 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8756 { 8757 PetscScalar *a; 8758 PetscInt numFields, off, foff, f; 8759 PetscErrorCode ierr; 8760 8761 PetscFunctionBegin; 8762 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8763 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8764 a = &array[off]; 8765 for (f = 0, foff = 0; f < numFields; ++f) { 8766 PetscInt fdof, fcomp, fcdof; 8767 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8768 PetscInt cind = 0, k, c; 8769 8770 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8771 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8772 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8773 if (!fcdof || setBC) { 8774 if (orientation >= 0) { 8775 for (k = 0; k < fdof; ++k) { 8776 fuse(&a[foff+k], values[foffs[f]+k]); 8777 } 8778 } else { 8779 for (k = fdof/fcomp-1; k >= 0; --k) { 8780 for (c = 0; c < fcomp; ++c) { 8781 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8782 } 8783 } 8784 } 8785 } else { 8786 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8787 if (orientation >= 0) { 8788 for (k = 0; k < fdof; ++k) { 8789 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8790 fuse(&a[foff+k], values[foffs[f]+k]); 8791 } 8792 } else { 8793 for (k = fdof/fcomp-1; k >= 0; --k) { 8794 for (c = 0; c < fcomp; ++c) { 8795 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8796 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8797 } 8798 } 8799 } 8800 } 8801 foff += fdof; 8802 foffs[f] += fdof; 8803 } 8804 PetscFunctionReturn(0); 8805 } 8806 8807 #undef __FUNCT__ 8808 #define __FUNCT__ "DMPlexVecSetClosure" 8809 /*@C 8810 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8811 8812 Not collective 8813 8814 Input Parameters: 8815 + dm - The DM 8816 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8817 . v - The local vector 8818 . point - The sieve point in the DM 8819 . values - The array of values, which is a borrowed array and should not be freed 8820 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8821 8822 Level: intermediate 8823 8824 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8825 @*/ 8826 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8827 { 8828 PetscScalar *array; 8829 PetscInt *points = PETSC_NULL; 8830 PetscInt offsets[32]; 8831 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8832 PetscErrorCode ierr; 8833 8834 PetscFunctionBegin; 8835 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8836 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8837 if (!section) { 8838 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8839 } 8840 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8841 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8842 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8843 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8844 /* Compress out points not in the section */ 8845 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8846 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8847 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8848 points[q*2] = points[p]; 8849 points[q*2+1] = points[p+1]; 8850 ++q; 8851 } 8852 } 8853 numPoints = q; 8854 for (p = 0; p < numPoints*2; p += 2) { 8855 PetscInt fdof; 8856 8857 for (f = 0; f < numFields; ++f) { 8858 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8859 offsets[f+1] += fdof; 8860 } 8861 } 8862 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8863 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8864 if (numFields) { 8865 switch (mode) { 8866 case INSERT_VALUES: 8867 for (p = 0; p < numPoints*2; p += 2) { 8868 PetscInt o = points[p+1]; 8869 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8870 } break; 8871 case INSERT_ALL_VALUES: 8872 for (p = 0; p < numPoints*2; p += 2) { 8873 PetscInt o = points[p+1]; 8874 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8875 } break; 8876 case ADD_VALUES: 8877 for (p = 0; p < numPoints*2; p += 2) { 8878 PetscInt o = points[p+1]; 8879 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8880 } break; 8881 case ADD_ALL_VALUES: 8882 for (p = 0; p < numPoints*2; p += 2) { 8883 PetscInt o = points[p+1]; 8884 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8885 } break; 8886 default: 8887 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8888 } 8889 } else { 8890 switch (mode) { 8891 case INSERT_VALUES: 8892 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8893 PetscInt o = points[p+1]; 8894 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8895 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8896 } break; 8897 case INSERT_ALL_VALUES: 8898 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8899 PetscInt o = points[p+1]; 8900 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8901 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8902 } break; 8903 case ADD_VALUES: 8904 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8905 PetscInt o = points[p+1]; 8906 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8907 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8908 } break; 8909 case ADD_ALL_VALUES: 8910 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8911 PetscInt o = points[p+1]; 8912 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8913 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8914 } break; 8915 default: 8916 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8917 } 8918 } 8919 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8920 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8921 PetscFunctionReturn(0); 8922 } 8923 8924 #undef __FUNCT__ 8925 #define __FUNCT__ "DMPlexPrintMatSetValues" 8926 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8927 { 8928 PetscMPIInt rank; 8929 PetscInt i, j; 8930 PetscErrorCode ierr; 8931 8932 PetscFunctionBegin; 8933 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8934 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8935 for (i = 0; i < numIndices; i++) { 8936 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8937 } 8938 for (i = 0; i < numIndices; i++) { 8939 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8940 for (j = 0; j < numIndices; j++) { 8941 #if defined(PETSC_USE_COMPLEX) 8942 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8943 #else 8944 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8945 #endif 8946 } 8947 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8948 } 8949 PetscFunctionReturn(0); 8950 } 8951 8952 #undef __FUNCT__ 8953 #define __FUNCT__ "indicesPoint_private" 8954 /* . off - The global offset of this point */ 8955 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8956 { 8957 PetscInt cdof; /* The number of constraints on this point */ 8958 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8959 PetscInt cind = 0, k; 8960 PetscErrorCode ierr; 8961 8962 PetscFunctionBegin; 8963 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8964 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8965 if (!cdof || setBC) { 8966 if (orientation >= 0) { 8967 for (k = 0; k < dof; ++k) indices[k] = off+k; 8968 } else { 8969 for (k = 0; k < dof; ++k) indices[dof-k-1] = off+k; 8970 } 8971 } else { 8972 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8973 if (orientation >= 0) { 8974 for (k = 0; k < dof; ++k) { 8975 if ((cind < cdof) && (k == cdofs[cind])) { 8976 /* Insert check for returning constrained indices */ 8977 indices[k] = -(off+k+1); 8978 ++cind; 8979 } else { 8980 indices[k] = off+k-cind; 8981 } 8982 } 8983 } else { 8984 for (k = 0; k < dof; ++k) { 8985 if ((cind < cdof) && (k == cdofs[cind])) { 8986 /* Insert check for returning constrained indices */ 8987 indices[dof-k-1] = -(off+k+1); 8988 ++cind; 8989 } else { 8990 indices[dof-k-1] = off+k-cind; 8991 } 8992 } 8993 } 8994 } 8995 PetscFunctionReturn(0); 8996 } 8997 8998 #undef __FUNCT__ 8999 #define __FUNCT__ "indicesPointFields_private" 9000 /* . off - The global offset of this point */ 9001 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 9002 { 9003 PetscInt numFields, foff, f; 9004 PetscErrorCode ierr; 9005 9006 PetscFunctionBegin; 9007 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9008 for (f = 0, foff = 0; f < numFields; ++f) { 9009 PetscInt fdof, fcomp, cfdof; 9010 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 9011 PetscInt cind = 0, k, c; 9012 9013 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 9014 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 9015 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 9016 if (!cfdof || setBC) { 9017 if (orientation >= 0) { 9018 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 9019 } else { 9020 for (k = fdof/fcomp-1; k >= 0; --k) { 9021 for (c = 0; c < fcomp; ++c) { 9022 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 9023 } 9024 } 9025 } 9026 } else { 9027 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 9028 if (orientation >= 0) { 9029 for (k = 0; k < fdof; ++k) { 9030 if ((cind < cfdof) && (k == fcdofs[cind])) { 9031 indices[foffs[f]+k] = -(off+foff+k+1); 9032 ++cind; 9033 } else { 9034 indices[foffs[f]+k] = off+foff+k-cind; 9035 } 9036 } 9037 } else { 9038 for (k = fdof/fcomp-1; k >= 0; --k) { 9039 for (c = 0; c < fcomp; ++c) { 9040 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 9041 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 9042 ++cind; 9043 } else { 9044 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 9045 } 9046 } 9047 } 9048 } 9049 } 9050 foff += fdof - cfdof; 9051 foffs[f] += fdof; 9052 } 9053 PetscFunctionReturn(0); 9054 } 9055 9056 #undef __FUNCT__ 9057 #define __FUNCT__ "DMPlexMatSetClosure" 9058 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 9059 { 9060 DM_Plex *mesh = (DM_Plex*) dm->data; 9061 PetscInt *points = PETSC_NULL; 9062 PetscInt *indices; 9063 PetscInt offsets[32]; 9064 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 9065 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 9066 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 9067 PetscErrorCode ierr; 9068 9069 PetscFunctionBegin; 9070 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9071 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 9072 if (useDefault) { 9073 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9074 } 9075 if (useGlobalDefault) { 9076 if (useDefault) { 9077 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 9078 } else { 9079 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9080 } 9081 } 9082 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9083 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 9084 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 9085 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9086 /* Compress out points not in the section */ 9087 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 9088 for (p = 0, q = 0; p < numPoints*2; p += 2) { 9089 if ((points[p] >= pStart) && (points[p] < pEnd)) { 9090 points[q*2] = points[p]; 9091 points[q*2+1] = points[p+1]; 9092 ++q; 9093 } 9094 } 9095 numPoints = q; 9096 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 9097 PetscInt fdof; 9098 9099 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 9100 for (f = 0; f < numFields; ++f) { 9101 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 9102 offsets[f+1] += fdof; 9103 } 9104 numIndices += dof; 9105 } 9106 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 9107 9108 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 9109 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9110 if (numFields) { 9111 for (p = 0; p < numPoints*2; p += 2) { 9112 PetscInt o = points[p+1]; 9113 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9114 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 9115 } 9116 } else { 9117 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 9118 PetscInt o = points[p+1]; 9119 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9120 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 9121 } 9122 } 9123 if (useGlobalDefault && !useDefault) { 9124 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9125 } 9126 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 9127 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 9128 if (ierr) { 9129 PetscMPIInt rank; 9130 PetscErrorCode ierr2; 9131 9132 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 9133 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 9134 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 9135 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 9136 CHKERRQ(ierr); 9137 } 9138 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9139 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9140 PetscFunctionReturn(0); 9141 } 9142 9143 #undef __FUNCT__ 9144 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 9145 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9146 { 9147 PetscSection coordSection; 9148 Vec coordinates; 9149 const PetscScalar *coords; 9150 const PetscInt dim = 2; 9151 PetscInt d, f; 9152 PetscErrorCode ierr; 9153 9154 PetscFunctionBegin; 9155 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9156 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9157 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9158 if (v0) { 9159 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9160 } 9161 if (J) { 9162 for (d = 0; d < dim; d++) { 9163 for (f = 0; f < dim; f++) { 9164 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9165 } 9166 } 9167 *detJ = J[0]*J[3] - J[1]*J[2]; 9168 #if 0 9169 if (detJ < 0.0) { 9170 const PetscReal xLength = mesh->periodicity[0]; 9171 9172 if (xLength != 0.0) { 9173 PetscReal v0x = coords[0*dim+0]; 9174 9175 if (v0x == 0.0) v0x = v0[0] = xLength; 9176 for (f = 0; f < dim; f++) { 9177 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 9178 9179 J[0*dim+f] = 0.5*(px - v0x); 9180 } 9181 } 9182 detJ = J[0]*J[3] - J[1]*J[2]; 9183 } 9184 #endif 9185 PetscLogFlops(8.0 + 3.0); 9186 } 9187 if (invJ) { 9188 const PetscReal invDet = 1.0/(*detJ); 9189 9190 invJ[0] = invDet*J[3]; 9191 invJ[1] = -invDet*J[1]; 9192 invJ[2] = -invDet*J[2]; 9193 invJ[3] = invDet*J[0]; 9194 PetscLogFlops(5.0); 9195 } 9196 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9197 PetscFunctionReturn(0); 9198 } 9199 9200 #undef __FUNCT__ 9201 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9202 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9203 { 9204 PetscSection coordSection; 9205 Vec coordinates; 9206 const PetscScalar *coords; 9207 const PetscInt dim = 2; 9208 PetscInt d, f; 9209 PetscErrorCode ierr; 9210 9211 PetscFunctionBegin; 9212 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9213 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9214 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9215 if (v0) { 9216 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9217 } 9218 if (J) { 9219 for (d = 0; d < dim; d++) { 9220 for (f = 0; f < dim; f++) { 9221 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9222 } 9223 } 9224 *detJ = J[0]*J[3] - J[1]*J[2]; 9225 PetscLogFlops(8.0 + 3.0); 9226 } 9227 if (invJ) { 9228 const PetscReal invDet = 1.0/(*detJ); 9229 9230 invJ[0] = invDet*J[3]; 9231 invJ[1] = -invDet*J[1]; 9232 invJ[2] = -invDet*J[2]; 9233 invJ[3] = invDet*J[0]; 9234 PetscLogFlops(5.0); 9235 } 9236 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9237 PetscFunctionReturn(0); 9238 } 9239 9240 #undef __FUNCT__ 9241 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9242 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9243 { 9244 PetscSection coordSection; 9245 Vec coordinates; 9246 const PetscScalar *coords; 9247 const PetscInt dim = 3; 9248 PetscInt d, f; 9249 PetscErrorCode ierr; 9250 9251 PetscFunctionBegin; 9252 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9253 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9254 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9255 if (v0) { 9256 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9257 } 9258 if (J) { 9259 for (d = 0; d < dim; d++) { 9260 for (f = 0; f < dim; f++) { 9261 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9262 } 9263 } 9264 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9265 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9266 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9267 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9268 PetscLogFlops(18.0 + 12.0); 9269 } 9270 if (invJ) { 9271 const PetscReal invDet = 1.0/(*detJ); 9272 9273 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9274 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9275 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9276 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9277 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9278 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9279 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9280 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9281 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9282 PetscLogFlops(37.0); 9283 } 9284 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9285 PetscFunctionReturn(0); 9286 } 9287 9288 #undef __FUNCT__ 9289 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9290 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9291 { 9292 PetscSection coordSection; 9293 Vec coordinates; 9294 const PetscScalar *coords; 9295 const PetscInt dim = 3; 9296 PetscInt d; 9297 PetscErrorCode ierr; 9298 9299 PetscFunctionBegin; 9300 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9301 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9302 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9303 if (v0) { 9304 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9305 } 9306 if (J) { 9307 for (d = 0; d < dim; d++) { 9308 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9309 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9310 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9311 } 9312 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9313 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9314 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9315 PetscLogFlops(18.0 + 12.0); 9316 } 9317 if (invJ) { 9318 const PetscReal invDet = -1.0/(*detJ); 9319 9320 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9321 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9322 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9323 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9324 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9325 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9326 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9327 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9328 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9329 PetscLogFlops(37.0); 9330 } 9331 *detJ *= 8.0; 9332 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9333 PetscFunctionReturn(0); 9334 } 9335 9336 #undef __FUNCT__ 9337 #define __FUNCT__ "DMPlexComputeCellGeometry" 9338 /*@C 9339 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9340 9341 Collective on DM 9342 9343 Input Arguments: 9344 + dm - the DM 9345 - cell - the cell 9346 9347 Output Arguments: 9348 + v0 - the translation part of this affine transform 9349 . J - the Jacobian of the transform to the reference element 9350 . invJ - the inverse of the Jacobian 9351 - detJ - the Jacobian determinant 9352 9353 Level: advanced 9354 9355 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9356 @*/ 9357 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9358 { 9359 PetscInt dim, coneSize; 9360 PetscErrorCode ierr; 9361 9362 PetscFunctionBegin; 9363 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9364 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9365 switch (dim) { 9366 case 2: 9367 switch (coneSize) { 9368 case 3: 9369 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9370 break; 9371 case 4: 9372 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9373 break; 9374 default: 9375 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9376 } 9377 break; 9378 case 3: 9379 switch (coneSize) { 9380 case 4: 9381 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9382 break; 9383 case 8: 9384 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9385 break; 9386 default: 9387 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9388 } 9389 break; 9390 default: 9391 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9392 } 9393 PetscFunctionReturn(0); 9394 } 9395 9396 #undef __FUNCT__ 9397 #define __FUNCT__ "DMPlexGetFaceOrientation" 9398 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9399 { 9400 MPI_Comm comm = ((PetscObject) dm)->comm; 9401 PetscBool posOrient = PETSC_FALSE; 9402 const PetscInt debug = 0; 9403 PetscInt cellDim, faceSize, f; 9404 PetscErrorCode ierr; 9405 9406 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9407 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9408 9409 if (cellDim == numCorners-1) { 9410 /* Simplices */ 9411 faceSize = numCorners-1; 9412 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9413 } else if (cellDim == 1 && numCorners == 3) { 9414 /* Quadratic line */ 9415 faceSize = 1; 9416 posOrient = PETSC_TRUE; 9417 } else if (cellDim == 2 && numCorners == 4) { 9418 /* Quads */ 9419 faceSize = 2; 9420 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9421 posOrient = PETSC_TRUE; 9422 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9423 posOrient = PETSC_TRUE; 9424 } else { 9425 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9426 posOrient = PETSC_FALSE; 9427 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9428 } 9429 } else if (cellDim == 2 && numCorners == 6) { 9430 /* Quadratic triangle (I hate this) */ 9431 /* Edges are determined by the first 2 vertices (corners of edges) */ 9432 const PetscInt faceSizeTri = 3; 9433 PetscInt sortedIndices[3], i, iFace; 9434 PetscBool found = PETSC_FALSE; 9435 PetscInt faceVerticesTriSorted[9] = { 9436 0, 3, 4, /* bottom */ 9437 1, 4, 5, /* right */ 9438 2, 3, 5, /* left */ 9439 }; 9440 PetscInt faceVerticesTri[9] = { 9441 0, 3, 4, /* bottom */ 9442 1, 4, 5, /* right */ 9443 2, 5, 3, /* left */ 9444 }; 9445 9446 faceSize = faceSizeTri; 9447 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9448 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9449 for (iFace = 0; iFace < 3; ++iFace) { 9450 const PetscInt ii = iFace*faceSizeTri; 9451 PetscInt fVertex, cVertex; 9452 9453 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9454 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9455 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9456 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9457 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9458 faceVertices[fVertex] = origVertices[cVertex]; 9459 break; 9460 } 9461 } 9462 } 9463 found = PETSC_TRUE; 9464 break; 9465 } 9466 } 9467 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9468 if (posOriented) *posOriented = PETSC_TRUE; 9469 PetscFunctionReturn(0); 9470 } else if (cellDim == 2 && numCorners == 9) { 9471 /* Quadratic quad (I hate this) */ 9472 /* Edges are determined by the first 2 vertices (corners of edges) */ 9473 const PetscInt faceSizeQuad = 3; 9474 PetscInt sortedIndices[3], i, iFace; 9475 PetscBool found = PETSC_FALSE; 9476 PetscInt faceVerticesQuadSorted[12] = { 9477 0, 1, 4, /* bottom */ 9478 1, 2, 5, /* right */ 9479 2, 3, 6, /* top */ 9480 0, 3, 7, /* left */ 9481 }; 9482 PetscInt faceVerticesQuad[12] = { 9483 0, 1, 4, /* bottom */ 9484 1, 2, 5, /* right */ 9485 2, 3, 6, /* top */ 9486 3, 0, 7, /* left */ 9487 }; 9488 9489 faceSize = faceSizeQuad; 9490 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9491 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9492 for (iFace = 0; iFace < 4; ++iFace) { 9493 const PetscInt ii = iFace*faceSizeQuad; 9494 PetscInt fVertex, cVertex; 9495 9496 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9497 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9498 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9499 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9500 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9501 faceVertices[fVertex] = origVertices[cVertex]; 9502 break; 9503 } 9504 } 9505 } 9506 found = PETSC_TRUE; 9507 break; 9508 } 9509 } 9510 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9511 if (posOriented) *posOriented = PETSC_TRUE; 9512 PetscFunctionReturn(0); 9513 } else if (cellDim == 3 && numCorners == 8) { 9514 /* Hexes 9515 A hex is two oriented quads with the normal of the first 9516 pointing up at the second. 9517 9518 7---6 9519 /| /| 9520 4---5 | 9521 | 3-|-2 9522 |/ |/ 9523 0---1 9524 9525 Faces are determined by the first 4 vertices (corners of faces) */ 9526 const PetscInt faceSizeHex = 4; 9527 PetscInt sortedIndices[4], i, iFace; 9528 PetscBool found = PETSC_FALSE; 9529 PetscInt faceVerticesHexSorted[24] = { 9530 0, 1, 2, 3, /* bottom */ 9531 4, 5, 6, 7, /* top */ 9532 0, 1, 4, 5, /* front */ 9533 1, 2, 5, 6, /* right */ 9534 2, 3, 6, 7, /* back */ 9535 0, 3, 4, 7, /* left */ 9536 }; 9537 PetscInt faceVerticesHex[24] = { 9538 3, 2, 1, 0, /* bottom */ 9539 4, 5, 6, 7, /* top */ 9540 0, 1, 5, 4, /* front */ 9541 1, 2, 6, 5, /* right */ 9542 2, 3, 7, 6, /* back */ 9543 3, 0, 4, 7, /* left */ 9544 }; 9545 9546 faceSize = faceSizeHex; 9547 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9548 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9549 for (iFace = 0; iFace < 6; ++iFace) { 9550 const PetscInt ii = iFace*faceSizeHex; 9551 PetscInt fVertex, cVertex; 9552 9553 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9554 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9555 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9556 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9557 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9558 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9559 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9560 faceVertices[fVertex] = origVertices[cVertex]; 9561 break; 9562 } 9563 } 9564 } 9565 found = PETSC_TRUE; 9566 break; 9567 } 9568 } 9569 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9570 if (posOriented) *posOriented = PETSC_TRUE; 9571 PetscFunctionReturn(0); 9572 } else if (cellDim == 3 && numCorners == 10) { 9573 /* Quadratic tet */ 9574 /* Faces are determined by the first 3 vertices (corners of faces) */ 9575 const PetscInt faceSizeTet = 6; 9576 PetscInt sortedIndices[6], i, iFace; 9577 PetscBool found = PETSC_FALSE; 9578 PetscInt faceVerticesTetSorted[24] = { 9579 0, 1, 2, 6, 7, 8, /* bottom */ 9580 0, 3, 4, 6, 7, 9, /* front */ 9581 1, 4, 5, 7, 8, 9, /* right */ 9582 2, 3, 5, 6, 8, 9, /* left */ 9583 }; 9584 PetscInt faceVerticesTet[24] = { 9585 0, 1, 2, 6, 7, 8, /* bottom */ 9586 0, 4, 3, 6, 7, 9, /* front */ 9587 1, 5, 4, 7, 8, 9, /* right */ 9588 2, 3, 5, 8, 6, 9, /* left */ 9589 }; 9590 9591 faceSize = faceSizeTet; 9592 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9593 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9594 for (iFace=0; iFace < 4; ++iFace) { 9595 const PetscInt ii = iFace*faceSizeTet; 9596 PetscInt fVertex, cVertex; 9597 9598 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9599 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9600 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9601 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9602 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9603 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9604 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9605 faceVertices[fVertex] = origVertices[cVertex]; 9606 break; 9607 } 9608 } 9609 } 9610 found = PETSC_TRUE; 9611 break; 9612 } 9613 } 9614 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9615 if (posOriented) *posOriented = PETSC_TRUE; 9616 PetscFunctionReturn(0); 9617 } else if (cellDim == 3 && numCorners == 27) { 9618 /* Quadratic hexes (I hate this) 9619 A hex is two oriented quads with the normal of the first 9620 pointing up at the second. 9621 9622 7---6 9623 /| /| 9624 4---5 | 9625 | 3-|-2 9626 |/ |/ 9627 0---1 9628 9629 Faces are determined by the first 4 vertices (corners of faces) */ 9630 const PetscInt faceSizeQuadHex = 9; 9631 PetscInt sortedIndices[9], i, iFace; 9632 PetscBool found = PETSC_FALSE; 9633 PetscInt faceVerticesQuadHexSorted[54] = { 9634 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9635 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9636 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9637 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9638 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9639 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9640 }; 9641 PetscInt faceVerticesQuadHex[54] = { 9642 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9643 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9644 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9645 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9646 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9647 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9648 }; 9649 9650 faceSize = faceSizeQuadHex; 9651 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9652 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9653 for (iFace = 0; iFace < 6; ++iFace) { 9654 const PetscInt ii = iFace*faceSizeQuadHex; 9655 PetscInt fVertex, cVertex; 9656 9657 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9658 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9659 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9660 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9661 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9662 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9663 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9664 faceVertices[fVertex] = origVertices[cVertex]; 9665 break; 9666 } 9667 } 9668 } 9669 found = PETSC_TRUE; 9670 break; 9671 } 9672 } 9673 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9674 if (posOriented) *posOriented = PETSC_TRUE; 9675 PetscFunctionReturn(0); 9676 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9677 if (!posOrient) { 9678 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9679 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize-1 - f]; 9680 } else { 9681 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9682 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f]; 9683 } 9684 if (posOriented) *posOriented = posOrient; 9685 PetscFunctionReturn(0); 9686 } 9687 9688 #undef __FUNCT__ 9689 #define __FUNCT__ "DMPlexGetOrientedFace" 9690 /* 9691 Given a cell and a face, as a set of vertices, 9692 return the oriented face, as a set of vertices, in faceVertices 9693 The orientation is such that the face normal points out of the cell 9694 */ 9695 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9696 { 9697 const PetscInt *cone = PETSC_NULL; 9698 PetscInt coneSize, v, f, v2; 9699 PetscInt oppositeVertex = -1; 9700 PetscErrorCode ierr; 9701 9702 PetscFunctionBegin; 9703 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9704 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9705 for (v = 0, v2 = 0; v < coneSize; ++v) { 9706 PetscBool found = PETSC_FALSE; 9707 9708 for (f = 0; f < faceSize; ++f) { 9709 if (face[f] == cone[v]) { 9710 found = PETSC_TRUE; break; 9711 } 9712 } 9713 if (found) { 9714 indices[v2] = v; 9715 origVertices[v2] = cone[v]; 9716 ++v2; 9717 } else { 9718 oppositeVertex = v; 9719 } 9720 } 9721 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9722 PetscFunctionReturn(0); 9723 } 9724 9725 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9726 { 9727 switch (i) { 9728 case 0: 9729 switch (j) { 9730 case 0: return 0; 9731 case 1: 9732 switch (k) { 9733 case 0: return 0; 9734 case 1: return 0; 9735 case 2: return 1; 9736 } 9737 case 2: 9738 switch (k) { 9739 case 0: return 0; 9740 case 1: return -1; 9741 case 2: return 0; 9742 } 9743 } 9744 case 1: 9745 switch (j) { 9746 case 0: 9747 switch (k) { 9748 case 0: return 0; 9749 case 1: return 0; 9750 case 2: return -1; 9751 } 9752 case 1: return 0; 9753 case 2: 9754 switch (k) { 9755 case 0: return 1; 9756 case 1: return 0; 9757 case 2: return 0; 9758 } 9759 } 9760 case 2: 9761 switch (j) { 9762 case 0: 9763 switch (k) { 9764 case 0: return 0; 9765 case 1: return 1; 9766 case 2: return 0; 9767 } 9768 case 1: 9769 switch (k) { 9770 case 0: return -1; 9771 case 1: return 0; 9772 case 2: return 0; 9773 } 9774 case 2: return 0; 9775 } 9776 } 9777 return 0; 9778 } 9779 9780 #undef __FUNCT__ 9781 #define __FUNCT__ "DMPlexCreateRigidBody" 9782 /*@C 9783 DMPlexCreateRigidBody - create rigid body modes from coordinates 9784 9785 Collective on DM 9786 9787 Input Arguments: 9788 + dm - the DM 9789 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9790 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9791 9792 Output Argument: 9793 . sp - the null space 9794 9795 Note: This is necessary to take account of Dirichlet conditions on the displacements 9796 9797 Level: advanced 9798 9799 .seealso: MatNullSpaceCreate() 9800 @*/ 9801 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9802 { 9803 MPI_Comm comm = ((PetscObject) dm)->comm; 9804 Vec coordinates, localMode, mode[6]; 9805 PetscSection coordSection; 9806 PetscScalar *coords; 9807 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9808 PetscErrorCode ierr; 9809 9810 PetscFunctionBegin; 9811 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9812 if (dim == 1) { 9813 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9814 PetscFunctionReturn(0); 9815 } 9816 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9817 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9818 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9819 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9820 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9821 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9822 m = (dim*(dim+1))/2; 9823 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9824 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9825 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9826 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9827 /* Assume P1 */ 9828 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9829 for (d = 0; d < dim; ++d) { 9830 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9831 9832 values[d] = 1.0; 9833 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9834 for (v = vStart; v < vEnd; ++v) { 9835 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9836 } 9837 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9838 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9839 } 9840 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9841 for (d = dim; d < dim*(dim+1)/2; ++d) { 9842 PetscInt i, j, k = dim > 2 ? d - dim : d; 9843 9844 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9845 for (v = vStart; v < vEnd; ++v) { 9846 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9847 PetscInt off; 9848 9849 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9850 for (i = 0; i < dim; ++i) { 9851 for (j = 0; j < dim; ++j) { 9852 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9853 } 9854 } 9855 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9856 } 9857 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9858 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9859 } 9860 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9861 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9862 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9863 /* Orthonormalize system */ 9864 for (i = dim; i < m; ++i) { 9865 PetscScalar dots[6]; 9866 9867 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9868 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9869 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9870 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9871 } 9872 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9873 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9874 PetscFunctionReturn(0); 9875 } 9876 9877 #undef __FUNCT__ 9878 #define __FUNCT__ "DMPlexGetHybridBounds" 9879 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9880 { 9881 DM_Plex *mesh = (DM_Plex*) dm->data; 9882 PetscInt dim; 9883 PetscErrorCode ierr; 9884 9885 PetscFunctionBegin; 9886 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9887 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9888 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9889 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9890 if (eMax) *eMax = mesh->hybridPointMax[1]; 9891 if (vMax) *vMax = mesh->hybridPointMax[0]; 9892 PetscFunctionReturn(0); 9893 } 9894 9895 #undef __FUNCT__ 9896 #define __FUNCT__ "DMPlexSetHybridBounds" 9897 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9898 { 9899 DM_Plex *mesh = (DM_Plex*) dm->data; 9900 PetscInt dim; 9901 PetscErrorCode ierr; 9902 9903 PetscFunctionBegin; 9904 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9905 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9906 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9907 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9908 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9909 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9910 PetscFunctionReturn(0); 9911 } 9912 9913 #undef __FUNCT__ 9914 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9915 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9916 { 9917 DM_Plex *mesh = (DM_Plex*) dm->data; 9918 9919 PetscFunctionBegin; 9920 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9921 PetscValidPointer(cellHeight, 2); 9922 *cellHeight = mesh->vtkCellHeight; 9923 PetscFunctionReturn(0); 9924 } 9925 9926 #undef __FUNCT__ 9927 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9928 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9929 { 9930 DM_Plex *mesh = (DM_Plex*) dm->data; 9931 9932 PetscFunctionBegin; 9933 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9934 mesh->vtkCellHeight = cellHeight; 9935 PetscFunctionReturn(0); 9936 } 9937 9938 #undef __FUNCT__ 9939 #define __FUNCT__ "DMPlexInsertFace_Private" 9940 /* 9941 DMPlexInsertFace_Private - Puts a face into the mesh 9942 9943 Not collective 9944 9945 Input Parameters: 9946 + dm - The DMPlex 9947 . numFaceVertex - The number of vertices in the face 9948 . faceVertices - The vertices in the face for dm 9949 . subfaceVertices - The vertices in the face for subdm 9950 . numCorners - The number of vertices in the cell 9951 . cell - A cell in dm containing the face 9952 . subcell - A cell in subdm containing the face 9953 . firstFace - First face in the mesh 9954 - newFacePoint - Next face in the mesh 9955 9956 Output Parameters: 9957 . newFacePoint - Contains next face point number on input, updated on output 9958 9959 Level: developer 9960 */ 9961 PetscErrorCode DMPlexInsertFace_Private(DM dm, DM subdm, PetscInt numFaceVertices, const PetscInt faceVertices[], const PetscInt subfaceVertices[], PetscInt numCorners, PetscInt cell, PetscInt subcell, PetscInt firstFace, PetscInt *newFacePoint) 9962 { 9963 MPI_Comm comm = ((PetscObject) dm)->comm; 9964 DM_Plex *submesh = (DM_Plex*) subdm->data; 9965 const PetscInt *faces; 9966 PetscInt numFaces, coneSize; 9967 PetscErrorCode ierr; 9968 9969 PetscFunctionBegin; 9970 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9971 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9972 #if 0 9973 /* Cannot use this because support() has not been constructed yet */ 9974 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9975 #else 9976 { 9977 PetscInt f; 9978 9979 numFaces = 0; 9980 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void**) &faces);CHKERRQ(ierr); 9981 for (f = firstFace; f < *newFacePoint; ++f) { 9982 PetscInt dof, off, d; 9983 9984 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9985 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9986 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9987 for (d = 0; d < dof; ++d) { 9988 const PetscInt p = submesh->cones[off+d]; 9989 PetscInt v; 9990 9991 for (v = 0; v < numFaceVertices; ++v) { 9992 if (subfaceVertices[v] == p) break; 9993 } 9994 if (v == numFaceVertices) break; 9995 } 9996 if (d == dof) { 9997 numFaces = 1; 9998 ((PetscInt*) faces)[0] = f; 9999 } 10000 } 10001 } 10002 #endif 10003 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 10004 else if (numFaces == 1) { 10005 /* Add the other cell neighbor for this face */ 10006 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 10007 } else { 10008 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 10009 PetscBool posOriented; 10010 10011 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10012 origVertices = &orientedVertices[numFaceVertices]; 10013 indices = &orientedVertices[numFaceVertices*2]; 10014 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 10015 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 10016 /* TODO: I know that routine should return a permutation, not the indices */ 10017 for (v = 0; v < numFaceVertices; ++v) { 10018 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 10019 for (ov = 0; ov < numFaceVertices; ++ov) { 10020 if (orientedVertices[ov] == vertex) { 10021 orientedSubVertices[ov] = subvertex; 10022 break; 10023 } 10024 } 10025 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 10026 } 10027 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 10028 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 10029 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10030 ++(*newFacePoint); 10031 } 10032 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 10033 PetscFunctionReturn(0); 10034 } 10035 10036 #undef __FUNCT__ 10037 #define __FUNCT__ "DMPlexCreateSubmesh" 10038 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 10039 { 10040 MPI_Comm comm = ((PetscObject) dm)->comm; 10041 DM_Plex *submesh; 10042 PetscBool boundaryFaces = PETSC_FALSE; 10043 PetscSection coordSection, subCoordSection; 10044 Vec coordinates, subCoordinates; 10045 PetscScalar *coords, *subCoords; 10046 IS labelIS; 10047 const PetscInt *subVertices; 10048 PetscInt *subVerticesActive, *tmpPoints; 10049 PetscInt *subCells = PETSC_NULL; 10050 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 10051 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 10052 PetscInt dim; /* Right now, do not specify dimension */ 10053 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 10054 PetscErrorCode ierr; 10055 10056 PetscFunctionBegin; 10057 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10058 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10059 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10060 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 10061 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10062 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 10063 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 10064 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10065 10066 subface = &face[maxConeSize]; 10067 10068 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 10069 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 10070 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 10071 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 10072 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 10073 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 10074 10075 maxSubCells = numSubVertices; 10076 10077 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 10078 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 10079 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 10080 for (v = 0; v < numSubVertices; ++v) { 10081 const PetscInt vertex = subVertices[v]; 10082 PetscInt *star = PETSC_NULL; 10083 PetscInt starSize, numCells = 0; 10084 10085 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10086 for (p = 0; p < starSize*2; p += 2) { 10087 const PetscInt point = star[p]; 10088 if ((point >= cStart) && (point < cEnd)) star[numCells++] = point; 10089 } 10090 numOldSubCells = numSubCells; 10091 for (c = 0; c < numCells; ++c) { 10092 const PetscInt cell = star[c]; 10093 PetscInt *closure = PETSC_NULL; 10094 PetscInt closureSize, numCorners = 0, faceSize = 0; 10095 PetscInt cellLoc; 10096 10097 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 10098 if (cellLoc >= 0) continue; 10099 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10100 for (p = 0; p < closureSize*2; p += 2) { 10101 const PetscInt point = closure[p]; 10102 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 10103 } 10104 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 10105 for (corner = 0; corner < numCorners; ++corner) { 10106 const PetscInt cellVertex = closure[corner]; 10107 PetscInt subVertex; 10108 10109 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 10110 if (subVertex >= 0) { /* contains submesh vertex */ 10111 for (i = 0; i < faceSize; ++i) { 10112 if (cellVertex == face[i]) break; 10113 } 10114 if (i == faceSize) { 10115 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 10116 face[faceSize] = cellVertex; 10117 subface[faceSize] = subVertex; 10118 ++faceSize; 10119 } 10120 } 10121 } 10122 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10123 if (faceSize >= nFV) { 10124 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10125 if (numSubCells >= maxSubCells) { 10126 PetscInt *tmpCells; 10127 maxSubCells *= 2; 10128 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 10129 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 10130 ierr = PetscFree(subCells);CHKERRQ(ierr); 10131 10132 subCells = tmpCells; 10133 } 10134 /* TOOD: Maybe overestimate then squeeze out empty faces */ 10135 if (faceSize > nFV) { 10136 /* TODO: This is tricky. Maybe just add all faces */ 10137 numSubFaces++; 10138 } else { 10139 numSubFaces++; 10140 } 10141 for (f = 0; f < faceSize; ++f) { 10142 subVerticesActive[subface[f]] = 1; 10143 } 10144 subCells[numSubCells++] = cell; 10145 } 10146 } 10147 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10148 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 10149 } 10150 /* Pick out active subvertices */ 10151 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 10152 if (subVerticesActive[v]) { 10153 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 10154 } 10155 } 10156 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 10157 /* Set cone sizes */ 10158 firstSubVertex = numSubCells; 10159 firstSubFace = numSubCells+numSubVerticesActive; 10160 newFacePoint = firstSubFace; 10161 for (c = 0; c < numSubCells; ++c) { 10162 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 10163 } 10164 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 10165 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 10166 } 10167 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 10168 /* Create face cones */ 10169 for (c = 0; c < numSubCells; ++c) { 10170 const PetscInt cell = subCells[c]; 10171 PetscInt *closure = PETSC_NULL; 10172 PetscInt closureSize, numCorners = 0, faceSize = 0; 10173 10174 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10175 for (p = 0; p < closureSize*2; p += 2) { 10176 const PetscInt point = closure[p]; 10177 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 10178 } 10179 for (corner = 0; corner < numCorners; ++corner) { 10180 const PetscInt cellVertex = closure[corner]; 10181 PetscInt subVertex; 10182 10183 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 10184 if (subVertex >= 0) { /* contains submesh vertex */ 10185 for (i = 0; i < faceSize; ++i) { 10186 if (cellVertex == face[i]) break; 10187 } 10188 if (i == faceSize) { 10189 face[faceSize] = cellVertex; 10190 subface[faceSize] = numSubCells+subVertex; 10191 ++faceSize; 10192 } 10193 } 10194 } 10195 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10196 if (faceSize >= nFV) { 10197 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10198 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 10199 /* We have to take all the faces, and discard those in the interior */ 10200 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 10201 #if 0 10202 /* This object just calls insert on each face that comes from subsets() */ 10203 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 10204 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 10205 PointArray faceVec(face->begin(), face->end()); 10206 10207 subsets(faceVec, nFV, inserter); 10208 #endif 10209 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 10210 } 10211 } 10212 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 10213 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 10214 /* Build coordinates */ 10215 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10216 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10217 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 10218 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 10219 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 10220 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 10221 } 10222 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10223 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10224 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 10225 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10226 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10227 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10228 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10229 for (v = 0; v < numSubVerticesActive; ++v) { 10230 const PetscInt vertex = subVerticesActive[v]; 10231 const PetscInt subVertex = firstSubVertex+v; 10232 PetscInt dof, off, sdof, soff; 10233 10234 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10235 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10236 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10237 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10238 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10239 for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d]; 10240 } 10241 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10242 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10243 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 10244 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10245 10246 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 10247 /* Create map from submesh points to original mesh points */ 10248 submesh = (DM_Plex*) (*subdm)->data; 10249 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 10250 for (c = 0; c < numSubCells; ++c) tmpPoints[c] = subCells[c]; 10251 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 10252 tmpPoints[v] = subVerticesActive[v-numSubCells]; 10253 } 10254 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 10255 10256 ierr = PetscFree(subCells);CHKERRQ(ierr); 10257 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10258 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10259 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10260 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10261 PetscFunctionReturn(0); 10262 } 10263 10264 #undef __FUNCT__ 10265 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10266 /* We can easily have a form that takes an IS instead */ 10267 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10268 { 10269 PetscSection section, globalSection; 10270 PetscInt *numbers, p; 10271 PetscErrorCode ierr; 10272 10273 PetscFunctionBegin; 10274 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10275 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10276 for (p = pStart; p < pEnd; ++p) { 10277 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10278 } 10279 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10280 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10281 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10282 for (p = pStart; p < pEnd; ++p) { 10283 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10284 } 10285 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10286 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10287 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10288 PetscFunctionReturn(0); 10289 } 10290 10291 #undef __FUNCT__ 10292 #define __FUNCT__ "DMPlexGetCellNumbering" 10293 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10294 { 10295 DM_Plex *mesh = (DM_Plex*) dm->data; 10296 PetscInt cellHeight, cStart, cEnd, cMax; 10297 PetscErrorCode ierr; 10298 10299 PetscFunctionBegin; 10300 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10301 if (!mesh->globalCellNumbers) { 10302 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10303 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10304 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10305 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 10306 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10307 } 10308 *globalCellNumbers = mesh->globalCellNumbers; 10309 PetscFunctionReturn(0); 10310 } 10311 10312 #undef __FUNCT__ 10313 #define __FUNCT__ "DMPlexGetVertexNumbering" 10314 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10315 { 10316 DM_Plex *mesh = (DM_Plex*) dm->data; 10317 PetscInt vStart, vEnd, vMax; 10318 PetscErrorCode ierr; 10319 10320 PetscFunctionBegin; 10321 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10322 if (!mesh->globalVertexNumbers) { 10323 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10324 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10325 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 10326 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10327 } 10328 *globalVertexNumbers = mesh->globalVertexNumbers; 10329 PetscFunctionReturn(0); 10330 } 10331 10332 #undef __FUNCT__ 10333 #define __FUNCT__ "DMPlexGetSubpointMap" 10334 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 10335 { 10336 DM_Plex *mesh = (DM_Plex*) dm->data; 10337 10338 PetscFunctionBegin; 10339 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10340 PetscValidPointer(subpointMap, 2); 10341 *subpointMap = mesh->subpointMap; 10342 PetscFunctionReturn(0); 10343 } 10344 10345 #undef __FUNCT__ 10346 #define __FUNCT__ "DMPlexSetSubpointMap" 10347 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10348 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 10349 { 10350 DM_Plex *mesh = (DM_Plex*) dm->data; 10351 10352 PetscFunctionBegin; 10353 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10354 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 10355 mesh->subpointMap = subpointMap; 10356 PetscFunctionReturn(0); 10357 } 10358 10359 #undef __FUNCT__ 10360 #define __FUNCT__ "DMPlexGetScale" 10361 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10362 { 10363 DM_Plex *mesh = (DM_Plex*) dm->data; 10364 10365 PetscFunctionBegin; 10366 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10367 PetscValidPointer(scale, 3); 10368 *scale = mesh->scale[unit]; 10369 PetscFunctionReturn(0); 10370 } 10371 10372 #undef __FUNCT__ 10373 #define __FUNCT__ "DMPlexSetScale" 10374 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10375 { 10376 DM_Plex *mesh = (DM_Plex*) dm->data; 10377 10378 PetscFunctionBegin; 10379 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10380 mesh->scale[unit] = scale; 10381 PetscFunctionReturn(0); 10382 } 10383 10384 10385 /******************************************************************************* 10386 This should be in a separate Discretization object, but I am not sure how to lay 10387 it out yet, so I am stuffing things here while I experiment. 10388 *******************************************************************************/ 10389 #undef __FUNCT__ 10390 #define __FUNCT__ "DMPlexSetFEMIntegration" 10391 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10392 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10393 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10394 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10395 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10396 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10397 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10398 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10399 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10400 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10401 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10402 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10403 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10404 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10405 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10406 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10407 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 10408 { 10409 DM_Plex *mesh = (DM_Plex*) dm->data; 10410 10411 PetscFunctionBegin; 10412 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10413 mesh->integrateResidualFEM = integrateResidualFEM; 10414 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10415 mesh->integrateJacobianFEM = integrateJacobianFEM; 10416 PetscFunctionReturn(0); 10417 } 10418 10419 #undef __FUNCT__ 10420 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10421 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10422 { 10423 Vec coordinates; 10424 PetscSection section, cSection; 10425 PetscInt dim, vStart, vEnd, v, c, d; 10426 PetscScalar *values, *cArray; 10427 PetscReal *coords; 10428 PetscErrorCode ierr; 10429 10430 PetscFunctionBegin; 10431 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10432 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10433 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10434 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10435 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10436 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10437 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10438 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10439 for (v = vStart; v < vEnd; ++v) { 10440 PetscInt dof, off; 10441 10442 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10443 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10444 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10445 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 10446 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10447 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10448 } 10449 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10450 /* Temporary, must be replaced by a projection on the finite element basis */ 10451 { 10452 PetscInt eStart = 0, eEnd = 0, e, depth; 10453 10454 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10455 --depth; 10456 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10457 for (e = eStart; e < eEnd; ++e) { 10458 const PetscInt *cone = PETSC_NULL; 10459 PetscInt coneSize, d; 10460 PetscScalar *coordsA, *coordsB; 10461 10462 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10463 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10464 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10465 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10466 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10467 for (d = 0; d < dim; ++d) { 10468 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10469 } 10470 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10471 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10472 } 10473 } 10474 10475 ierr = PetscFree(coords);CHKERRQ(ierr); 10476 ierr = PetscFree(values);CHKERRQ(ierr); 10477 #if 0 10478 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10479 PetscReal detJ; 10480 10481 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10482 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10483 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10484 10485 for (PetscInt c = cStart; c < cEnd; ++c) { 10486 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10487 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10488 const int oSize = pV.getSize(); 10489 int v = 0; 10490 10491 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10492 for (PetscInt cl = 0; cl < oSize; ++cl) { 10493 const PetscInt fDim; 10494 10495 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10496 if (pointDim) { 10497 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10498 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10499 } 10500 } 10501 } 10502 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10503 pV.clear(); 10504 } 10505 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10506 ierr = PetscFree(values);CHKERRQ(ierr); 10507 #endif 10508 PetscFunctionReturn(0); 10509 } 10510 10511 #undef __FUNCT__ 10512 #define __FUNCT__ "DMPlexProjectFunction" 10513 /*@C 10514 DMPlexProjectFunction - This projects the given function into the function space provided. 10515 10516 Input Parameters: 10517 + dm - The DM 10518 . numComp - The number of components (functions) 10519 . funcs - The coordinate functions to evaluate 10520 - mode - The insertion mode for values 10521 10522 Output Parameter: 10523 . X - vector 10524 10525 Level: developer 10526 10527 Note: 10528 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10529 We will eventually fix it. 10530 10531 ,seealso: DMPlexComputeL2Diff() 10532 */ 10533 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10534 { 10535 Vec localX; 10536 PetscErrorCode ierr; 10537 10538 PetscFunctionBegin; 10539 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10540 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10541 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10542 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10543 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10544 PetscFunctionReturn(0); 10545 } 10546 10547 #undef __FUNCT__ 10548 #define __FUNCT__ "DMPlexComputeL2Diff" 10549 /*@C 10550 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10551 10552 Input Parameters: 10553 + dm - The DM 10554 . quad - The PetscQuadrature object for each field 10555 . funcs - The functions to evaluate for each field component 10556 - X - The coefficient vector u_h 10557 10558 Output Parameter: 10559 . diff - The diff ||u - u_h||_2 10560 10561 Level: developer 10562 10563 .seealso: DMPlexProjectFunction() 10564 */ 10565 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10566 { 10567 const PetscInt debug = 0; 10568 PetscSection section; 10569 Vec localX; 10570 PetscReal *coords, *v0, *J, *invJ, detJ; 10571 PetscReal localDiff = 0.0; 10572 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10573 PetscErrorCode ierr; 10574 10575 PetscFunctionBegin; 10576 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10577 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10578 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10579 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10580 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10581 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10582 for (field = 0; field < numFields; ++field) { 10583 numComponents += quad[field].numComponents; 10584 } 10585 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10586 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10587 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10588 for (c = cStart; c < cEnd; ++c) { 10589 const PetscScalar *x; 10590 PetscReal elemDiff = 0.0; 10591 10592 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10593 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10594 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10595 10596 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10597 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10598 const PetscReal *quadPoints = quad[field].quadPoints; 10599 const PetscReal *quadWeights = quad[field].quadWeights; 10600 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10601 const PetscInt numBasisComps = quad[field].numComponents; 10602 const PetscReal *basis = quad[field].basis; 10603 PetscInt q, d, e, fc, f; 10604 10605 if (debug) { 10606 char title[1024]; 10607 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10608 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10609 } 10610 for (q = 0; q < numQuadPoints; ++q) { 10611 for (d = 0; d < dim; d++) { 10612 coords[d] = v0[d]; 10613 for (e = 0; e < dim; e++) { 10614 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10615 } 10616 } 10617 for (fc = 0; fc < numBasisComps; ++fc) { 10618 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10619 PetscReal interpolant = 0.0; 10620 for (f = 0; f < numBasisFuncs; ++f) { 10621 const PetscInt fidx = f*numBasisComps+fc; 10622 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10623 } 10624 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10625 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10626 } 10627 } 10628 comp += numBasisComps; 10629 fieldOffset += numBasisFuncs*numBasisComps; 10630 } 10631 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10632 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10633 localDiff += elemDiff; 10634 } 10635 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10636 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10637 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10638 *diff = PetscSqrtReal(*diff); 10639 PetscFunctionReturn(0); 10640 } 10641 10642 #undef __FUNCT__ 10643 #define __FUNCT__ "DMPlexComputeResidualFEM" 10644 /*@ 10645 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10646 10647 Input Parameters: 10648 + dm - The mesh 10649 . X - Local input vector 10650 - user - The user context 10651 10652 Output Parameter: 10653 . F - Local output vector 10654 10655 Note: 10656 The second member of the user context must be an FEMContext. 10657 10658 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10659 like a GPU, or vectorize on a multicore machine. 10660 10661 .seealso: DMPlexComputeJacobianActionFEM() 10662 */ 10663 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10664 { 10665 DM_Plex *mesh = (DM_Plex*) dm->data; 10666 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10667 PetscQuadrature *quad = fem->quad; 10668 PetscSection section; 10669 PetscReal *v0, *J, *invJ, *detJ; 10670 PetscScalar *elemVec, *u; 10671 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10672 PetscInt cellDof = 0, numComponents = 0; 10673 PetscErrorCode ierr; 10674 10675 PetscFunctionBegin; 10676 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10677 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10678 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10679 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10680 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10681 numCells = cEnd - cStart; 10682 for (field = 0; field < numFields; ++field) { 10683 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10684 numComponents += quad[field].numComponents; 10685 } 10686 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10687 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10688 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); 10689 for (c = cStart; c < cEnd; ++c) { 10690 const PetscScalar *x; 10691 PetscInt i; 10692 10693 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10694 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10695 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10696 10697 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10698 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10699 } 10700 for (field = 0; field < numFields; ++field) { 10701 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10702 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10703 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10704 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10705 /* Conforming batches */ 10706 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10707 PetscInt numBlocks = 1; 10708 PetscInt batchSize = numBlocks * blockSize; 10709 PetscInt numBatches = numBatchesTmp; 10710 PetscInt numChunks = numCells / (numBatches*batchSize); 10711 /* Remainder */ 10712 PetscInt numRemainder = numCells % (numBatches * batchSize); 10713 PetscInt offset = numCells - numRemainder; 10714 10715 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10716 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10717 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10718 } 10719 for (c = cStart; c < cEnd; ++c) { 10720 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10721 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10722 } 10723 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10724 if (mesh->printFEM) { 10725 PetscMPIInt rank, numProcs; 10726 PetscInt p; 10727 10728 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10729 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10730 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10731 for (p = 0; p < numProcs; ++p) { 10732 if (p == rank) { 10733 Vec f; 10734 10735 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10736 ierr = VecCopy(F, f);CHKERRQ(ierr); 10737 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10738 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10739 ierr = VecDestroy(&f);CHKERRQ(ierr); 10740 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10741 } 10742 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10743 } 10744 } 10745 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10746 PetscFunctionReturn(0); 10747 } 10748 10749 #undef __FUNCT__ 10750 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10751 /*@C 10752 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10753 10754 Input Parameters: 10755 + dm - The mesh 10756 . J - The Jacobian shell matrix 10757 . X - Local input vector 10758 - user - The user context 10759 10760 Output Parameter: 10761 . F - Local output vector 10762 10763 Note: 10764 The second member of the user context must be an FEMContext. 10765 10766 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10767 like a GPU, or vectorize on a multicore machine. 10768 10769 .seealso: DMPlexComputeResidualFEM() 10770 */ 10771 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10772 { 10773 DM_Plex *mesh = (DM_Plex*) dm->data; 10774 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10775 PetscQuadrature *quad = fem->quad; 10776 PetscSection section; 10777 JacActionCtx *jctx; 10778 PetscReal *v0, *J, *invJ, *detJ; 10779 PetscScalar *elemVec, *u, *a; 10780 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10781 PetscInt cellDof = 0; 10782 PetscErrorCode ierr; 10783 10784 PetscFunctionBegin; 10785 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10786 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10787 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10788 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10789 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10790 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10791 numCells = cEnd - cStart; 10792 for (field = 0; field < numFields; ++field) { 10793 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10794 } 10795 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10796 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); 10797 for (c = cStart; c < cEnd; ++c) { 10798 const PetscScalar *x; 10799 PetscInt i; 10800 10801 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10802 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10803 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10804 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10805 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10806 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10807 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 10808 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10809 } 10810 for (field = 0; field < numFields; ++field) { 10811 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10812 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10813 /* Conforming batches */ 10814 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10815 PetscInt numBlocks = 1; 10816 PetscInt batchSize = numBlocks * blockSize; 10817 PetscInt numBatches = numBatchesTmp; 10818 PetscInt numChunks = numCells / (numBatches*batchSize); 10819 /* Remainder */ 10820 PetscInt numRemainder = numCells % (numBatches * batchSize); 10821 PetscInt offset = numCells - numRemainder; 10822 10823 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); 10824 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], 10825 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10826 } 10827 for (c = cStart; c < cEnd; ++c) { 10828 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10829 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10830 } 10831 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10832 if (mesh->printFEM) { 10833 PetscMPIInt rank, numProcs; 10834 PetscInt p; 10835 10836 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10837 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10838 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10839 for (p = 0; p < numProcs; ++p) { 10840 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10841 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10842 } 10843 } 10844 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10845 PetscFunctionReturn(0); 10846 } 10847 10848 #undef __FUNCT__ 10849 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10850 /*@ 10851 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10852 10853 Input Parameters: 10854 + dm - The mesh 10855 . X - Local input vector 10856 - user - The user context 10857 10858 Output Parameter: 10859 . Jac - Jacobian matrix 10860 10861 Note: 10862 The second member of the user context must be an FEMContext. 10863 10864 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10865 like a GPU, or vectorize on a multicore machine. 10866 10867 .seealso: FormFunctionLocal() 10868 */ 10869 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10870 { 10871 DM_Plex *mesh = (DM_Plex*) dm->data; 10872 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10873 PetscQuadrature *quad = fem->quad; 10874 PetscSection section; 10875 PetscReal *v0, *J, *invJ, *detJ; 10876 PetscScalar *elemMat, *u; 10877 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10878 PetscInt cellDof = 0, numComponents = 0; 10879 PetscBool isShell; 10880 PetscErrorCode ierr; 10881 10882 PetscFunctionBegin; 10883 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10884 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10885 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10886 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10887 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10888 numCells = cEnd - cStart; 10889 for (field = 0; field < numFields; ++field) { 10890 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10891 numComponents += quad[field].numComponents; 10892 } 10893 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10894 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10895 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); 10896 for (c = cStart; c < cEnd; ++c) { 10897 const PetscScalar *x; 10898 PetscInt i; 10899 10900 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10901 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10902 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10903 10904 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10905 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10906 } 10907 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10908 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10909 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10910 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10911 PetscInt fieldJ; 10912 10913 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10914 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10915 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10916 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10917 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10918 /* Conforming batches */ 10919 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10920 PetscInt numBlocks = 1; 10921 PetscInt batchSize = numBlocks * blockSize; 10922 PetscInt numBatches = numBatchesTmp; 10923 PetscInt numChunks = numCells / (numBatches*batchSize); 10924 /* Remainder */ 10925 PetscInt numRemainder = numCells % (numBatches * batchSize); 10926 PetscInt offset = numCells - numRemainder; 10927 10928 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10929 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10930 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10931 } 10932 } 10933 for (c = cStart; c < cEnd; ++c) { 10934 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10935 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10936 } 10937 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10938 10939 /* Assemble matrix, using the 2-step process: 10940 MatAssemblyBegin(), MatAssemblyEnd(). */ 10941 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10942 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10943 10944 if (mesh->printFEM) { 10945 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10946 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10947 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10948 } 10949 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10950 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10951 if (isShell) { 10952 JacActionCtx *jctx; 10953 10954 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10955 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10956 } 10957 *str = SAME_NONZERO_PATTERN; 10958 PetscFunctionReturn(0); 10959 } 10960 10961 10962 #undef __FUNCT__ 10963 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10964 /*@C 10965 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10966 the local section and an SF describing the section point overlap. 10967 10968 Input Parameters: 10969 + s - The PetscSection for the local field layout 10970 . sf - The SF describing parallel layout of the section points 10971 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10972 . label - The label specifying the points 10973 - labelValue - The label stratum specifying the points 10974 10975 Output Parameter: 10976 . gsection - The PetscSection for the global field layout 10977 10978 Note: This gives negative sizes and offsets to points not owned by this process 10979 10980 Level: developer 10981 10982 .seealso: PetscSectionCreate() 10983 @*/ 10984 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10985 { 10986 PetscInt *neg; 10987 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10988 PetscErrorCode ierr; 10989 10990 PetscFunctionBegin; 10991 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10992 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10993 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10994 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10995 /* Mark ghost points with negative dof */ 10996 for (p = pStart; p < pEnd; ++p) { 10997 PetscInt value; 10998 10999 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 11000 if (value != labelValue) continue; 11001 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 11002 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 11003 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 11004 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 11005 neg[p-pStart] = -(dof+1); 11006 } 11007 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 11008 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 11009 if (nroots >= 0) { 11010 if (nroots > pEnd - pStart) { 11011 PetscInt *tmpDof; 11012 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11013 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 11014 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11015 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11016 for (p = pStart; p < pEnd; ++p) { 11017 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 11018 } 11019 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 11020 } else { 11021 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11022 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11023 } 11024 } 11025 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 11026 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11027 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 11028 11029 (*gsection)->atlasOff[p] = off; 11030 11031 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 11032 } 11033 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 11034 globalOff -= off; 11035 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11036 (*gsection)->atlasOff[p] += globalOff; 11037 11038 neg[p] = -((*gsection)->atlasOff[p]+1); 11039 } 11040 /* Put in negative offsets for ghost points */ 11041 if (nroots >= 0) { 11042 if (nroots > pEnd - pStart) { 11043 PetscInt *tmpOff; 11044 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11045 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 11046 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11047 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11048 for (p = pStart; p < pEnd; ++p) { 11049 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 11050 } 11051 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 11052 } else { 11053 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11054 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11055 } 11056 } 11057 ierr = PetscFree(neg);CHKERRQ(ierr); 11058 PetscFunctionReturn(0); 11059 } 11060