1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex*) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 167 if (size > 1) { 168 PetscSF sf; 169 170 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 171 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 172 } 173 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 174 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 175 const char *name; 176 const char *colors[3] = {"red", "blue", "green"}; 177 const int numColors = 3; 178 PetscReal scale = 2.0; 179 PetscScalar *coords; 180 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 181 PetscMPIInt rank, size; 182 183 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 184 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 185 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 186 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 187 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 188 ierr = PetscViewerASCIIPrintf(viewer, "\ 189 \\documentclass[crop,multi=false]{standalone}\n\n\ 190 \\usepackage{tikz}\n\ 191 \\usepackage{pgflibraryshapes}\n\ 192 \\usetikzlibrary{backgrounds}\n\ 193 \\usetikzlibrary{arrows}\n\ 194 \\begin{document}\n\ 195 \\section{%s}\n\ 196 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 197 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 198 for (p = 0; p < size; ++p) { 199 if (p > 0 && p == size-1) { 200 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 201 } else if (p > 0) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 203 } 204 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 207 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 208 /* Plot vertices */ 209 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 210 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 211 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 212 for (v = vStart; v < vEnd; ++v) { 213 PetscInt off, dof, d; 214 215 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 216 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 217 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 218 for (d = 0; d < dof; ++d) { 219 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 220 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 221 } 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 223 } 224 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 225 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 226 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 227 /* Plot edges */ 228 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 229 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 230 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 231 for (e = eStart; e < eEnd; ++e) { 232 const PetscInt *cone; 233 PetscInt coneSize, offA, offB, dof, d; 234 235 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 236 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 237 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 238 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 239 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 240 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 241 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 242 for (d = 0; d < dof; ++d) { 243 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 244 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 245 } 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 247 } 248 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 249 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 250 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 251 /* Plot cells */ 252 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 253 for (c = cStart; c < cEnd; ++c) { 254 PetscInt *closure = PETSC_NULL; 255 PetscInt closureSize, firstPoint = -1; 256 257 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 258 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 259 for (p = 0; p < closureSize*2; p += 2) { 260 const PetscInt point = closure[p]; 261 262 if ((point < vStart) || (point >= vEnd)) continue; 263 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 264 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 265 if (firstPoint < 0) firstPoint = point; 266 } 267 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 268 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 269 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 270 } 271 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 272 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 273 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 274 } else { 275 MPI_Comm comm = ((PetscObject) dm)->comm; 276 PetscInt *sizes; 277 PetscInt locDepth, depth, dim, d; 278 PetscInt pStart, pEnd, p; 279 PetscMPIInt size; 280 281 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 282 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 283 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 284 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 285 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 286 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 287 if (depth == 1) { 288 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 289 pEnd = pEnd - pStart; 290 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 291 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 292 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 293 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 294 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 295 pEnd = pEnd - pStart; 296 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 297 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 298 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 299 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 300 } else { 301 for (d = 0; d <= dim; d++) { 302 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 303 pEnd = pEnd - pStart; 304 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 305 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 306 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 307 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 308 } 309 } 310 ierr = PetscFree(sizes);CHKERRQ(ierr); 311 } 312 PetscFunctionReturn(0); 313 } 314 315 #undef __FUNCT__ 316 #define __FUNCT__ "DMView_Plex" 317 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 318 { 319 PetscBool iascii, isbinary; 320 PetscErrorCode ierr; 321 322 PetscFunctionBegin; 323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 324 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 325 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 326 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 327 if (iascii) { 328 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 329 #if 0 330 } else if (isbinary) { 331 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 332 #endif 333 } 334 PetscFunctionReturn(0); 335 } 336 337 #undef __FUNCT__ 338 #define __FUNCT__ "DMDestroy_Plex" 339 PetscErrorCode DMDestroy_Plex(DM dm) 340 { 341 DM_Plex *mesh = (DM_Plex*) dm->data; 342 DMLabel next = mesh->labels; 343 PetscErrorCode ierr; 344 345 PetscFunctionBegin; 346 if (--mesh->refct > 0) PetscFunctionReturn(0); 347 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 348 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 349 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 350 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 353 while (next) { 354 DMLabel tmp = next->next; 355 356 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 357 next = tmp; 358 } 359 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 360 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 361 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 362 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 363 ierr = PetscFree(mesh);CHKERRQ(ierr); 364 PetscFunctionReturn(0); 365 } 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 369 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 370 { 371 const PetscInt *support = PETSC_NULL; 372 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 373 PetscErrorCode ierr; 374 375 PetscFunctionBegin; 376 if (useClosure) { 377 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 378 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 379 for (s = 0; s < supportSize; ++s) { 380 const PetscInt *cone = PETSC_NULL; 381 PetscInt coneSize, c, q; 382 383 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 384 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 385 for (c = 0; c < coneSize; ++c) { 386 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 387 if (cone[c] == adj[q]) break; 388 } 389 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 390 } 391 } 392 } else { 393 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 394 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 395 for (s = 0; s < supportSize; ++s) { 396 const PetscInt *cone = PETSC_NULL; 397 PetscInt coneSize, c, q; 398 399 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 400 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 401 for (c = 0; c < coneSize; ++c) { 402 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 403 if (cone[c] == adj[q]) break; 404 } 405 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 406 } 407 } 408 } 409 *adjSize = numAdj; 410 PetscFunctionReturn(0); 411 } 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "DMPlexGetAdjacency_Private" 415 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 416 { 417 const PetscInt *star = tmpClosure; 418 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 419 PetscErrorCode ierr; 420 421 PetscFunctionBegin; 422 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 423 for (s = 2; s < starSize*2; s += 2) { 424 const PetscInt *closure = PETSC_NULL; 425 PetscInt closureSize, c, q; 426 427 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 428 for (c = 0; c < closureSize*2; c += 2) { 429 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 430 if (closure[c] == adj[q]) break; 431 } 432 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 433 } 434 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 435 } 436 *adjSize = numAdj; 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNCT__ 441 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 442 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 443 { 444 DM_Plex *mesh = (DM_Plex*) dm->data; 445 446 PetscFunctionBegin; 447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 448 mesh->preallocCenterDim = preallocCenterDim; 449 PetscFunctionReturn(0); 450 } 451 452 #undef __FUNCT__ 453 #define __FUNCT__ "DMPlexPreallocateOperator" 454 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 455 { 456 DM_Plex *mesh = (DM_Plex*) dm->data; 457 MPI_Comm comm = ((PetscObject) dm)->comm; 458 PetscSF sf, sfDof, sfAdj; 459 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 460 PetscInt nleaves, l, p; 461 const PetscInt *leaves; 462 const PetscSFNode *remotes; 463 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 464 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 465 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 466 PetscLayout rLayout; 467 PetscInt locRows, rStart, rEnd, r; 468 PetscMPIInt size; 469 PetscBool useClosure, debug = PETSC_FALSE; 470 PetscErrorCode ierr; 471 472 PetscFunctionBegin; 473 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 474 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 475 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 476 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 477 /* Create dof SF based on point SF */ 478 if (debug) { 479 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 480 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 481 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 485 } 486 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 487 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 488 if (debug) { 489 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 490 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 491 } 492 /* Create section for dof adjacency (dof ==> # adj dof) */ 493 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 494 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 495 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 496 if (mesh->preallocCenterDim == dim) { 497 useClosure = PETSC_FALSE; 498 } else if (mesh->preallocCenterDim == 0) { 499 useClosure = PETSC_TRUE; 500 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 501 502 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 503 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 504 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 505 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 508 /* Fill in the ghost dofs on the interface */ 509 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 510 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 511 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 512 513 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 514 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 515 516 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 517 518 /* 519 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 520 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 521 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 522 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 523 Create sfAdj connecting rootSectionAdj and leafSectionAdj 524 3. Visit unowned points on interface, write adjacencies to adj 525 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 526 4. Visit owned points on interface, write adjacencies to rootAdj 527 Remove redundancy in rootAdj 528 ** The last two traversals use transitive closure 529 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 530 Allocate memory addressed by sectionAdj (cols) 531 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 532 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 533 */ 534 535 for (l = 0; l < nleaves; ++l) { 536 PetscInt dof, off, d, q; 537 PetscInt p = leaves[l], numAdj = maxAdjSize; 538 539 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 540 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 541 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 542 for (q = 0; q < numAdj; ++q) { 543 PetscInt ndof, ncdof; 544 545 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 546 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 547 for (d = off; d < off+dof; ++d) { 548 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 549 } 550 } 551 } 552 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 553 if (debug) { 554 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 555 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 556 } 557 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 558 if (size > 1) { 559 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 560 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 561 } 562 if (debug) { 563 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 564 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 565 } 566 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 567 for (p = pStart; p < pEnd; ++p) { 568 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 569 570 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 571 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 572 if (!dof) continue; 573 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 574 if (adof <= 0) continue; 575 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 576 for (q = 0; q < numAdj; ++q) { 577 PetscInt ndof, ncdof; 578 579 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 580 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 581 for (d = off; d < off+dof; ++d) { 582 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 583 } 584 } 585 } 586 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 587 if (debug) { 588 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 589 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 590 } 591 /* Create adj SF based on dof SF */ 592 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 593 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 594 if (debug) { 595 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 596 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 597 } 598 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 599 /* Create leaf adjacency */ 600 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 601 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 602 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 603 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 604 for (l = 0; l < nleaves; ++l) { 605 PetscInt dof, off, d, q; 606 PetscInt p = leaves[l], numAdj = maxAdjSize; 607 608 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 609 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 610 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 611 for (d = off; d < off+dof; ++d) { 612 PetscInt aoff, i = 0; 613 614 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 615 for (q = 0; q < numAdj; ++q) { 616 PetscInt ndof, ncdof, ngoff, nd; 617 618 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 619 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 621 for (nd = 0; nd < ndof-ncdof; ++nd) { 622 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 623 ++i; 624 } 625 } 626 } 627 } 628 /* Debugging */ 629 if (debug) { 630 IS tmp; 631 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 632 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 633 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 634 } 635 /* Gather adjacenct indices to root */ 636 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 637 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 638 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 639 if (size > 1) { 640 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 641 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 642 } 643 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 644 ierr = PetscFree(adj);CHKERRQ(ierr); 645 /* Debugging */ 646 if (debug) { 647 IS tmp; 648 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 649 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 650 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 651 } 652 /* Add in local adjacency indices for owned dofs on interface (roots) */ 653 for (p = pStart; p < pEnd; ++p) { 654 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 655 656 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 657 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 658 if (!dof) continue; 659 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 660 if (adof <= 0) continue; 661 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 662 for (d = off; d < off+dof; ++d) { 663 PetscInt adof, aoff, i; 664 665 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 666 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 667 i = adof-1; 668 for (q = 0; q < numAdj; ++q) { 669 PetscInt ndof, ncdof, ngoff, nd; 670 671 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 672 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 673 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 674 for (nd = 0; nd < ndof-ncdof; ++nd) { 675 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 676 --i; 677 } 678 } 679 } 680 } 681 /* Debugging */ 682 if (debug) { 683 IS tmp; 684 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 685 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 686 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 687 } 688 /* Compress indices */ 689 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 690 for (p = pStart; p < pEnd; ++p) { 691 PetscInt dof, cdof, off, d; 692 PetscInt adof, aoff; 693 694 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 695 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 696 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 697 if (!dof) continue; 698 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 699 if (adof <= 0) continue; 700 for (d = off; d < off+dof-cdof; ++d) { 701 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 702 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 703 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 704 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 705 } 706 } 707 /* Debugging */ 708 if (debug) { 709 IS tmp; 710 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 711 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 712 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 713 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 714 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 715 } 716 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 717 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 718 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 719 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 720 for (p = pStart; p < pEnd; ++p) { 721 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 722 PetscBool found = PETSC_TRUE; 723 724 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 725 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 727 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 728 for (d = 0; d < dof-cdof; ++d) { 729 PetscInt ldof, rdof; 730 731 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 732 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 733 if (ldof > 0) { 734 /* We do not own this point */ 735 } else if (rdof > 0) { 736 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 737 } else { 738 found = PETSC_FALSE; 739 } 740 } 741 if (found) continue; 742 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 743 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 744 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 745 for (q = 0; q < numAdj; ++q) { 746 PetscInt ndof, ncdof, noff; 747 748 /* Adjacent points may not be in the section chart */ 749 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 750 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 751 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 752 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 753 for (d = goff; d < goff+dof-cdof; ++d) { 754 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 755 } 756 } 757 } 758 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 759 if (debug) { 760 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 761 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 762 } 763 /* Get adjacent indices */ 764 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 765 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 768 PetscBool found = PETSC_TRUE; 769 770 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 771 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 772 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 773 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 774 for (d = 0; d < dof-cdof; ++d) { 775 PetscInt ldof, rdof; 776 777 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 778 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 779 if (ldof > 0) { 780 /* We do not own this point */ 781 } else if (rdof > 0) { 782 PetscInt aoff, roff; 783 784 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 786 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 787 } else { 788 found = PETSC_FALSE; 789 } 790 } 791 if (found) continue; 792 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 793 for (d = goff; d < goff+dof-cdof; ++d) { 794 PetscInt adof, aoff, i = 0; 795 796 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 797 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 798 for (q = 0; q < numAdj; ++q) { 799 PetscInt ndof, ncdof, ngoff, nd; 800 const PetscInt *ncind; 801 802 /* Adjacent points may not be in the section chart */ 803 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 804 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 805 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 806 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 807 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 808 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 809 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 810 } 811 } 812 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 813 } 814 } 815 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 816 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 817 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 818 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 819 /* Debugging */ 820 if (debug) { 821 IS tmp; 822 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 823 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 824 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 825 } 826 /* Create allocation vectors from adjacency graph */ 827 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 828 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 829 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 830 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 831 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 832 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 833 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 834 /* Only loop over blocks of rows */ 835 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 836 for (r = rStart/bs; r < rEnd/bs; ++r) { 837 const PetscInt row = r*bs; 838 PetscInt numCols, cStart, c; 839 840 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 841 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 842 for (c = cStart; c < cStart+numCols; ++c) { 843 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 844 ++dnz[r-rStart]; 845 if (cols[c] >= row) ++dnzu[r-rStart]; 846 } else { 847 ++onz[r-rStart]; 848 if (cols[c] >= row) ++onzu[r-rStart]; 849 } 850 } 851 } 852 if (bs > 1) { 853 for (r = 0; r < locRows/bs; ++r) { 854 dnz[r] /= bs; 855 onz[r] /= bs; 856 dnzu[r] /= bs; 857 onzu[r] /= bs; 858 } 859 } 860 /* Set matrix pattern */ 861 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 862 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 863 /* Fill matrix with zeros */ 864 if (fillMatrix) { 865 PetscScalar *values; 866 PetscInt maxRowLen = 0; 867 868 for (r = rStart; r < rEnd; ++r) { 869 PetscInt len; 870 871 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 872 maxRowLen = PetscMax(maxRowLen, len); 873 } 874 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 875 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 876 for (r = rStart; r < rEnd; ++r) { 877 PetscInt numCols, cStart; 878 879 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 880 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 881 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 882 } 883 ierr = PetscFree(values);CHKERRQ(ierr); 884 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 885 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 886 } 887 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 888 ierr = PetscFree(cols);CHKERRQ(ierr); 889 PetscFunctionReturn(0); 890 } 891 892 #if 0 893 #undef __FUNCT__ 894 #define __FUNCT__ "DMPlexPreallocateOperator_2" 895 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 896 { 897 PetscInt *tmpClosure,*tmpAdj,*visits; 898 PetscInt c,cStart,cEnd,pStart,pEnd; 899 PetscErrorCode ierr; 900 901 PetscFunctionBegin; 902 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 903 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 904 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 905 906 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 907 908 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 909 npoints = pEnd - pStart; 910 911 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 912 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 913 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 914 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 915 for (c=cStart; c<cEnd; c++) { 916 PetscInt *support = tmpClosure; 917 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 918 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 919 } 920 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 921 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 922 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 923 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 924 925 ierr = PetscSFGetRanks();CHKERRQ(ierr); 926 927 928 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 929 for (c=cStart; c<cEnd; c++) { 930 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 931 /* 932 Depth-first walk of transitive closure. 933 At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 934 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 935 */ 936 } 937 938 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 939 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 940 PetscFunctionReturn(0); 941 } 942 #endif 943 944 #undef __FUNCT__ 945 #define __FUNCT__ "DMCreateMatrix_Plex" 946 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 947 { 948 PetscSection section, sectionGlobal; 949 PetscInt bs = -1; 950 PetscInt localSize; 951 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 952 PetscErrorCode ierr; 953 954 PetscFunctionBegin; 955 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 956 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 957 #endif 958 if (!mtype) mtype = MATAIJ; 959 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 960 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 961 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 962 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 963 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 964 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 965 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 966 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 967 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 974 /* Check for symmetric storage */ 975 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 976 if (isSymmetric) { 977 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 978 } 979 if (!isShell) { 980 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 981 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 982 983 if (bs < 0) { 984 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 985 PetscInt pStart, pEnd, p, dof, cdof; 986 987 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 988 for (p = pStart; p < pEnd; ++p) { 989 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 990 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 991 if (dof-cdof) { 992 if (bs < 0) { 993 bs = dof-cdof; 994 } else if (bs != dof-cdof) { 995 /* Layout does not admit a pointwise block size */ 996 bs = 1; 997 break; 998 } 999 } 1000 } 1001 /* Must have same blocksize on all procs (some might have no points) */ 1002 bsLocal = bs; 1003 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1004 bsLocal = bs < 0 ? bsMax : bs; 1005 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1006 if (bsMin != bsMax) { 1007 bs = 1; 1008 } else { 1009 bs = bsMax; 1010 } 1011 } else { 1012 bs = 1; 1013 } 1014 } 1015 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1016 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1017 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1018 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1019 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1020 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1021 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1022 } 1023 PetscFunctionReturn(0); 1024 } 1025 1026 #undef __FUNCT__ 1027 #define __FUNCT__ "DMPlexGetDimension" 1028 /*@ 1029 DMPlexGetDimension - Return the topological mesh dimension 1030 1031 Not collective 1032 1033 Input Parameter: 1034 . mesh - The DMPlex 1035 1036 Output Parameter: 1037 . dim - The topological mesh dimension 1038 1039 Level: beginner 1040 1041 .seealso: DMPlexCreate() 1042 @*/ 1043 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1044 { 1045 DM_Plex *mesh = (DM_Plex*) dm->data; 1046 1047 PetscFunctionBegin; 1048 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1049 PetscValidPointer(dim, 2); 1050 *dim = mesh->dim; 1051 PetscFunctionReturn(0); 1052 } 1053 1054 #undef __FUNCT__ 1055 #define __FUNCT__ "DMPlexSetDimension" 1056 /*@ 1057 DMPlexSetDimension - Set the topological mesh dimension 1058 1059 Collective on mesh 1060 1061 Input Parameters: 1062 + mesh - The DMPlex 1063 - dim - The topological mesh dimension 1064 1065 Level: beginner 1066 1067 .seealso: DMPlexCreate() 1068 @*/ 1069 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1070 { 1071 DM_Plex *mesh = (DM_Plex*) dm->data; 1072 1073 PetscFunctionBegin; 1074 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1075 PetscValidLogicalCollectiveInt(dm, dim, 2); 1076 mesh->dim = dim; 1077 mesh->preallocCenterDim = dim; 1078 PetscFunctionReturn(0); 1079 } 1080 1081 #undef __FUNCT__ 1082 #define __FUNCT__ "DMPlexGetChart" 1083 /*@ 1084 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1085 1086 Not collective 1087 1088 Input Parameter: 1089 . mesh - The DMPlex 1090 1091 Output Parameters: 1092 + pStart - The first mesh point 1093 - pEnd - The upper bound for mesh points 1094 1095 Level: beginner 1096 1097 .seealso: DMPlexCreate(), DMPlexSetChart() 1098 @*/ 1099 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1100 { 1101 DM_Plex *mesh = (DM_Plex*) dm->data; 1102 PetscErrorCode ierr; 1103 1104 PetscFunctionBegin; 1105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1106 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1107 PetscFunctionReturn(0); 1108 } 1109 1110 #undef __FUNCT__ 1111 #define __FUNCT__ "DMPlexSetChart" 1112 /*@ 1113 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1114 1115 Not collective 1116 1117 Input Parameters: 1118 + mesh - The DMPlex 1119 . pStart - The first mesh point 1120 - pEnd - The upper bound for mesh points 1121 1122 Output Parameters: 1123 1124 Level: beginner 1125 1126 .seealso: DMPlexCreate(), DMPlexGetChart() 1127 @*/ 1128 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1129 { 1130 DM_Plex *mesh = (DM_Plex*) dm->data; 1131 PetscErrorCode ierr; 1132 1133 PetscFunctionBegin; 1134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1135 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1136 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1137 PetscFunctionReturn(0); 1138 } 1139 1140 #undef __FUNCT__ 1141 #define __FUNCT__ "DMPlexGetConeSize" 1142 /*@ 1143 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1144 1145 Not collective 1146 1147 Input Parameters: 1148 + mesh - The DMPlex 1149 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1150 1151 Output Parameter: 1152 . size - The cone size for point p 1153 1154 Level: beginner 1155 1156 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1157 @*/ 1158 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1159 { 1160 DM_Plex *mesh = (DM_Plex*) dm->data; 1161 PetscErrorCode ierr; 1162 1163 PetscFunctionBegin; 1164 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1165 PetscValidPointer(size, 3); 1166 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1167 PetscFunctionReturn(0); 1168 } 1169 1170 #undef __FUNCT__ 1171 #define __FUNCT__ "DMPlexSetConeSize" 1172 /*@ 1173 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1174 1175 Not collective 1176 1177 Input Parameters: 1178 + mesh - The DMPlex 1179 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1180 - size - The cone size for point p 1181 1182 Output Parameter: 1183 1184 Note: 1185 This should be called after DMPlexSetChart(). 1186 1187 Level: beginner 1188 1189 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1190 @*/ 1191 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1192 { 1193 DM_Plex *mesh = (DM_Plex*) dm->data; 1194 PetscErrorCode ierr; 1195 1196 PetscFunctionBegin; 1197 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1198 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1199 1200 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1201 PetscFunctionReturn(0); 1202 } 1203 1204 #undef __FUNCT__ 1205 #define __FUNCT__ "DMPlexGetCone" 1206 /*@C 1207 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1208 1209 Not collective 1210 1211 Input Parameters: 1212 + mesh - The DMPlex 1213 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1214 1215 Output Parameter: 1216 . cone - An array of points which are on the in-edges for point p 1217 1218 Level: beginner 1219 1220 Note: 1221 This routine is not available in Fortran. 1222 1223 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1224 @*/ 1225 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1226 { 1227 DM_Plex *mesh = (DM_Plex*) dm->data; 1228 PetscInt off; 1229 PetscErrorCode ierr; 1230 1231 PetscFunctionBegin; 1232 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1233 PetscValidPointer(cone, 3); 1234 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1235 *cone = &mesh->cones[off]; 1236 PetscFunctionReturn(0); 1237 } 1238 1239 #undef __FUNCT__ 1240 #define __FUNCT__ "DMPlexSetCone" 1241 /*@ 1242 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1243 1244 Not collective 1245 1246 Input Parameters: 1247 + mesh - The DMPlex 1248 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1249 - cone - An array of points which are on the in-edges for point p 1250 1251 Output Parameter: 1252 1253 Note: 1254 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1255 1256 Level: beginner 1257 1258 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1259 @*/ 1260 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1261 { 1262 DM_Plex *mesh = (DM_Plex*) dm->data; 1263 PetscInt pStart, pEnd; 1264 PetscInt dof, off, c; 1265 PetscErrorCode ierr; 1266 1267 PetscFunctionBegin; 1268 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1269 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1270 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1271 if (dof) PetscValidPointer(cone, 3); 1272 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1273 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1274 for (c = 0; c < dof; ++c) { 1275 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1276 mesh->cones[off+c] = cone[c]; 1277 } 1278 PetscFunctionReturn(0); 1279 } 1280 1281 #undef __FUNCT__ 1282 #define __FUNCT__ "DMPlexGetConeOrientation" 1283 /*@C 1284 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1285 1286 Not collective 1287 1288 Input Parameters: 1289 + mesh - The DMPlex 1290 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1291 1292 Output Parameter: 1293 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1294 integer giving the prescription for cone traversal. If it is negative, the cone is 1295 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1296 the index of the cone point on which to start. 1297 1298 Level: beginner 1299 1300 Note: 1301 This routine is not available in Fortran. 1302 1303 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1304 @*/ 1305 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1306 { 1307 DM_Plex *mesh = (DM_Plex*) dm->data; 1308 PetscInt off; 1309 PetscErrorCode ierr; 1310 1311 PetscFunctionBegin; 1312 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1313 #if defined(PETSC_USE_DEBUG) 1314 { 1315 PetscInt dof; 1316 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1317 if (dof) PetscValidPointer(coneOrientation, 3); 1318 } 1319 #endif 1320 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1321 1322 *coneOrientation = &mesh->coneOrientations[off]; 1323 PetscFunctionReturn(0); 1324 } 1325 1326 #undef __FUNCT__ 1327 #define __FUNCT__ "DMPlexSetConeOrientation" 1328 /*@ 1329 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1330 1331 Not collective 1332 1333 Input Parameters: 1334 + mesh - The DMPlex 1335 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1336 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1337 integer giving the prescription for cone traversal. If it is negative, the cone is 1338 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1339 the index of the cone point on which to start. 1340 1341 Output Parameter: 1342 1343 Note: 1344 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1345 1346 Level: beginner 1347 1348 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1349 @*/ 1350 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1351 { 1352 DM_Plex *mesh = (DM_Plex*) dm->data; 1353 PetscInt pStart, pEnd; 1354 PetscInt dof, off, c; 1355 PetscErrorCode ierr; 1356 1357 PetscFunctionBegin; 1358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1359 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1360 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1361 if (dof) PetscValidPointer(coneOrientation, 3); 1362 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1363 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1364 for (c = 0; c < dof; ++c) { 1365 PetscInt cdof, o = coneOrientation[c]; 1366 1367 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1368 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1369 mesh->coneOrientations[off+c] = o; 1370 } 1371 PetscFunctionReturn(0); 1372 } 1373 1374 #undef __FUNCT__ 1375 #define __FUNCT__ "DMPlexInsertCone" 1376 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1377 { 1378 DM_Plex *mesh = (DM_Plex*) dm->data; 1379 PetscInt pStart, pEnd; 1380 PetscInt dof, off; 1381 PetscErrorCode ierr; 1382 1383 PetscFunctionBegin; 1384 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1385 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1386 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1387 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1388 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1389 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1390 if (conePos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1391 mesh->cones[off+conePos] = conePoint; 1392 PetscFunctionReturn(0); 1393 } 1394 1395 #undef __FUNCT__ 1396 #define __FUNCT__ "DMPlexGetSupportSize" 1397 /*@ 1398 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1399 1400 Not collective 1401 1402 Input Parameters: 1403 + mesh - The DMPlex 1404 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1405 1406 Output Parameter: 1407 . size - The support size for point p 1408 1409 Level: beginner 1410 1411 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1412 @*/ 1413 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1414 { 1415 DM_Plex *mesh = (DM_Plex*) dm->data; 1416 PetscErrorCode ierr; 1417 1418 PetscFunctionBegin; 1419 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1420 PetscValidPointer(size, 3); 1421 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1422 PetscFunctionReturn(0); 1423 } 1424 1425 #undef __FUNCT__ 1426 #define __FUNCT__ "DMPlexSetSupportSize" 1427 /*@ 1428 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1429 1430 Not collective 1431 1432 Input Parameters: 1433 + mesh - The DMPlex 1434 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1435 - size - The support size for point p 1436 1437 Output Parameter: 1438 1439 Note: 1440 This should be called after DMPlexSetChart(). 1441 1442 Level: beginner 1443 1444 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1445 @*/ 1446 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1447 { 1448 DM_Plex *mesh = (DM_Plex*) dm->data; 1449 PetscErrorCode ierr; 1450 1451 PetscFunctionBegin; 1452 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1453 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1454 1455 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1456 PetscFunctionReturn(0); 1457 } 1458 1459 #undef __FUNCT__ 1460 #define __FUNCT__ "DMPlexGetSupport" 1461 /*@C 1462 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1463 1464 Not collective 1465 1466 Input Parameters: 1467 + mesh - The DMPlex 1468 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1469 1470 Output Parameter: 1471 . support - An array of points which are on the out-edges for point p 1472 1473 Level: beginner 1474 1475 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1476 @*/ 1477 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1478 { 1479 DM_Plex *mesh = (DM_Plex*) dm->data; 1480 PetscInt off; 1481 PetscErrorCode ierr; 1482 1483 PetscFunctionBegin; 1484 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1485 PetscValidPointer(support, 3); 1486 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1487 *support = &mesh->supports[off]; 1488 PetscFunctionReturn(0); 1489 } 1490 1491 #undef __FUNCT__ 1492 #define __FUNCT__ "DMPlexSetSupport" 1493 /*@ 1494 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1495 1496 Not collective 1497 1498 Input Parameters: 1499 + mesh - The DMPlex 1500 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1501 - support - An array of points which are on the in-edges for point p 1502 1503 Output Parameter: 1504 1505 Note: 1506 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1507 1508 Level: beginner 1509 1510 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1511 @*/ 1512 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1513 { 1514 DM_Plex *mesh = (DM_Plex*) dm->data; 1515 PetscInt pStart, pEnd; 1516 PetscInt dof, off, c; 1517 PetscErrorCode ierr; 1518 1519 PetscFunctionBegin; 1520 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1521 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1522 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1523 if (dof) PetscValidPointer(support, 3); 1524 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1525 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1526 for (c = 0; c < dof; ++c) { 1527 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1528 mesh->supports[off+c] = support[c]; 1529 } 1530 PetscFunctionReturn(0); 1531 } 1532 1533 #undef __FUNCT__ 1534 #define __FUNCT__ "DMPlexInsertSupport" 1535 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1536 { 1537 DM_Plex *mesh = (DM_Plex*) dm->data; 1538 PetscInt pStart, pEnd; 1539 PetscInt dof, off; 1540 PetscErrorCode ierr; 1541 1542 PetscFunctionBegin; 1543 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1544 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1545 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1546 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1547 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1548 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1549 if (supportPos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1550 mesh->supports[off+supportPos] = supportPoint; 1551 PetscFunctionReturn(0); 1552 } 1553 1554 #undef __FUNCT__ 1555 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1556 /*@C 1557 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1558 1559 Not collective 1560 1561 Input Parameters: 1562 + mesh - The DMPlex 1563 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1564 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1565 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1566 1567 Output Parameters: 1568 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1569 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1570 1571 Note: 1572 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1573 1574 Level: beginner 1575 1576 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1577 @*/ 1578 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1579 { 1580 DM_Plex *mesh = (DM_Plex*) dm->data; 1581 PetscInt *closure, *fifo; 1582 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1583 PetscInt tmpSize, t; 1584 PetscInt depth = 0, maxSize; 1585 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1586 PetscErrorCode ierr; 1587 1588 PetscFunctionBegin; 1589 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1590 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1591 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1592 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1593 if (*points) { 1594 closure = *points; 1595 } else { 1596 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1597 } 1598 closure[0] = p; closure[1] = 0; 1599 /* This is only 1-level */ 1600 if (useCone) { 1601 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1602 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1603 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1604 } else { 1605 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1606 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1607 } 1608 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1609 const PetscInt cp = tmp[t]; 1610 const PetscInt co = tmpO ? tmpO[t] : 0; 1611 1612 closure[closureSize] = cp; 1613 closure[closureSize+1] = co; 1614 fifo[fifoSize] = cp; 1615 fifo[fifoSize+1] = co; 1616 } 1617 while (fifoSize - fifoStart) { 1618 const PetscInt q = fifo[fifoStart]; 1619 const PetscInt o = fifo[fifoStart+1]; 1620 const PetscInt rev = o >= 0 ? 0 : 1; 1621 const PetscInt off = rev ? -(o+1) : o; 1622 1623 if (useCone) { 1624 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1625 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1626 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1627 } else { 1628 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1629 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1630 tmpO = PETSC_NULL; 1631 } 1632 for (t = 0; t < tmpSize; ++t) { 1633 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1634 const PetscInt cp = tmp[i]; 1635 /* Must propogate orientation */ 1636 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1637 PetscInt c; 1638 1639 /* Check for duplicate */ 1640 for (c = 0; c < closureSize; c += 2) { 1641 if (closure[c] == cp) break; 1642 } 1643 if (c == closureSize) { 1644 closure[closureSize] = cp; 1645 closure[closureSize+1] = co; 1646 fifo[fifoSize] = cp; 1647 fifo[fifoSize+1] = co; 1648 closureSize += 2; 1649 fifoSize += 2; 1650 } 1651 } 1652 fifoStart += 2; 1653 } 1654 if (numPoints) *numPoints = closureSize/2; 1655 if (points) *points = closure; 1656 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1657 PetscFunctionReturn(0); 1658 } 1659 1660 #undef __FUNCT__ 1661 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1662 /*@C 1663 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1664 1665 Not collective 1666 1667 Input Parameters: 1668 + mesh - The DMPlex 1669 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1670 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1671 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1672 1673 Output Parameters: 1674 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1675 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1676 1677 Note: 1678 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1679 1680 Level: beginner 1681 1682 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1683 @*/ 1684 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1685 { 1686 PetscErrorCode ierr; 1687 1688 PetscFunctionBegin; 1689 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1690 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1691 PetscFunctionReturn(0); 1692 } 1693 1694 #undef __FUNCT__ 1695 #define __FUNCT__ "DMPlexGetFaces" 1696 /* 1697 DMPlexGetFaces - 1698 1699 Note: This will only work for cell-vertex meshes. 1700 */ 1701 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1702 { 1703 DM_Plex *mesh = (DM_Plex*) dm->data; 1704 const PetscInt *cone = PETSC_NULL; 1705 PetscInt depth = 0, dim, coneSize; 1706 PetscErrorCode ierr; 1707 1708 PetscFunctionBegin; 1709 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1710 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1711 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1712 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1713 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1714 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1715 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1716 switch (dim) { 1717 case 2: 1718 switch (coneSize) { 1719 case 3: 1720 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1721 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1722 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1723 *numFaces = 3; 1724 *faceSize = 2; 1725 *faces = mesh->facesTmp; 1726 break; 1727 case 4: 1728 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1729 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1730 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1731 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1732 *numFaces = 4; 1733 *faceSize = 2; 1734 *faces = mesh->facesTmp; 1735 break; 1736 default: 1737 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1738 } 1739 break; 1740 case 3: 1741 switch (coneSize) { 1742 case 3: 1743 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1744 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1745 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1746 *numFaces = 3; 1747 *faceSize = 2; 1748 *faces = mesh->facesTmp; 1749 break; 1750 case 4: 1751 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1752 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1753 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1754 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1755 *numFaces = 4; 1756 *faceSize = 3; 1757 *faces = mesh->facesTmp; 1758 break; 1759 default: 1760 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1761 } 1762 break; 1763 default: 1764 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1765 } 1766 PetscFunctionReturn(0); 1767 } 1768 1769 #undef __FUNCT__ 1770 #define __FUNCT__ "DMPlexGetMaxSizes" 1771 /*@ 1772 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1773 1774 Not collective 1775 1776 Input Parameter: 1777 . mesh - The DMPlex 1778 1779 Output Parameters: 1780 + maxConeSize - The maximum number of in-edges 1781 - maxSupportSize - The maximum number of out-edges 1782 1783 Level: beginner 1784 1785 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1786 @*/ 1787 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1788 { 1789 DM_Plex *mesh = (DM_Plex*) dm->data; 1790 1791 PetscFunctionBegin; 1792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1793 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1794 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1795 PetscFunctionReturn(0); 1796 } 1797 1798 #undef __FUNCT__ 1799 #define __FUNCT__ "DMSetUp_Plex" 1800 PetscErrorCode DMSetUp_Plex(DM dm) 1801 { 1802 DM_Plex *mesh = (DM_Plex*) dm->data; 1803 PetscInt size; 1804 PetscErrorCode ierr; 1805 1806 PetscFunctionBegin; 1807 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1808 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1809 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1810 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1811 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1812 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1813 if (mesh->maxSupportSize) { 1814 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1815 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1816 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1817 } 1818 PetscFunctionReturn(0); 1819 } 1820 1821 #undef __FUNCT__ 1822 #define __FUNCT__ "DMCreateSubDM_Plex" 1823 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1824 { 1825 PetscSection section, sectionGlobal; 1826 PetscInt *subIndices; 1827 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1828 PetscErrorCode ierr; 1829 1830 PetscFunctionBegin; 1831 if (!numFields) PetscFunctionReturn(0); 1832 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1833 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1834 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1835 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1836 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1837 if (numFields > nF) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1838 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1839 for (p = pStart; p < pEnd; ++p) { 1840 PetscInt gdof; 1841 1842 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1843 if (gdof > 0) { 1844 for (f = 0; f < numFields; ++f) { 1845 PetscInt fdof, fcdof; 1846 1847 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1848 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1849 subSize += fdof-fcdof; 1850 } 1851 } 1852 } 1853 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1854 for (p = pStart; p < pEnd; ++p) { 1855 PetscInt gdof, goff; 1856 1857 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1858 if (gdof > 0) { 1859 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1860 for (f = 0; f < numFields; ++f) { 1861 PetscInt fdof, fcdof, fc, f2, poff = 0; 1862 1863 /* Can get rid of this loop by storing field information in the global section */ 1864 for (f2 = 0; f2 < fields[f]; ++f2) { 1865 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1866 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1867 poff += fdof-fcdof; 1868 } 1869 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1870 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1871 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1872 subIndices[subOff] = goff+poff+fc; 1873 } 1874 } 1875 } 1876 } 1877 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1878 if (subdm) { 1879 PetscSection subsection; 1880 PetscBool haveNull = PETSC_FALSE; 1881 PetscInt f, nf = 0; 1882 1883 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1884 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1885 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1886 for (f = 0; f < numFields; ++f) { 1887 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1888 if ((*subdm)->nullspaceConstructors[f]) { 1889 haveNull = PETSC_TRUE; 1890 nf = f; 1891 } 1892 } 1893 if (haveNull) { 1894 MatNullSpace nullSpace; 1895 1896 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1897 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1898 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1899 } 1900 if (dm->fields) { 1901 if (nF != dm->numFields) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1902 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1903 for (f = 0; f < numFields; ++f) { 1904 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1905 } 1906 if (numFields == 1) { 1907 MatNullSpace space; 1908 Mat pmat; 1909 1910 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1911 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1912 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1913 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1914 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1915 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1916 } 1917 } 1918 } 1919 PetscFunctionReturn(0); 1920 } 1921 1922 #undef __FUNCT__ 1923 #define __FUNCT__ "DMPlexSymmetrize" 1924 /*@ 1925 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1926 1927 Not collective 1928 1929 Input Parameter: 1930 . mesh - The DMPlex 1931 1932 Output Parameter: 1933 1934 Note: 1935 This should be called after all calls to DMPlexSetCone() 1936 1937 Level: beginner 1938 1939 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1940 @*/ 1941 PetscErrorCode DMPlexSymmetrize(DM dm) 1942 { 1943 DM_Plex *mesh = (DM_Plex*) dm->data; 1944 PetscInt *offsets; 1945 PetscInt supportSize; 1946 PetscInt pStart, pEnd, p; 1947 PetscErrorCode ierr; 1948 1949 PetscFunctionBegin; 1950 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1951 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1952 /* Calculate support sizes */ 1953 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1954 for (p = pStart; p < pEnd; ++p) { 1955 PetscInt dof, off, c; 1956 1957 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1958 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1959 for (c = off; c < off+dof; ++c) { 1960 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1961 } 1962 } 1963 for (p = pStart; p < pEnd; ++p) { 1964 PetscInt dof; 1965 1966 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1967 1968 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1969 } 1970 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1971 /* Calculate supports */ 1972 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1973 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1974 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1975 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1976 for (p = pStart; p < pEnd; ++p) { 1977 PetscInt dof, off, c; 1978 1979 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1980 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1981 for (c = off; c < off+dof; ++c) { 1982 const PetscInt q = mesh->cones[c]; 1983 PetscInt offS; 1984 1985 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1986 1987 mesh->supports[offS+offsets[q]] = p; 1988 ++offsets[q]; 1989 } 1990 } 1991 ierr = PetscFree(offsets);CHKERRQ(ierr); 1992 PetscFunctionReturn(0); 1993 } 1994 1995 #undef __FUNCT__ 1996 #define __FUNCT__ "DMPlexSetDepth_Private" 1997 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1998 { 1999 PetscInt d; 2000 PetscErrorCode ierr; 2001 2002 PetscFunctionBegin; 2003 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 2004 if (d < 0) { 2005 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2006 const PetscInt *cone = PETSC_NULL; 2007 PetscInt dCone; 2008 2009 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2010 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2011 d = dCone+1; 2012 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2013 } 2014 *depth = d; 2015 PetscFunctionReturn(0); 2016 } 2017 2018 #undef __FUNCT__ 2019 #define __FUNCT__ "DMPlexStratify" 2020 /*@ 2021 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2022 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2023 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2024 the DAG. 2025 2026 Not collective 2027 2028 Input Parameter: 2029 . mesh - The DMPlex 2030 2031 Output Parameter: 2032 2033 Notes: 2034 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2035 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2036 2037 This should be called after all calls to DMPlexSymmetrize() 2038 2039 Level: beginner 2040 2041 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2042 @*/ 2043 PetscErrorCode DMPlexStratify(DM dm) 2044 { 2045 DM_Plex *mesh = (DM_Plex*) dm->data; 2046 PetscInt pStart, pEnd, p; 2047 PetscInt numRoots = 0, numLeaves = 0; 2048 PetscErrorCode ierr; 2049 2050 PetscFunctionBegin; 2051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2052 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2053 /* Calculate depth */ 2054 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2055 /* Initialize roots and count leaves */ 2056 for (p = pStart; p < pEnd; ++p) { 2057 PetscInt coneSize, supportSize; 2058 2059 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2060 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2061 if (!coneSize && supportSize) { 2062 ++numRoots; 2063 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2064 } else if (!supportSize && coneSize) { 2065 ++numLeaves; 2066 } else if (!supportSize && !coneSize) { 2067 /* Isolated points */ 2068 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2069 } 2070 } 2071 if (numRoots + numLeaves == (pEnd - pStart)) { 2072 for (p = pStart; p < pEnd; ++p) { 2073 PetscInt coneSize, supportSize; 2074 2075 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2076 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2077 if (!supportSize && coneSize) { 2078 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2079 } 2080 } 2081 } else { 2082 /* This might be slow since lookup is not fast */ 2083 for (p = pStart; p < pEnd; ++p) { 2084 PetscInt depth; 2085 2086 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2087 } 2088 } 2089 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2090 PetscFunctionReturn(0); 2091 } 2092 2093 #undef __FUNCT__ 2094 #define __FUNCT__ "DMPlexGetJoin" 2095 /*@C 2096 DMPlexGetJoin - Get an array for the join of the set of points 2097 2098 Not Collective 2099 2100 Input Parameters: 2101 + dm - The DMPlex object 2102 . numPoints - The number of input points for the join 2103 - points - The input points 2104 2105 Output Parameters: 2106 + numCoveredPoints - The number of points in the join 2107 - coveredPoints - The points in the join 2108 2109 Level: intermediate 2110 2111 Note: Currently, this is restricted to a single level join 2112 2113 .keywords: mesh 2114 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2115 @*/ 2116 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2117 { 2118 DM_Plex *mesh = (DM_Plex*) dm->data; 2119 PetscInt *join[2]; 2120 PetscInt joinSize, i = 0; 2121 PetscInt dof, off, p, c, m; 2122 PetscErrorCode ierr; 2123 2124 PetscFunctionBegin; 2125 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2126 PetscValidPointer(points, 2); 2127 PetscValidPointer(numCoveredPoints, 3); 2128 PetscValidPointer(coveredPoints, 4); 2129 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2130 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2131 /* Copy in support of first point */ 2132 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2133 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2134 for (joinSize = 0; joinSize < dof; ++joinSize) { 2135 join[i][joinSize] = mesh->supports[off+joinSize]; 2136 } 2137 /* Check each successive support */ 2138 for (p = 1; p < numPoints; ++p) { 2139 PetscInt newJoinSize = 0; 2140 2141 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2142 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2143 for (c = 0; c < dof; ++c) { 2144 const PetscInt point = mesh->supports[off+c]; 2145 2146 for (m = 0; m < joinSize; ++m) { 2147 if (point == join[i][m]) { 2148 join[1-i][newJoinSize++] = point; 2149 break; 2150 } 2151 } 2152 } 2153 joinSize = newJoinSize; 2154 i = 1-i; 2155 } 2156 *numCoveredPoints = joinSize; 2157 *coveredPoints = join[i]; 2158 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2159 PetscFunctionReturn(0); 2160 } 2161 2162 #undef __FUNCT__ 2163 #define __FUNCT__ "DMPlexRestoreJoin" 2164 /*@C 2165 DMPlexRestoreJoin - Restore an array for the join of the set of points 2166 2167 Not Collective 2168 2169 Input Parameters: 2170 + dm - The DMPlex object 2171 . numPoints - The number of input points for the join 2172 - points - The input points 2173 2174 Output Parameters: 2175 + numCoveredPoints - The number of points in the join 2176 - coveredPoints - The points in the join 2177 2178 Level: intermediate 2179 2180 .keywords: mesh 2181 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2182 @*/ 2183 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2184 { 2185 PetscErrorCode ierr; 2186 2187 PetscFunctionBegin; 2188 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2189 PetscValidPointer(coveredPoints, 4); 2190 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2191 PetscFunctionReturn(0); 2192 } 2193 2194 #undef __FUNCT__ 2195 #define __FUNCT__ "DMPlexGetFullJoin" 2196 /*@C 2197 DMPlexGetFullJoin - Get an array for the join of the set of points 2198 2199 Not Collective 2200 2201 Input Parameters: 2202 + dm - The DMPlex object 2203 . numPoints - The number of input points for the join 2204 - points - The input points 2205 2206 Output Parameters: 2207 + numCoveredPoints - The number of points in the join 2208 - coveredPoints - The points in the join 2209 2210 Level: intermediate 2211 2212 .keywords: mesh 2213 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2214 @*/ 2215 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2216 { 2217 DM_Plex *mesh = (DM_Plex*) dm->data; 2218 PetscInt *offsets, **closures; 2219 PetscInt *join[2]; 2220 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2221 PetscInt p, d, c, m; 2222 PetscErrorCode ierr; 2223 2224 PetscFunctionBegin; 2225 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2226 PetscValidPointer(points, 2); 2227 PetscValidPointer(numCoveredPoints, 3); 2228 PetscValidPointer(coveredPoints, 4); 2229 2230 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2231 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2232 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2233 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2234 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2235 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2236 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2237 2238 for (p = 0; p < numPoints; ++p) { 2239 PetscInt closureSize; 2240 2241 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2242 2243 offsets[p*(depth+2)+0] = 0; 2244 for (d = 0; d < depth+1; ++d) { 2245 PetscInt pStart, pEnd, i; 2246 2247 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2248 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2249 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2250 offsets[p*(depth+2)+d+1] = i; 2251 break; 2252 } 2253 } 2254 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2255 } 2256 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2257 } 2258 for (d = 0; d < depth+1; ++d) { 2259 PetscInt dof; 2260 2261 /* Copy in support of first point */ 2262 dof = offsets[d+1] - offsets[d]; 2263 for (joinSize = 0; joinSize < dof; ++joinSize) { 2264 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2265 } 2266 /* Check each successive cone */ 2267 for (p = 1; p < numPoints && joinSize; ++p) { 2268 PetscInt newJoinSize = 0; 2269 2270 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2271 for (c = 0; c < dof; ++c) { 2272 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2273 2274 for (m = 0; m < joinSize; ++m) { 2275 if (point == join[i][m]) { 2276 join[1-i][newJoinSize++] = point; 2277 break; 2278 } 2279 } 2280 } 2281 joinSize = newJoinSize; 2282 i = 1-i; 2283 } 2284 if (joinSize) break; 2285 } 2286 *numCoveredPoints = joinSize; 2287 *coveredPoints = join[i]; 2288 for (p = 0; p < numPoints; ++p) { 2289 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2290 } 2291 ierr = PetscFree(closures);CHKERRQ(ierr); 2292 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2293 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2294 PetscFunctionReturn(0); 2295 } 2296 2297 #undef __FUNCT__ 2298 #define __FUNCT__ "DMPlexGetMeet" 2299 /*@C 2300 DMPlexGetMeet - Get an array for the meet of the set of points 2301 2302 Not Collective 2303 2304 Input Parameters: 2305 + dm - The DMPlex object 2306 . numPoints - The number of input points for the meet 2307 - points - The input points 2308 2309 Output Parameters: 2310 + numCoveredPoints - The number of points in the meet 2311 - coveredPoints - The points in the meet 2312 2313 Level: intermediate 2314 2315 Note: Currently, this is restricted to a single level meet 2316 2317 .keywords: mesh 2318 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2319 @*/ 2320 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2321 { 2322 DM_Plex *mesh = (DM_Plex*) dm->data; 2323 PetscInt *meet[2]; 2324 PetscInt meetSize, i = 0; 2325 PetscInt dof, off, p, c, m; 2326 PetscErrorCode ierr; 2327 2328 PetscFunctionBegin; 2329 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2330 PetscValidPointer(points, 2); 2331 PetscValidPointer(numCoveringPoints, 3); 2332 PetscValidPointer(coveringPoints, 4); 2333 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2334 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2335 /* Copy in cone of first point */ 2336 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2337 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2338 for (meetSize = 0; meetSize < dof; ++meetSize) { 2339 meet[i][meetSize] = mesh->cones[off+meetSize]; 2340 } 2341 /* Check each successive cone */ 2342 for (p = 1; p < numPoints; ++p) { 2343 PetscInt newMeetSize = 0; 2344 2345 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2346 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2347 for (c = 0; c < dof; ++c) { 2348 const PetscInt point = mesh->cones[off+c]; 2349 2350 for (m = 0; m < meetSize; ++m) { 2351 if (point == meet[i][m]) { 2352 meet[1-i][newMeetSize++] = point; 2353 break; 2354 } 2355 } 2356 } 2357 meetSize = newMeetSize; 2358 i = 1-i; 2359 } 2360 *numCoveringPoints = meetSize; 2361 *coveringPoints = meet[i]; 2362 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2363 PetscFunctionReturn(0); 2364 } 2365 2366 #undef __FUNCT__ 2367 #define __FUNCT__ "DMPlexRestoreMeet" 2368 /*@C 2369 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2370 2371 Not Collective 2372 2373 Input Parameters: 2374 + dm - The DMPlex object 2375 . numPoints - The number of input points for the meet 2376 - points - The input points 2377 2378 Output Parameters: 2379 + numCoveredPoints - The number of points in the meet 2380 - coveredPoints - The points in the meet 2381 2382 Level: intermediate 2383 2384 .keywords: mesh 2385 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2386 @*/ 2387 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2388 { 2389 PetscErrorCode ierr; 2390 2391 PetscFunctionBegin; 2392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2393 PetscValidPointer(coveredPoints, 4); 2394 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2395 PetscFunctionReturn(0); 2396 } 2397 2398 #undef __FUNCT__ 2399 #define __FUNCT__ "DMPlexGetFullMeet" 2400 /*@C 2401 DMPlexGetFullMeet - Get an array for the meet of the set of points 2402 2403 Not Collective 2404 2405 Input Parameters: 2406 + dm - The DMPlex object 2407 . numPoints - The number of input points for the meet 2408 - points - The input points 2409 2410 Output Parameters: 2411 + numCoveredPoints - The number of points in the meet 2412 - coveredPoints - The points in the meet 2413 2414 Level: intermediate 2415 2416 .keywords: mesh 2417 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2418 @*/ 2419 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2420 { 2421 DM_Plex *mesh = (DM_Plex*) dm->data; 2422 PetscInt *offsets, **closures; 2423 PetscInt *meet[2]; 2424 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2425 PetscInt p, h, c, m; 2426 PetscErrorCode ierr; 2427 2428 PetscFunctionBegin; 2429 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2430 PetscValidPointer(points, 2); 2431 PetscValidPointer(numCoveredPoints, 3); 2432 PetscValidPointer(coveredPoints, 4); 2433 2434 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2435 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2436 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2437 maxSize = PetscPowInt(mesh->maxConeSize,height); 2438 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2439 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2440 2441 for (p = 0; p < numPoints; ++p) { 2442 PetscInt closureSize; 2443 2444 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2445 2446 offsets[p*(height+2)+0] = 0; 2447 for (h = 0; h < height+1; ++h) { 2448 PetscInt pStart, pEnd, i; 2449 2450 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2451 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2452 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2453 offsets[p*(height+2)+h+1] = i; 2454 break; 2455 } 2456 } 2457 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2458 } 2459 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2460 } 2461 for (h = 0; h < height+1; ++h) { 2462 PetscInt dof; 2463 2464 /* Copy in cone of first point */ 2465 dof = offsets[h+1] - offsets[h]; 2466 for (meetSize = 0; meetSize < dof; ++meetSize) { 2467 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2468 } 2469 /* Check each successive cone */ 2470 for (p = 1; p < numPoints && meetSize; ++p) { 2471 PetscInt newMeetSize = 0; 2472 2473 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2474 for (c = 0; c < dof; ++c) { 2475 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2476 2477 for (m = 0; m < meetSize; ++m) { 2478 if (point == meet[i][m]) { 2479 meet[1-i][newMeetSize++] = point; 2480 break; 2481 } 2482 } 2483 } 2484 meetSize = newMeetSize; 2485 i = 1-i; 2486 } 2487 if (meetSize) break; 2488 } 2489 *numCoveredPoints = meetSize; 2490 *coveredPoints = meet[i]; 2491 for (p = 0; p < numPoints; ++p) { 2492 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2493 } 2494 ierr = PetscFree(closures);CHKERRQ(ierr); 2495 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2496 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2497 PetscFunctionReturn(0); 2498 } 2499 2500 #undef __FUNCT__ 2501 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2502 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2503 { 2504 MPI_Comm comm = ((PetscObject) dm)->comm; 2505 PetscInt cellDim; 2506 PetscErrorCode ierr; 2507 2508 PetscFunctionBegin; 2509 PetscValidPointer(numFaceVertices,3); 2510 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2511 switch (cellDim) { 2512 case 0: 2513 *numFaceVertices = 0; 2514 break; 2515 case 1: 2516 *numFaceVertices = 1; 2517 break; 2518 case 2: 2519 switch (numCorners) { 2520 case 3: /* triangle */ 2521 *numFaceVertices = 2; /* Edge has 2 vertices */ 2522 break; 2523 case 4: /* quadrilateral */ 2524 *numFaceVertices = 2; /* Edge has 2 vertices */ 2525 break; 2526 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2527 *numFaceVertices = 3; /* Edge has 3 vertices */ 2528 break; 2529 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2530 *numFaceVertices = 3; /* Edge has 3 vertices */ 2531 break; 2532 default: 2533 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2534 } 2535 break; 2536 case 3: 2537 switch (numCorners) { 2538 case 4: /* tetradehdron */ 2539 *numFaceVertices = 3; /* Face has 3 vertices */ 2540 break; 2541 case 6: /* tet cohesive cells */ 2542 *numFaceVertices = 4; /* Face has 4 vertices */ 2543 break; 2544 case 8: /* hexahedron */ 2545 *numFaceVertices = 4; /* Face has 4 vertices */ 2546 break; 2547 case 9: /* tet cohesive Lagrange cells */ 2548 *numFaceVertices = 6; /* Face has 6 vertices */ 2549 break; 2550 case 10: /* quadratic tetrahedron */ 2551 *numFaceVertices = 6; /* Face has 6 vertices */ 2552 break; 2553 case 12: /* hex cohesive Lagrange cells */ 2554 *numFaceVertices = 6; /* Face has 6 vertices */ 2555 break; 2556 case 18: /* quadratic tet cohesive Lagrange cells */ 2557 *numFaceVertices = 6; /* Face has 6 vertices */ 2558 break; 2559 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2560 *numFaceVertices = 9; /* Face has 9 vertices */ 2561 break; 2562 default: 2563 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2564 } 2565 break; 2566 default: 2567 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2568 } 2569 PetscFunctionReturn(0); 2570 } 2571 2572 #undef __FUNCT__ 2573 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2574 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2575 { 2576 const PetscInt maxFaceCases = 30; 2577 PetscInt numFaceCases = 0; 2578 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2579 PetscInt *off, *adj; 2580 PetscInt *neighborCells, *tmpClosure; 2581 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2582 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2583 PetscErrorCode ierr; 2584 2585 PetscFunctionBegin; 2586 /* For parallel partitioning, I think you have to communicate supports */ 2587 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2588 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2589 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2590 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2591 if (cEnd - cStart == 0) { 2592 if (numVertices) *numVertices = 0; 2593 if (offsets) *offsets = PETSC_NULL; 2594 if (adjacency) *adjacency = PETSC_NULL; 2595 PetscFunctionReturn(0); 2596 } 2597 numCells = cEnd - cStart; 2598 /* Setup face recognition */ 2599 if (depth == 1) { 2600 PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */ 2601 2602 for (c = cStart; c < cEnd; ++c) { 2603 PetscInt corners; 2604 2605 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2606 if (!cornersSeen[corners]) { 2607 PetscInt nFV; 2608 2609 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2610 cornersSeen[corners] = 1; 2611 2612 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2613 2614 numFaceVertices[numFaceCases++] = nFV; 2615 } 2616 } 2617 } 2618 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2619 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2620 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2621 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2622 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2623 /* Count neighboring cells */ 2624 for (cell = cStart; cell < cEnd; ++cell) { 2625 PetscInt numNeighbors = maxNeighbors, n; 2626 2627 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2628 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2629 for (n = 0; n < numNeighbors; ++n) { 2630 PetscInt cellPair[2]; 2631 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2632 PetscInt meetSize = 0; 2633 const PetscInt *meet = PETSC_NULL; 2634 2635 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2636 if (cellPair[0] == cellPair[1]) continue; 2637 if (!found) { 2638 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2639 if (meetSize) { 2640 PetscInt f; 2641 2642 for (f = 0; f < numFaceCases; ++f) { 2643 if (numFaceVertices[f] == meetSize) { 2644 found = PETSC_TRUE; 2645 break; 2646 } 2647 } 2648 } 2649 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2650 } 2651 if (found) ++off[cell-cStart+1]; 2652 } 2653 } 2654 /* Prefix sum */ 2655 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2656 2657 if (adjacency) { 2658 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2659 /* Get neighboring cells */ 2660 for (cell = cStart; cell < cEnd; ++cell) { 2661 PetscInt numNeighbors = maxNeighbors, n; 2662 PetscInt cellOffset = 0; 2663 2664 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2665 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2666 for (n = 0; n < numNeighbors; ++n) { 2667 PetscInt cellPair[2]; 2668 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2669 PetscInt meetSize = 0; 2670 const PetscInt *meet = PETSC_NULL; 2671 2672 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2673 if (cellPair[0] == cellPair[1]) continue; 2674 if (!found) { 2675 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2676 if (meetSize) { 2677 PetscInt f; 2678 2679 for (f = 0; f < numFaceCases; ++f) { 2680 if (numFaceVertices[f] == meetSize) { 2681 found = PETSC_TRUE; 2682 break; 2683 } 2684 } 2685 } 2686 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2687 } 2688 if (found) { 2689 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2690 ++cellOffset; 2691 } 2692 } 2693 } 2694 } 2695 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2696 if (numVertices) *numVertices = numCells; 2697 if (offsets) *offsets = off; 2698 if (adjacency) *adjacency = adj; 2699 PetscFunctionReturn(0); 2700 } 2701 2702 #if defined(PETSC_HAVE_CHACO) 2703 #if defined(PETSC_HAVE_UNISTD_H) 2704 #include <unistd.h> 2705 #endif 2706 /* Chaco does not have an include file */ 2707 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2708 float *ewgts, float *x, float *y, float *z, char *outassignname, 2709 char *outfilename, short *assignment, int architecture, int ndims_tot, 2710 int mesh_dims[3], double *goal, int global_method, int local_method, 2711 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2712 2713 extern int FREE_GRAPH; 2714 2715 #undef __FUNCT__ 2716 #define __FUNCT__ "DMPlexPartition_Chaco" 2717 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2718 { 2719 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2720 MPI_Comm comm = ((PetscObject) dm)->comm; 2721 int nvtxs = numVertices; /* number of vertices in full graph */ 2722 int *vwgts = NULL; /* weights for all vertices */ 2723 float *ewgts = NULL; /* weights for all edges */ 2724 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2725 char *outassignname = NULL; /* name of assignment output file */ 2726 char *outfilename = NULL; /* output file name */ 2727 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2728 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2729 int mesh_dims[3]; /* dimensions of mesh of processors */ 2730 double *goal = NULL; /* desired set sizes for each set */ 2731 int global_method = 1; /* global partitioning algorithm */ 2732 int local_method = 1; /* local partitioning algorithm */ 2733 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2734 int vmax = 200; /* how many vertices to coarsen down to? */ 2735 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2736 double eigtol = 0.001; /* tolerance on eigenvectors */ 2737 long seed = 123636512; /* for random graph mutations */ 2738 short int *assignment; /* Output partition */ 2739 int fd_stdout, fd_pipe[2]; 2740 PetscInt *points; 2741 PetscMPIInt commSize; 2742 int i, v, p; 2743 PetscErrorCode ierr; 2744 2745 PetscFunctionBegin; 2746 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2747 if (!numVertices) { 2748 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2749 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2750 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2751 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2752 PetscFunctionReturn(0); 2753 } 2754 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2755 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2756 2757 if (global_method == INERTIAL_METHOD) { 2758 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2759 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2760 } 2761 mesh_dims[0] = commSize; 2762 mesh_dims[1] = 1; 2763 mesh_dims[2] = 1; 2764 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2765 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2766 /* TODO: check error codes for UNIX calls */ 2767 #if defined(PETSC_HAVE_UNISTD_H) 2768 { 2769 int piperet; 2770 piperet = pipe(fd_pipe); 2771 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2772 fd_stdout = dup(1); 2773 close(1); 2774 dup2(fd_pipe[1], 1); 2775 } 2776 #endif 2777 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2778 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2779 vmax, ndims, eigtol, seed); 2780 #if defined(PETSC_HAVE_UNISTD_H) 2781 { 2782 char msgLog[10000]; 2783 int count; 2784 2785 fflush(stdout); 2786 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2787 if (count < 0) count = 0; 2788 msgLog[count] = 0; 2789 close(1); 2790 dup2(fd_stdout, 1); 2791 close(fd_stdout); 2792 close(fd_pipe[0]); 2793 close(fd_pipe[1]); 2794 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2795 } 2796 #endif 2797 /* Convert to PetscSection+IS */ 2798 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2799 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2800 for (v = 0; v < nvtxs; ++v) { 2801 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2802 } 2803 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2804 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2805 for (p = 0, i = 0; p < commSize; ++p) { 2806 for (v = 0; v < nvtxs; ++v) { 2807 if (assignment[v] == p) points[i++] = v; 2808 } 2809 } 2810 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2811 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2812 if (global_method == INERTIAL_METHOD) { 2813 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2814 } 2815 ierr = PetscFree(assignment);CHKERRQ(ierr); 2816 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2817 PetscFunctionReturn(0); 2818 } 2819 #endif 2820 2821 #if defined(PETSC_HAVE_PARMETIS) 2822 #undef __FUNCT__ 2823 #define __FUNCT__ "DMPlexPartition_ParMetis" 2824 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2825 { 2826 PetscFunctionBegin; 2827 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2828 PetscFunctionReturn(0); 2829 } 2830 #endif 2831 2832 #undef __FUNCT__ 2833 #define __FUNCT__ "DMPlexEnlargePartition" 2834 /* Expand the partition by BFS on the adjacency graph */ 2835 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2836 { 2837 PetscHashI h; 2838 const PetscInt *points; 2839 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2840 PetscInt pStart, pEnd, part, q; 2841 PetscErrorCode ierr; 2842 2843 PetscFunctionBegin; 2844 PetscHashICreate(h); 2845 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2846 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2847 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2848 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2849 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2850 for (part = pStart; part < pEnd; ++part) { 2851 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2852 2853 PetscHashIClear(h); 2854 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2855 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2856 /* Add all existing points to h */ 2857 for (p = 0; p < numPoints; ++p) { 2858 const PetscInt point = points[off+p]; 2859 PetscHashIAdd(h, point, 1); 2860 } 2861 PetscHashISize(h, nP); 2862 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2863 /* Add all points in next BFS level */ 2864 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2865 for (p = 0; p < numPoints; ++p) { 2866 const PetscInt point = points[off+p]; 2867 PetscInt s = start[point], e = start[point+1], a; 2868 2869 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2870 } 2871 PetscHashISize(h, numNewPoints); 2872 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2873 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2874 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2875 totPoints += numNewPoints; 2876 } 2877 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2878 PetscHashIDestroy(h); 2879 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2880 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2881 for (part = pStart, q = 0; part < pEnd; ++part) { 2882 PetscInt numPoints, p; 2883 2884 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2885 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2886 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2887 } 2888 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2889 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2890 PetscFunctionReturn(0); 2891 } 2892 2893 #undef __FUNCT__ 2894 #define __FUNCT__ "DMPlexCreatePartition" 2895 /* 2896 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2897 2898 Collective on DM 2899 2900 Input Parameters: 2901 + dm - The DM 2902 . height - The height for points in the partition 2903 - enlarge - Expand each partition with neighbors 2904 2905 Output Parameters: 2906 + partSection - The PetscSection giving the division of points by partition 2907 . partition - The list of points by partition 2908 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2909 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2910 2911 Level: developer 2912 2913 .seealso DMPlexDistribute() 2914 */ 2915 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2916 { 2917 PetscMPIInt size; 2918 PetscErrorCode ierr; 2919 2920 PetscFunctionBegin; 2921 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2922 2923 *origPartSection = PETSC_NULL; 2924 *origPartition = PETSC_NULL; 2925 if (size == 1) { 2926 PetscInt *points; 2927 PetscInt cStart, cEnd, c; 2928 2929 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2930 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2931 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2932 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2933 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2934 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2935 for (c = cStart; c < cEnd; ++c) points[c] = c; 2936 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2937 PetscFunctionReturn(0); 2938 } 2939 if (height == 0) { 2940 PetscInt numVertices; 2941 PetscInt *start = PETSC_NULL; 2942 PetscInt *adjacency = PETSC_NULL; 2943 2944 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2945 if (1) { 2946 #if defined(PETSC_HAVE_CHACO) 2947 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2948 #endif 2949 } else { 2950 #if defined(PETSC_HAVE_PARMETIS) 2951 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2952 #endif 2953 } 2954 if (enlarge) { 2955 *origPartSection = *partSection; 2956 *origPartition = *partition; 2957 2958 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2959 } 2960 ierr = PetscFree(start);CHKERRQ(ierr); 2961 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2962 # if 0 2963 } else if (height == 1) { 2964 /* Build the dual graph for faces and partition the hypergraph */ 2965 PetscInt numEdges; 2966 2967 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2968 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2969 destroyCSR(numEdges, start, adjacency); 2970 #endif 2971 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2972 PetscFunctionReturn(0); 2973 } 2974 2975 #undef __FUNCT__ 2976 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2977 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2978 { 2979 /* const PetscInt height = 0; */ 2980 const PetscInt *partArray; 2981 PetscInt *allPoints, *partPoints = PETSC_NULL; 2982 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2983 PetscErrorCode ierr; 2984 2985 PetscFunctionBegin; 2986 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2987 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2988 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2989 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2990 for (rank = rStart; rank < rEnd; ++rank) { 2991 PetscInt partSize = 0; 2992 PetscInt numPoints, offset, p; 2993 2994 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2995 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2996 for (p = 0; p < numPoints; ++p) { 2997 PetscInt point = partArray[offset+p], closureSize, c; 2998 PetscInt *closure = PETSC_NULL; 2999 3000 /* TODO Include support for height > 0 case */ 3001 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3002 /* Merge into existing points */ 3003 if (partSize+closureSize > maxPartSize) { 3004 PetscInt *tmpPoints; 3005 3006 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 3007 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 3008 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3009 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3010 3011 partPoints = tmpPoints; 3012 } 3013 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3014 partSize += closureSize; 3015 3016 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3017 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3018 } 3019 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3020 } 3021 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3022 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3023 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3024 3025 for (rank = rStart; rank < rEnd; ++rank) { 3026 PetscInt partSize = 0, newOffset; 3027 PetscInt numPoints, offset, p; 3028 3029 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3030 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3031 for (p = 0; p < numPoints; ++p) { 3032 PetscInt point = partArray[offset+p], closureSize, c; 3033 PetscInt *closure = PETSC_NULL; 3034 3035 /* TODO Include support for height > 0 case */ 3036 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3037 /* Merge into existing points */ 3038 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3039 partSize += closureSize; 3040 3041 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3042 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3043 } 3044 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3045 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3046 } 3047 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3048 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3049 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3050 PetscFunctionReturn(0); 3051 } 3052 3053 #undef __FUNCT__ 3054 #define __FUNCT__ "DMPlexDistributeField" 3055 /* 3056 Input Parameters: 3057 . originalSection 3058 , originalVec 3059 3060 Output Parameters: 3061 . newSection 3062 . newVec 3063 */ 3064 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3065 { 3066 PetscSF fieldSF; 3067 PetscInt *remoteOffsets, fieldSize; 3068 PetscScalar *originalValues, *newValues; 3069 PetscErrorCode ierr; 3070 3071 PetscFunctionBegin; 3072 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3073 3074 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3075 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3076 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3077 3078 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3079 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3080 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3081 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3082 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3083 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3084 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3085 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3086 PetscFunctionReturn(0); 3087 } 3088 3089 #undef __FUNCT__ 3090 #define __FUNCT__ "DMPlexDistribute" 3091 /*@C 3092 DMPlexDistribute - Distributes the mesh and any associated sections. 3093 3094 Not Collective 3095 3096 Input Parameter: 3097 + dm - The original DMPlex object 3098 . partitioner - The partitioning package, or NULL for the default 3099 - overlap - The overlap of partitions, 0 is the default 3100 3101 Output Parameter: 3102 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3103 3104 Note: If the mesh was not distributed, the return value is PETSC_NULL 3105 3106 Level: intermediate 3107 3108 .keywords: mesh, elements 3109 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3110 @*/ 3111 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3112 { 3113 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3114 MPI_Comm comm = ((PetscObject) dm)->comm; 3115 const PetscInt height = 0; 3116 PetscInt dim, numRemoteRanks; 3117 IS origCellPart, cellPart, part; 3118 PetscSection origCellPartSection, cellPartSection, partSection; 3119 PetscSFNode *remoteRanks; 3120 PetscSF partSF, pointSF, coneSF; 3121 ISLocalToGlobalMapping renumbering; 3122 PetscSection originalConeSection, newConeSection; 3123 PetscInt *remoteOffsets; 3124 PetscInt *cones, *newCones, newConesSize; 3125 PetscBool flg; 3126 PetscMPIInt rank, numProcs, p; 3127 PetscErrorCode ierr; 3128 3129 PetscFunctionBegin; 3130 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3131 PetscValidPointer(dmParallel,4); 3132 3133 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3134 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3135 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3136 3137 *dmParallel = PETSC_NULL; 3138 if (numProcs == 1) PetscFunctionReturn(0); 3139 3140 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3141 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3142 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3143 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3144 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3145 if (!rank) numRemoteRanks = numProcs; 3146 else numRemoteRanks = 0; 3147 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3148 for (p = 0; p < numRemoteRanks; ++p) { 3149 remoteRanks[p].rank = p; 3150 remoteRanks[p].index = 0; 3151 } 3152 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3153 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3154 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3155 if (flg) { 3156 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3157 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3158 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3159 if (origCellPart) { 3160 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3161 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3162 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3163 } 3164 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3165 } 3166 /* Close the partition over the mesh */ 3167 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3168 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3169 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3170 /* Create new mesh */ 3171 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3172 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3173 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3174 pmesh = (DM_Plex*) (*dmParallel)->data; 3175 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3176 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3177 if (flg) { 3178 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3179 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3180 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3181 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3182 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3183 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3184 } 3185 /* Distribute cone section */ 3186 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3187 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3188 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3189 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3190 { 3191 PetscInt pStart, pEnd, p; 3192 3193 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3194 for (p = pStart; p < pEnd; ++p) { 3195 PetscInt coneSize; 3196 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3197 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3198 } 3199 } 3200 /* Communicate and renumber cones */ 3201 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3202 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3203 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3204 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3205 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3206 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3207 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3208 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3209 if (flg) { 3210 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3211 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3212 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3213 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3214 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3215 } 3216 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3217 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3218 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3219 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3220 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3221 /* Create supports and stratify sieve */ 3222 { 3223 PetscInt pStart, pEnd; 3224 3225 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3226 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3227 } 3228 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3229 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3230 /* Distribute Coordinates */ 3231 { 3232 PetscSection originalCoordSection, newCoordSection; 3233 Vec originalCoordinates, newCoordinates; 3234 const char *name; 3235 3236 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3237 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3238 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3239 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3240 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3241 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3242 3243 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3244 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3245 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3246 } 3247 /* Distribute labels */ 3248 { 3249 DMLabel next = mesh->labels, newNext = pmesh->labels; 3250 PetscInt numLabels = 0, l; 3251 3252 /* Bcast number of labels */ 3253 while (next) { 3254 ++numLabels; next = next->next; 3255 } 3256 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3257 next = mesh->labels; 3258 for (l = 0; l < numLabels; ++l) { 3259 DMLabel newLabel; 3260 const PetscInt *partArray; 3261 char *name; 3262 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3263 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3264 PetscInt nameSize, s, p; 3265 PetscBool isdepth; 3266 size_t len = 0; 3267 3268 /* Bcast name (could filter for no points) */ 3269 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3270 nameSize = len; 3271 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3272 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3273 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3274 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3275 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3276 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3277 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3278 newLabel->name = name; 3279 /* Bcast numStrata (could filter for no points in stratum) */ 3280 if (!rank) newLabel->numStrata = next->numStrata; 3281 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3282 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3283 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3284 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3285 /* Bcast stratumValues (could filter for no points in stratum) */ 3286 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3287 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3288 /* Find size on each process and Scatter */ 3289 if (!rank) { 3290 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3291 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3292 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3293 for (s = 0; s < next->numStrata; ++s) { 3294 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3295 const PetscInt point = next->points[p]; 3296 PetscInt proc; 3297 3298 for (proc = 0; proc < numProcs; ++proc) { 3299 PetscInt dof, off, pPart; 3300 3301 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3302 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3303 for (pPart = off; pPart < off+dof; ++pPart) { 3304 if (partArray[pPart] == point) { 3305 ++stratumSizes[proc*next->numStrata+s]; 3306 break; 3307 } 3308 } 3309 } 3310 } 3311 } 3312 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3313 } 3314 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3315 /* Calculate stratumOffsets */ 3316 newLabel->stratumOffsets[0] = 0; 3317 for (s = 0; s < newLabel->numStrata; ++s) { 3318 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3319 } 3320 /* Pack points and Scatter */ 3321 if (!rank) { 3322 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3323 displs[0] = 0; 3324 for (p = 0; p < numProcs; ++p) { 3325 sendcnts[p] = 0; 3326 for (s = 0; s < next->numStrata; ++s) { 3327 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3328 } 3329 offsets[p] = displs[p]; 3330 displs[p+1] = displs[p] + sendcnts[p]; 3331 } 3332 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3333 for (s = 0; s < next->numStrata; ++s) { 3334 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3335 const PetscInt point = next->points[p]; 3336 PetscInt proc; 3337 3338 for (proc = 0; proc < numProcs; ++proc) { 3339 PetscInt dof, off, pPart; 3340 3341 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3342 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3343 for (pPart = off; pPart < off+dof; ++pPart) { 3344 if (partArray[pPart] == point) { 3345 points[offsets[proc]++] = point; 3346 break; 3347 } 3348 } 3349 } 3350 } 3351 } 3352 } 3353 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3354 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3355 ierr = PetscFree(points);CHKERRQ(ierr); 3356 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3357 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3358 /* Renumber points */ 3359 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3360 /* Sort points */ 3361 for (s = 0; s < newLabel->numStrata; ++s) { 3362 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3363 } 3364 /* Insert into list */ 3365 if (newNext) newNext->next = newLabel; 3366 else pmesh->labels = newLabel; 3367 newNext = newLabel; 3368 if (!rank) next = next->next; 3369 } 3370 } 3371 /* Cleanup Partition */ 3372 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3373 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3374 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3375 ierr = ISDestroy(&part);CHKERRQ(ierr); 3376 /* Create point SF for parallel mesh */ 3377 { 3378 const PetscInt *leaves; 3379 PetscSFNode *remotePoints, *rowners, *lowners; 3380 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3381 PetscInt pStart, pEnd; 3382 3383 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3384 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3385 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3386 for (p=0; p<numRoots; p++) { 3387 rowners[p].rank = -1; 3388 rowners[p].index = -1; 3389 } 3390 if (origCellPart) { 3391 /* Make sure cells in the original partition are not assigned to other procs */ 3392 const PetscInt *origCells; 3393 3394 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3395 for (p = 0; p < numProcs; ++p) { 3396 PetscInt dof, off, d; 3397 3398 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3399 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3400 for (d = off; d < off+dof; ++d) { 3401 rowners[origCells[d]].rank = p; 3402 } 3403 } 3404 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3405 } 3406 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3407 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3408 3409 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3410 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3411 for (p = 0; p < numLeaves; ++p) { 3412 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3413 lowners[p].rank = rank; 3414 lowners[p].index = leaves ? leaves[p] : p; 3415 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3416 lowners[p].rank = -2; 3417 lowners[p].index = -2; 3418 } 3419 } 3420 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3421 rowners[p].rank = -3; 3422 rowners[p].index = -3; 3423 } 3424 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3425 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3426 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3427 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3428 for (p = 0; p < numLeaves; ++p) { 3429 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3430 if (lowners[p].rank != rank) ++numGhostPoints; 3431 } 3432 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3433 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3434 for (p = 0, gp = 0; p < numLeaves; ++p) { 3435 if (lowners[p].rank != rank) { 3436 ghostPoints[gp] = leaves ? leaves[p] : p; 3437 remotePoints[gp].rank = lowners[p].rank; 3438 remotePoints[gp].index = lowners[p].index; 3439 ++gp; 3440 } 3441 } 3442 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3443 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3444 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3445 } 3446 /* Cleanup */ 3447 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3448 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3449 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3450 PetscFunctionReturn(0); 3451 } 3452 3453 #undef __FUNCT__ 3454 #define __FUNCT__ "DMPlexRenumber_Private" 3455 /* 3456 Reasons to renumber: 3457 3458 1) Permute points, e.g. bandwidth reduction (Renumber) 3459 3460 a) Must not mix strata 3461 3462 2) Shift numbers for point insertion (Shift) 3463 3464 a) Want operation brken into parts so that insertion can be interleaved 3465 3466 renumbering - An IS which provides the new numbering 3467 */ 3468 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3469 { 3470 PetscFunctionBegin; 3471 PetscFunctionReturn(0); 3472 } 3473 3474 #undef __FUNCT__ 3475 #define __FUNCT__ "DMPlexShiftPoint_Private" 3476 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3477 { 3478 if (depth < 0) return p; 3479 /* Cells */ if (p < depthEnd[depth]) return p; 3480 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3481 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3482 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3483 } 3484 3485 #undef __FUNCT__ 3486 #define __FUNCT__ "DMPlexShiftSizes_Private" 3487 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3488 { 3489 PetscInt *depthEnd; 3490 PetscInt depth = 0, d, pStart, pEnd, p; 3491 PetscErrorCode ierr; 3492 3493 PetscFunctionBegin; 3494 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3495 if (depth < 0) PetscFunctionReturn(0); 3496 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3497 /* Step 1: Expand chart */ 3498 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3499 for (d = 0; d <= depth; ++d) { 3500 pEnd += depthShift[d]; 3501 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3502 } 3503 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3504 /* Step 2: Set cone and support sizes */ 3505 for (d = 0; d <= depth; ++d) { 3506 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3507 for (p = pStart; p < pEnd; ++p) { 3508 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3509 PetscInt size; 3510 3511 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3512 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3513 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3514 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3515 } 3516 } 3517 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3518 PetscFunctionReturn(0); 3519 } 3520 3521 #undef __FUNCT__ 3522 #define __FUNCT__ "DMPlexShiftPoints_Private" 3523 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3524 { 3525 PetscInt *depthEnd, *newpoints; 3526 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3527 PetscErrorCode ierr; 3528 3529 PetscFunctionBegin; 3530 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3531 if (depth < 0) PetscFunctionReturn(0); 3532 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3533 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3534 for (d = 0; d <= depth; ++d) { 3535 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3536 } 3537 /* Step 5: Set cones and supports */ 3538 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3539 for (p = pStart; p < pEnd; ++p) { 3540 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3541 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3542 3543 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3544 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3545 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3546 for (i = 0; i < size; ++i) { 3547 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3548 } 3549 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3550 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3551 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3552 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3553 for (i = 0; i < size; ++i) { 3554 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3555 } 3556 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3557 } 3558 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3559 PetscFunctionReturn(0); 3560 } 3561 3562 #undef __FUNCT__ 3563 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3564 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3565 { 3566 PetscSection coordSection, newCoordSection; 3567 Vec coordinates, newCoordinates; 3568 PetscScalar *coords, *newCoords; 3569 PetscInt *depthEnd, coordSize; 3570 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3571 PetscErrorCode ierr; 3572 3573 PetscFunctionBegin; 3574 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3575 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3576 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3577 for (d = 0; d <= depth; ++d) { 3578 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3579 } 3580 /* Step 8: Convert coordinates */ 3581 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3582 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3583 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3584 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3585 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3586 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3587 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3588 for (v = vStartNew; v < vEndNew; ++v) { 3589 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3590 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3591 } 3592 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3593 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3594 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3595 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3596 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3597 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3598 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3599 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3600 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3601 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3602 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3603 for (v = vStart; v < vEnd; ++v) { 3604 PetscInt dof, off, noff, d; 3605 3606 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3607 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3608 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3609 for (d = 0; d < dof; ++d) { 3610 newCoords[noff+d] = coords[off+d]; 3611 } 3612 } 3613 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3614 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3615 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3616 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3617 PetscFunctionReturn(0); 3618 } 3619 3620 #undef __FUNCT__ 3621 #define __FUNCT__ "DMPlexShiftSF_Private" 3622 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3623 { 3624 PetscInt *depthEnd; 3625 PetscInt depth = 0, d; 3626 PetscSF sfPoint, sfPointNew; 3627 const PetscSFNode *remotePoints; 3628 PetscSFNode *gremotePoints; 3629 const PetscInt *localPoints; 3630 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3631 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3632 PetscMPIInt numProcs; 3633 PetscErrorCode ierr; 3634 3635 PetscFunctionBegin; 3636 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3637 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3638 for (d = 0; d <= depth; ++d) { 3639 totShift += depthShift[d]; 3640 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3641 } 3642 /* Step 9: Convert pointSF */ 3643 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3644 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3645 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3646 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3647 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3648 if (numRoots >= 0) { 3649 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3650 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3651 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3652 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3653 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3654 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3655 for (l = 0; l < numLeaves; ++l) { 3656 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3657 gremotePoints[l].rank = remotePoints[l].rank; 3658 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3659 } 3660 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3661 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3662 } 3663 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3664 PetscFunctionReturn(0); 3665 } 3666 3667 #undef __FUNCT__ 3668 #define __FUNCT__ "DMPlexShiftLabels_Private" 3669 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3670 { 3671 PetscSF sfPoint; 3672 DMLabel vtkLabel, ghostLabel; 3673 PetscInt *depthEnd; 3674 const PetscSFNode *leafRemote; 3675 const PetscInt *leafLocal; 3676 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3677 PetscMPIInt rank; 3678 PetscErrorCode ierr; 3679 3680 PetscFunctionBegin; 3681 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3682 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3683 for (d = 0; d <= depth; ++d) { 3684 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3685 } 3686 /* Step 10: Convert labels */ 3687 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3688 for (l = 0; l < numLabels; ++l) { 3689 DMLabel label, newlabel; 3690 const char *lname; 3691 PetscBool isDepth; 3692 IS valueIS; 3693 const PetscInt *values; 3694 PetscInt numValues, val; 3695 3696 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3697 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3698 if (isDepth) continue; 3699 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3700 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3701 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3702 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3703 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3704 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3705 for (val = 0; val < numValues; ++val) { 3706 IS pointIS; 3707 const PetscInt *points; 3708 PetscInt numPoints, p; 3709 3710 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3711 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3712 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3713 for (p = 0; p < numPoints; ++p) { 3714 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3715 3716 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3717 } 3718 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3719 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3720 } 3721 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3722 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3723 } 3724 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3725 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3726 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3727 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3728 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3729 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3730 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3731 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3732 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3733 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3734 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3735 for (; c < leafLocal[l] && c < cEnd; ++c) { 3736 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3737 } 3738 if (leafLocal[l] >= cEnd) break; 3739 if (leafRemote[l].rank == rank) { 3740 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3741 } else { 3742 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3743 } 3744 } 3745 for (; c < cEnd; ++c) { 3746 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3747 } 3748 if (0) { 3749 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3750 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3751 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3752 } 3753 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3754 for (f = fStart; f < fEnd; ++f) { 3755 PetscInt numCells; 3756 3757 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3758 if (numCells < 2) { 3759 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3760 } else { 3761 const PetscInt *cells = PETSC_NULL; 3762 PetscInt vA, vB; 3763 3764 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3765 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3766 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3767 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3768 } 3769 } 3770 if (0) { 3771 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3772 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3773 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3774 } 3775 PetscFunctionReturn(0); 3776 } 3777 3778 #undef __FUNCT__ 3779 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3780 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3781 { 3782 DMLabel label; 3783 IS valueIS; 3784 const PetscInt *values; 3785 PetscInt *depthShift; 3786 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3787 PetscErrorCode ierr; 3788 3789 PetscFunctionBegin; 3790 /* Count ghost cells */ 3791 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3792 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3793 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3794 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3795 3796 *numGhostCells = 0; 3797 for (fs = 0; fs < numFS; ++fs) { 3798 PetscInt numBdFaces; 3799 3800 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3801 3802 *numGhostCells += numBdFaces; 3803 } 3804 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3805 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3806 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3807 if (depth >= 0) depthShift[depth] = *numGhostCells; 3808 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3809 /* Step 3: Set cone/support sizes for new points */ 3810 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3811 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3812 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3813 } 3814 for (fs = 0; fs < numFS; ++fs) { 3815 IS faceIS; 3816 const PetscInt *faces; 3817 PetscInt numFaces, f; 3818 3819 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3820 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3821 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3822 for (f = 0; f < numFaces; ++f) { 3823 PetscInt size; 3824 3825 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3826 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3827 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3828 } 3829 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3830 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3831 } 3832 /* Step 4: Setup ghosted DM */ 3833 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3834 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3835 /* Step 6: Set cones and supports for new points */ 3836 ghostCell = cEnd; 3837 for (fs = 0; fs < numFS; ++fs) { 3838 IS faceIS; 3839 const PetscInt *faces; 3840 PetscInt numFaces, f; 3841 3842 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3843 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3844 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3845 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3846 PetscInt newFace = faces[f] + *numGhostCells; 3847 3848 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3849 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3850 } 3851 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3852 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3853 } 3854 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3855 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3856 /* Step 7: Stratify */ 3857 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3858 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3859 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3860 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3861 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3862 PetscFunctionReturn(0); 3863 } 3864 3865 #undef __FUNCT__ 3866 #define __FUNCT__ "DMPlexConstructGhostCells" 3867 /*@C 3868 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3869 3870 Collective on dm 3871 3872 Input Parameters: 3873 + dm - The original DM 3874 - labelName - The label specifying the boundary faces (this could be auto-generated) 3875 3876 Output Parameters: 3877 + numGhostCells - The number of ghost cells added to the DM 3878 - dmGhosted - The new DM 3879 3880 Level: developer 3881 3882 .seealso: DMCreate() 3883 */ 3884 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3885 { 3886 DM gdm; 3887 PetscInt dim; 3888 PetscErrorCode ierr; 3889 3890 PetscFunctionBegin; 3891 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3892 PetscValidPointer(numGhostCells, 3); 3893 PetscValidPointer(dmGhosted, 4); 3894 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3895 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3896 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3897 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3898 switch (dim) { 3899 case 2: 3900 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3901 break; 3902 default: 3903 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3904 } 3905 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3906 *dmGhosted = gdm; 3907 PetscFunctionReturn(0); 3908 } 3909 3910 #undef __FUNCT__ 3911 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3912 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3913 { 3914 MPI_Comm comm = ((PetscObject) dm)->comm; 3915 IS valueIS, *pointIS; 3916 const PetscInt *values, **splitPoints; 3917 PetscSection coordSection; 3918 Vec coordinates; 3919 PetscScalar *coords; 3920 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3921 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3922 PetscErrorCode ierr; 3923 3924 PetscFunctionBegin; 3925 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3926 /* Count split points and add cohesive cells */ 3927 if (label) { 3928 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3929 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3930 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3931 } 3932 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3933 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3934 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3935 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3936 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3937 for (d = 0; d <= depth; ++d) { 3938 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3939 numSplitPoints[d] = 0; 3940 splitPoints[d] = PETSC_NULL; 3941 pointIS[d] = PETSC_NULL; 3942 } 3943 for (sp = 0; sp < numSP; ++sp) { 3944 const PetscInt dep = values[sp]; 3945 3946 if ((dep < 0) || (dep > depth)) continue; 3947 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3948 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3949 if (pointIS[dep]) { 3950 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3951 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3952 } 3953 } 3954 if (depth >= 0) { 3955 /* Calculate number of additional points */ 3956 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3957 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3958 /* Calculate hybrid bound for each dimension */ 3959 pMaxNew[0] += depthShift[depth]; 3960 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3961 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3962 3963 /* Calculate point offset for each dimension */ 3964 depthOffset[depth] = 0; 3965 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3966 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3967 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3968 } 3969 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3970 /* Step 3: Set cone/support sizes for new points */ 3971 for (dep = 0; dep <= depth; ++dep) { 3972 for (p = 0; p < numSplitPoints[dep]; ++p) { 3973 const PetscInt oldp = splitPoints[dep][p]; 3974 const PetscInt newp = depthOffset[dep] + oldp; 3975 const PetscInt splitp = pMaxNew[dep] + p; 3976 const PetscInt *support; 3977 PetscInt coneSize, supportSize, q, e; 3978 3979 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3980 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3981 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3982 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3983 if (dep == depth-1) { 3984 const PetscInt ccell = pMaxNew[depth] + p; 3985 /* Add cohesive cells, they are prisms */ 3986 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3987 } else if (dep == 0) { 3988 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3989 3990 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3991 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3992 for (e = 0, q = 0; e < supportSize; ++e) { 3993 PetscInt val; 3994 3995 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3996 if ((val == 1) || (val == (shift + 1))) ++q; 3997 } 3998 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3999 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4000 for (e = 0, q = 0; e < supportSize; ++e) { 4001 PetscInt val; 4002 4003 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4004 if ((val == 1) || (val == -(shift + 1))) ++q; 4005 } 4006 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 4007 /* Add cohesive edges */ 4008 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 4009 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4010 } else if (dep == dim-2) { 4011 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4012 /* Split old edge: Faces in positive side cells and old split faces */ 4013 for (e = 0, q = 0; e < supportSize; ++e) { 4014 PetscInt val; 4015 4016 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4017 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4018 } 4019 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4020 /* Split new edge: Faces in negative side cells and new split faces */ 4021 for (e = 0, q = 0; e < supportSize; ++e) { 4022 PetscInt val; 4023 4024 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4025 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4026 } 4027 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4028 } 4029 } 4030 } 4031 /* Step 4: Setup split DM */ 4032 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4033 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4034 /* Step 6: Set cones and supports for new points */ 4035 for (dep = 0; dep <= depth; ++dep) { 4036 for (p = 0; p < numSplitPoints[dep]; ++p) { 4037 const PetscInt oldp = splitPoints[dep][p]; 4038 const PetscInt newp = depthOffset[dep] + oldp; 4039 const PetscInt splitp = pMaxNew[dep] + p; 4040 const PetscInt *cone, *support, *ornt; 4041 PetscInt coneSize, supportSize, q, v, e, s; 4042 4043 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4044 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4045 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4046 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4047 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4048 if (dep == depth-1) { 4049 const PetscInt ccell = pMaxNew[depth] + p; 4050 const PetscInt *supportF; 4051 4052 /* Split face: copy in old face to new face to start */ 4053 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4054 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4055 /* Split old face: old vertices/edges in cone so no change */ 4056 /* Split new face: new vertices/edges in cone */ 4057 for (q = 0; q < coneSize; ++q) { 4058 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4059 4060 coneNew[2+q] = pMaxNew[dim-2] + v; 4061 } 4062 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4063 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4064 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4065 coneNew[0] = newp; 4066 coneNew[1] = splitp; 4067 for (q = 0; q < coneSize; ++q) { 4068 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4069 } 4070 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4071 4072 4073 for (s = 0; s < supportSize; ++s) { 4074 PetscInt val; 4075 4076 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4077 if (val < 0) { 4078 /* Split old face: Replace negative side cell with cohesive cell */ 4079 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4080 } else { 4081 /* Split new face: Replace positive side cell with cohesive cell */ 4082 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4083 } 4084 } 4085 } else if (dep == 0) { 4086 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4087 4088 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4089 for (e = 0, q = 0; e < supportSize; ++e) { 4090 PetscInt val; 4091 4092 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4093 if ((val == 1) || (val == (shift + 1))) { 4094 supportNew[q++] = depthOffset[1] + support[e]; 4095 } 4096 } 4097 supportNew[q] = cedge; 4098 4099 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4100 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4101 for (e = 0, q = 0; e < supportSize; ++e) { 4102 PetscInt val, edge; 4103 4104 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4105 if (val == 1) { 4106 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4107 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4108 supportNew[q++] = pMaxNew[1] + edge; 4109 } else if (val == -(shift + 1)) { 4110 supportNew[q++] = depthOffset[1] + support[e]; 4111 } 4112 } 4113 supportNew[q] = cedge; 4114 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4115 /* Cohesive edge: Old and new split vertex, punting on support */ 4116 coneNew[0] = newp; 4117 coneNew[1] = splitp; 4118 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4119 } else if (dep == dim-2) { 4120 /* Split old edge: old vertices in cone so no change */ 4121 /* Split new edge: new vertices in cone */ 4122 for (q = 0; q < coneSize; ++q) { 4123 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4124 4125 coneNew[q] = pMaxNew[dim-3] + v; 4126 } 4127 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4128 /* Split old edge: Faces in positive side cells and old split faces */ 4129 for (e = 0, q = 0; e < supportSize; ++e) { 4130 PetscInt val; 4131 4132 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4133 if ((val == dim-1) || (val == (shift + dim-1))) { 4134 supportNew[q++] = depthOffset[dim-1] + support[e]; 4135 } 4136 } 4137 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4138 /* Split new edge: Faces in negative side cells and new split faces */ 4139 for (e = 0, q = 0; e < supportSize; ++e) { 4140 PetscInt val, face; 4141 4142 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4143 if (val == dim-1) { 4144 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4145 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4146 supportNew[q++] = pMaxNew[dim-1] + face; 4147 } else if (val == -(shift + dim-1)) { 4148 supportNew[q++] = depthOffset[dim-1] + support[e]; 4149 } 4150 } 4151 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4152 } 4153 } 4154 } 4155 /* Step 6b: Replace split points in negative side cones */ 4156 for (sp = 0; sp < numSP; ++sp) { 4157 PetscInt dep = values[sp]; 4158 IS pIS; 4159 PetscInt numPoints; 4160 const PetscInt *points; 4161 4162 if (dep >= 0) continue; 4163 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4164 if (!pIS) continue; 4165 dep = -dep - shift; 4166 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4167 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4168 for (p = 0; p < numPoints; ++p) { 4169 const PetscInt oldp = points[p]; 4170 const PetscInt newp = depthOffset[dep] + oldp; 4171 const PetscInt *cone; 4172 PetscInt coneSize, c; 4173 PetscBool replaced = PETSC_FALSE; 4174 4175 /* Negative edge: replace split vertex */ 4176 /* Negative cell: replace split face */ 4177 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4178 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4179 for (c = 0; c < coneSize; ++c) { 4180 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4181 PetscInt csplitp, cp, val; 4182 4183 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4184 if (val == dep-1) { 4185 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4186 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4187 csplitp = pMaxNew[dep-1] + cp; 4188 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4189 replaced = PETSC_TRUE; 4190 } 4191 } 4192 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4193 } 4194 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4195 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4196 } 4197 /* Step 7: Stratify */ 4198 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4199 /* Step 8: Coordinates */ 4200 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4201 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4202 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4203 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4204 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4205 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4206 const PetscInt splitp = pMaxNew[0] + v; 4207 PetscInt dof, off, soff, d; 4208 4209 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4210 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4211 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4212 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4213 } 4214 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4215 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4216 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4217 /* Step 10: Labels */ 4218 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4219 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4220 for (dep = 0; dep <= depth; ++dep) { 4221 for (p = 0; p < numSplitPoints[dep]; ++p) { 4222 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4223 const PetscInt splitp = pMaxNew[dep] + p; 4224 PetscInt l; 4225 4226 for (l = 0; l < numLabels; ++l) { 4227 DMLabel mlabel; 4228 const char *lname; 4229 PetscInt val; 4230 4231 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4232 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4233 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4234 if (val >= 0) { 4235 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4236 if (dep == 0) { 4237 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4238 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4239 } 4240 } 4241 } 4242 } 4243 } 4244 for (sp = 0; sp < numSP; ++sp) { 4245 const PetscInt dep = values[sp]; 4246 4247 if ((dep < 0) || (dep > depth)) continue; 4248 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4249 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4250 } 4251 if (label) { 4252 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4253 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4254 } 4255 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4256 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4257 PetscFunctionReturn(0); 4258 } 4259 4260 #undef __FUNCT__ 4261 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4262 /*@C 4263 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4264 4265 Collective on dm 4266 4267 Input Parameters: 4268 + dm - The original DM 4269 - labelName - The label specifying the boundary faces (this could be auto-generated) 4270 4271 Output Parameters: 4272 - dmSplit - The new DM 4273 4274 Level: developer 4275 4276 .seealso: DMCreate() 4277 */ 4278 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4279 { 4280 DM sdm; 4281 PetscInt dim; 4282 PetscErrorCode ierr; 4283 4284 PetscFunctionBegin; 4285 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4286 PetscValidPointer(dmSplit, 4); 4287 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4288 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4289 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4290 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4291 switch (dim) { 4292 case 2: 4293 case 3: 4294 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4295 break; 4296 default: 4297 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4298 } 4299 *dmSplit = sdm; 4300 PetscFunctionReturn(0); 4301 } 4302 4303 #undef __FUNCT__ 4304 #define __FUNCT__ "DMLabelCohesiveComplete" 4305 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4306 { 4307 IS dimIS; 4308 const PetscInt *points; 4309 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4310 PetscErrorCode ierr; 4311 4312 PetscFunctionBegin; 4313 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4314 /* Cell orientation for face gives the side of the fault */ 4315 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4316 if (!dimIS) PetscFunctionReturn(0); 4317 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4318 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4319 for (p = 0; p < numPoints; ++p) { 4320 const PetscInt *support; 4321 PetscInt supportSize, s; 4322 4323 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4324 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4325 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4326 for (s = 0; s < supportSize; ++s) { 4327 const PetscInt *cone, *ornt; 4328 PetscInt coneSize, c; 4329 PetscBool pos = PETSC_TRUE; 4330 4331 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4332 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4333 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4334 for (c = 0; c < coneSize; ++c) { 4335 if (cone[c] == points[p]) { 4336 if (ornt[c] >= 0) { 4337 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4338 } else { 4339 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4340 pos = PETSC_FALSE; 4341 } 4342 break; 4343 } 4344 } 4345 if (c == coneSize) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]); 4346 /* Put faces touching the fault in the label */ 4347 for (c = 0; c < coneSize; ++c) { 4348 const PetscInt point = cone[c]; 4349 4350 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4351 if (val == -1) { 4352 PetscInt *closure = PETSC_NULL; 4353 PetscInt closureSize, cl; 4354 4355 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4356 for (cl = 0; cl < closureSize*2; cl += 2) { 4357 const PetscInt clp = closure[cl]; 4358 4359 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4360 if ((val >= 0) && (val < dim-1)) { 4361 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4362 break; 4363 } 4364 } 4365 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4366 } 4367 } 4368 } 4369 } 4370 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4371 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4372 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4373 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4374 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4375 if (!dimIS) PetscFunctionReturn(0); 4376 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4377 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4378 for (p = 0; p < numPoints; ++p) { 4379 PetscInt *star = PETSC_NULL; 4380 PetscInt starSize, s; 4381 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4382 4383 /* First mark cells connected to the fault */ 4384 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4385 while (again) { 4386 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4387 again = 0; 4388 for (s = 0; s < starSize*2; s += 2) { 4389 const PetscInt point = star[s]; 4390 const PetscInt *cone; 4391 PetscInt coneSize, c; 4392 4393 if ((point < cStart) || (point >= cEnd)) continue; 4394 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4395 if (val != -1) continue; 4396 again = 2; 4397 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4398 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4399 for (c = 0; c < coneSize; ++c) { 4400 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4401 if (val != -1) { 4402 if (abs(val) < shift) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 4403 if (val > 0) { 4404 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4405 } else { 4406 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4407 } 4408 again = 1; 4409 break; 4410 } 4411 } 4412 } 4413 } 4414 /* Classify the rest by cell membership */ 4415 for (s = 0; s < starSize*2; s += 2) { 4416 const PetscInt point = star[s]; 4417 4418 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4419 if (val == -1) { 4420 PetscInt *sstar = PETSC_NULL; 4421 PetscInt sstarSize, ss; 4422 PetscBool marked = PETSC_FALSE; 4423 4424 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4425 for (ss = 0; ss < sstarSize*2; ss += 2) { 4426 const PetscInt spoint = sstar[ss]; 4427 4428 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4429 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4430 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4431 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4432 if (val > 0) { 4433 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4434 } else { 4435 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4436 } 4437 marked = PETSC_TRUE; 4438 break; 4439 } 4440 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4441 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4442 } 4443 } 4444 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4445 } 4446 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4447 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4448 PetscFunctionReturn(0); 4449 } 4450 4451 #undef __FUNCT__ 4452 #define __FUNCT__ "DMPlexInterpolate_2D" 4453 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4454 { 4455 DM idm; 4456 DM_Plex *mesh; 4457 PetscHashIJ edgeTable; 4458 PetscInt *off; 4459 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4460 PetscInt numEdges, firstEdge, edge, e; 4461 PetscErrorCode ierr; 4462 4463 PetscFunctionBegin; 4464 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4465 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4466 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4467 numCells = cEnd - cStart; 4468 numVertices = vEnd - vStart; 4469 firstEdge = numCells + numVertices; 4470 numEdges = 0; 4471 /* Count edges using algorithm from CreateNeighborCSR */ 4472 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4473 if (off) { 4474 PetscInt numCorners = 0; 4475 4476 numEdges = off[numCells]/2; 4477 #if 0 4478 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4479 numEdges += 3*numCells - off[numCells]; 4480 #else 4481 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4482 for (c = cStart; c < cEnd; ++c) { 4483 PetscInt coneSize; 4484 4485 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4486 numCorners += coneSize; 4487 } 4488 numEdges += numCorners - off[numCells]; 4489 #endif 4490 } 4491 #if 0 4492 /* Check Euler characteristic V - E + F = 1 */ 4493 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4494 #endif 4495 /* Create interpolated mesh */ 4496 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4497 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4498 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4499 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4500 for (c = 0; c < numCells; ++c) { 4501 PetscInt numCorners; 4502 4503 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4504 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4505 } 4506 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4507 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4508 } 4509 ierr = DMSetUp(idm);CHKERRQ(ierr); 4510 /* Get edge cones from subsets of cell vertices */ 4511 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4512 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4513 4514 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4515 const PetscInt *cellFaces; 4516 PetscInt numCellFaces, faceSize, cf; 4517 4518 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4519 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4520 for (cf = 0; cf < numCellFaces; ++cf) { 4521 #if 1 4522 PetscHashIJKey key; 4523 4524 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4525 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4526 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4527 if (e < 0) { 4528 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4529 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4530 e = edge++; 4531 } 4532 #else 4533 PetscBool found = PETSC_FALSE; 4534 4535 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4536 for (e = firstEdge; e < edge; ++e) { 4537 const PetscInt *cone; 4538 4539 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4540 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4541 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4542 found = PETSC_TRUE; 4543 break; 4544 } 4545 } 4546 if (!found) { 4547 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4548 ++edge; 4549 } 4550 #endif 4551 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4552 } 4553 } 4554 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4555 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4556 ierr = PetscFree(off);CHKERRQ(ierr); 4557 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4558 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4559 mesh = (DM_Plex*) (idm)->data; 4560 /* Orient edges */ 4561 for (c = 0; c < numCells; ++c) { 4562 const PetscInt *cone = PETSC_NULL, *cellFaces; 4563 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4564 4565 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4566 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4567 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4568 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4569 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4570 for (cf = 0; cf < numCellFaces; ++cf) { 4571 const PetscInt *econe = PETSC_NULL; 4572 PetscInt esize; 4573 4574 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4575 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4576 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4577 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4578 /* Correctly oriented */ 4579 mesh->coneOrientations[coff+cf] = 0; 4580 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4581 /* Start at index 1, and reverse orientation */ 4582 mesh->coneOrientations[coff+cf] = -(1+1); 4583 } 4584 } 4585 } 4586 *dmInt = idm; 4587 PetscFunctionReturn(0); 4588 } 4589 4590 #undef __FUNCT__ 4591 #define __FUNCT__ "DMPlexInterpolate_3D" 4592 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4593 { 4594 DM idm, fdm; 4595 DM_Plex *mesh; 4596 PetscInt *off; 4597 const PetscInt numCorners = 4; 4598 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4599 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4600 PetscErrorCode ierr; 4601 4602 PetscFunctionBegin; 4603 { 4604 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4605 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4606 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4607 } 4608 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4609 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4610 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4611 numCells = cEnd - cStart; 4612 numVertices = vEnd - vStart; 4613 firstFace = numCells + numVertices; 4614 numFaces = 0; 4615 /* Count faces using algorithm from CreateNeighborCSR */ 4616 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4617 if (off) { 4618 numFaces = off[numCells]/2; 4619 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4620 numFaces += 4*numCells - off[numCells]; 4621 } 4622 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4623 firstEdge = firstFace + numFaces; 4624 numEdges = numVertices + numFaces - numCells - 1; 4625 /* Create interpolated mesh */ 4626 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4627 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4628 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4629 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4630 for (c = 0; c < numCells; ++c) { 4631 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4632 } 4633 for (f = firstFace; f < firstFace+numFaces; ++f) { 4634 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4635 } 4636 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4637 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4638 } 4639 ierr = DMSetUp(idm);CHKERRQ(ierr); 4640 /* Get face cones from subsets of cell vertices */ 4641 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4642 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4643 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4644 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4645 for (f = firstFace; f < firstFace+numFaces; ++f) { 4646 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4647 } 4648 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4649 for (c = 0, face = firstFace; c < numCells; ++c) { 4650 const PetscInt *cellFaces; 4651 PetscInt numCellFaces, faceSize, cf; 4652 4653 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4654 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4655 for (cf = 0; cf < numCellFaces; ++cf) { 4656 PetscBool found = PETSC_FALSE; 4657 4658 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4659 for (f = firstFace; f < face; ++f) { 4660 const PetscInt *cone = PETSC_NULL; 4661 4662 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4663 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4664 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4665 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4666 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4667 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4668 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4669 found = PETSC_TRUE; 4670 break; 4671 } 4672 } 4673 if (!found) { 4674 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4675 /* Save the vertices for orientation calculation */ 4676 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4677 ++face; 4678 } 4679 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4680 } 4681 } 4682 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4683 /* Get edge cones from subsets of face vertices */ 4684 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4685 const PetscInt *cellFaces; 4686 PetscInt numCellFaces, faceSize, cf; 4687 4688 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4689 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4690 for (cf = 0; cf < numCellFaces; ++cf) { 4691 PetscBool found = PETSC_FALSE; 4692 4693 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4694 for (e = firstEdge; e < edge; ++e) { 4695 const PetscInt *cone = PETSC_NULL; 4696 4697 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4698 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4699 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4700 found = PETSC_TRUE; 4701 break; 4702 } 4703 } 4704 if (!found) { 4705 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4706 ++edge; 4707 } 4708 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4709 } 4710 } 4711 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4712 ierr = PetscFree(off);CHKERRQ(ierr); 4713 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4714 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4715 mesh = (DM_Plex*) (idm)->data; 4716 /* Orient edges */ 4717 for (f = firstFace; f < firstFace+numFaces; ++f) { 4718 const PetscInt *cone, *cellFaces; 4719 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4720 4721 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4722 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4723 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4724 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4725 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4726 for (cf = 0; cf < numCellFaces; ++cf) { 4727 const PetscInt *econe; 4728 PetscInt esize; 4729 4730 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4731 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4732 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4733 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4734 /* Correctly oriented */ 4735 mesh->coneOrientations[coff+cf] = 0; 4736 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4737 /* Start at index 1, and reverse orientation */ 4738 mesh->coneOrientations[coff+cf] = -(1+1); 4739 } 4740 } 4741 } 4742 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4743 /* Orient faces */ 4744 for (c = 0; c < numCells; ++c) { 4745 const PetscInt *cone, *cellFaces; 4746 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4747 4748 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4749 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4750 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4751 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4752 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4753 for (cf = 0; cf < numCellFaces; ++cf) { 4754 PetscInt *origClosure = PETSC_NULL, *closure; 4755 PetscInt closureSize, i; 4756 4757 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4758 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4759 for (i = 4; i < 7; ++i) { 4760 if ((origClosure[i*2] < vStart) || (origClosure[i*2] >= vEnd)) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure point %D should be a vertex in [%D, %D)", origClosure[i*2], vStart, vEnd); 4761 } 4762 closure = &origClosure[4*2]; 4763 /* Remember that this is the orientation for edges, not vertices */ 4764 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4765 /* Correctly oriented */ 4766 mesh->coneOrientations[coff+cf] = 0; 4767 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4768 /* Shifted by 1 */ 4769 mesh->coneOrientations[coff+cf] = 1; 4770 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4771 /* Shifted by 2 */ 4772 mesh->coneOrientations[coff+cf] = 2; 4773 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4774 /* Start at edge 1, and reverse orientation */ 4775 mesh->coneOrientations[coff+cf] = -(1+1); 4776 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4777 /* Start at index 0, and reverse orientation */ 4778 mesh->coneOrientations[coff+cf] = -(0+1); 4779 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4780 /* Start at index 2, and reverse orientation */ 4781 mesh->coneOrientations[coff+cf] = -(2+1); 4782 } else SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Face %D did not match local face %D in cell %D for any orientation", cone[cf], cf, c); 4783 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4784 } 4785 } 4786 { 4787 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4788 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4789 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4790 } 4791 *dmInt = idm; 4792 PetscFunctionReturn(0); 4793 } 4794 4795 #undef __FUNCT__ 4796 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4797 /* 4798 This takes as input the common mesh generator output, a list of the vertices for each cell 4799 */ 4800 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4801 { 4802 PetscInt *cone, c, p; 4803 PetscErrorCode ierr; 4804 4805 PetscFunctionBegin; 4806 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4807 for (c = 0; c < numCells; ++c) { 4808 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4809 } 4810 ierr = DMSetUp(dm);CHKERRQ(ierr); 4811 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4812 for (c = 0; c < numCells; ++c) { 4813 for (p = 0; p < numCorners; ++p) { 4814 cone[p] = cells[c*numCorners+p]+numCells; 4815 } 4816 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4817 } 4818 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4819 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4820 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4821 PetscFunctionReturn(0); 4822 } 4823 4824 #undef __FUNCT__ 4825 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4826 /* 4827 This takes as input the coordinates for each vertex 4828 */ 4829 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4830 { 4831 PetscSection coordSection; 4832 Vec coordinates; 4833 PetscScalar *coords; 4834 PetscInt coordSize, v, d; 4835 PetscErrorCode ierr; 4836 4837 PetscFunctionBegin; 4838 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4839 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4840 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4841 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4842 for (v = numCells; v < numCells+numVertices; ++v) { 4843 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4844 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4845 } 4846 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4847 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4848 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4849 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4850 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4851 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4852 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4853 for (v = 0; v < numVertices; ++v) { 4854 for (d = 0; d < spaceDim; ++d) { 4855 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4856 } 4857 } 4858 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4859 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4860 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4861 PetscFunctionReturn(0); 4862 } 4863 4864 #undef __FUNCT__ 4865 #define __FUNCT__ "DMPlexCreateFromCellList" 4866 /* 4867 This takes as input the common mesh generator output, a list of the vertices for each cell 4868 */ 4869 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4870 { 4871 PetscErrorCode ierr; 4872 4873 PetscFunctionBegin; 4874 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4875 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4876 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4877 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4878 if (interpolate) { 4879 DM idm; 4880 4881 switch (dim) { 4882 case 2: 4883 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4884 case 3: 4885 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4886 default: 4887 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4888 } 4889 ierr = DMDestroy(dm);CHKERRQ(ierr); 4890 *dm = idm; 4891 } 4892 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4893 PetscFunctionReturn(0); 4894 } 4895 4896 #if defined(PETSC_HAVE_TRIANGLE) 4897 #include <triangle.h> 4898 4899 #undef __FUNCT__ 4900 #define __FUNCT__ "InitInput_Triangle" 4901 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4902 { 4903 PetscFunctionBegin; 4904 inputCtx->numberofpoints = 0; 4905 inputCtx->numberofpointattributes = 0; 4906 inputCtx->pointlist = PETSC_NULL; 4907 inputCtx->pointattributelist = PETSC_NULL; 4908 inputCtx->pointmarkerlist = PETSC_NULL; 4909 inputCtx->numberofsegments = 0; 4910 inputCtx->segmentlist = PETSC_NULL; 4911 inputCtx->segmentmarkerlist = PETSC_NULL; 4912 inputCtx->numberoftriangleattributes = 0; 4913 inputCtx->trianglelist = PETSC_NULL; 4914 inputCtx->numberofholes = 0; 4915 inputCtx->holelist = PETSC_NULL; 4916 inputCtx->numberofregions = 0; 4917 inputCtx->regionlist = PETSC_NULL; 4918 PetscFunctionReturn(0); 4919 } 4920 4921 #undef __FUNCT__ 4922 #define __FUNCT__ "InitOutput_Triangle" 4923 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4924 { 4925 PetscFunctionBegin; 4926 outputCtx->numberofpoints = 0; 4927 outputCtx->pointlist = PETSC_NULL; 4928 outputCtx->pointattributelist = PETSC_NULL; 4929 outputCtx->pointmarkerlist = PETSC_NULL; 4930 outputCtx->numberoftriangles = 0; 4931 outputCtx->trianglelist = PETSC_NULL; 4932 outputCtx->triangleattributelist = PETSC_NULL; 4933 outputCtx->neighborlist = PETSC_NULL; 4934 outputCtx->segmentlist = PETSC_NULL; 4935 outputCtx->segmentmarkerlist = PETSC_NULL; 4936 outputCtx->numberofedges = 0; 4937 outputCtx->edgelist = PETSC_NULL; 4938 outputCtx->edgemarkerlist = PETSC_NULL; 4939 PetscFunctionReturn(0); 4940 } 4941 4942 #undef __FUNCT__ 4943 #define __FUNCT__ "FiniOutput_Triangle" 4944 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4945 { 4946 PetscFunctionBegin; 4947 free(outputCtx->pointmarkerlist); 4948 free(outputCtx->edgelist); 4949 free(outputCtx->edgemarkerlist); 4950 free(outputCtx->trianglelist); 4951 free(outputCtx->neighborlist); 4952 PetscFunctionReturn(0); 4953 } 4954 4955 #undef __FUNCT__ 4956 #define __FUNCT__ "DMPlexGenerate_Triangle" 4957 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4958 { 4959 MPI_Comm comm = ((PetscObject) boundary)->comm; 4960 PetscInt dim = 2; 4961 const PetscBool createConvexHull = PETSC_FALSE; 4962 const PetscBool constrained = PETSC_FALSE; 4963 struct triangulateio in; 4964 struct triangulateio out; 4965 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4966 PetscMPIInt rank; 4967 PetscErrorCode ierr; 4968 4969 PetscFunctionBegin; 4970 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4971 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4972 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4973 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4974 4975 in.numberofpoints = vEnd - vStart; 4976 if (in.numberofpoints > 0) { 4977 PetscSection coordSection; 4978 Vec coordinates; 4979 PetscScalar *array; 4980 4981 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4982 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4983 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4984 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4985 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4986 for (v = vStart; v < vEnd; ++v) { 4987 const PetscInt idx = v - vStart; 4988 PetscInt off, d; 4989 4990 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4991 for (d = 0; d < dim; ++d) { 4992 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4993 } 4994 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4995 } 4996 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4997 } 4998 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4999 in.numberofsegments = eEnd - eStart; 5000 if (in.numberofsegments > 0) { 5001 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 5002 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 5003 for (e = eStart; e < eEnd; ++e) { 5004 const PetscInt idx = e - eStart; 5005 const PetscInt *cone; 5006 5007 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 5008 5009 in.segmentlist[idx*2+0] = cone[0] - vStart; 5010 in.segmentlist[idx*2+1] = cone[1] - vStart; 5011 5012 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5013 } 5014 } 5015 #if 0 /* Do not currently support holes */ 5016 PetscReal *holeCoords; 5017 PetscInt h, d; 5018 5019 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5020 if (in.numberofholes > 0) { 5021 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5022 for (h = 0; h < in.numberofholes; ++h) { 5023 for (d = 0; d < dim; ++d) { 5024 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5025 } 5026 } 5027 } 5028 #endif 5029 if (!rank) { 5030 char args[32]; 5031 5032 /* Take away 'Q' for verbose output */ 5033 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5034 if (createConvexHull) { 5035 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5036 } 5037 if (constrained) { 5038 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5039 } 5040 triangulate(args, &in, &out, PETSC_NULL); 5041 } 5042 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5043 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5044 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5045 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5046 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5047 5048 { 5049 const PetscInt numCorners = 3; 5050 const PetscInt numCells = out.numberoftriangles; 5051 const PetscInt numVertices = out.numberofpoints; 5052 const int *cells = out.trianglelist; 5053 const double *meshCoords = out.pointlist; 5054 5055 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5056 /* Set labels */ 5057 for (v = 0; v < numVertices; ++v) { 5058 if (out.pointmarkerlist[v]) { 5059 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5060 } 5061 } 5062 if (interpolate) { 5063 for (e = 0; e < out.numberofedges; e++) { 5064 if (out.edgemarkerlist[e]) { 5065 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5066 const PetscInt *edges; 5067 PetscInt numEdges; 5068 5069 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5070 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5071 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5072 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5073 } 5074 } 5075 } 5076 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5077 } 5078 #if 0 /* Do not currently support holes */ 5079 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5080 #endif 5081 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5082 PetscFunctionReturn(0); 5083 } 5084 5085 #undef __FUNCT__ 5086 #define __FUNCT__ "DMPlexRefine_Triangle" 5087 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5088 { 5089 MPI_Comm comm = ((PetscObject) dm)->comm; 5090 PetscInt dim = 2; 5091 struct triangulateio in; 5092 struct triangulateio out; 5093 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5094 PetscMPIInt rank; 5095 PetscErrorCode ierr; 5096 5097 PetscFunctionBegin; 5098 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5099 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5100 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5101 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5102 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5103 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5104 5105 in.numberofpoints = vEnd - vStart; 5106 if (in.numberofpoints > 0) { 5107 PetscSection coordSection; 5108 Vec coordinates; 5109 PetscScalar *array; 5110 5111 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5112 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5113 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5114 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5115 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5116 for (v = vStart; v < vEnd; ++v) { 5117 const PetscInt idx = v - vStart; 5118 PetscInt off, d; 5119 5120 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5121 for (d = 0; d < dim; ++d) { 5122 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5123 } 5124 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5125 } 5126 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5127 } 5128 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5129 5130 in.numberofcorners = 3; 5131 in.numberoftriangles = cEnd - cStart; 5132 5133 in.trianglearealist = (double*) maxVolumes; 5134 if (in.numberoftriangles > 0) { 5135 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5136 for (c = cStart; c < cEnd; ++c) { 5137 const PetscInt idx = c - cStart; 5138 PetscInt *closure = PETSC_NULL; 5139 PetscInt closureSize; 5140 5141 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5142 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5143 for (v = 0; v < 3; ++v) { 5144 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5145 } 5146 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5147 } 5148 } 5149 /* TODO: Segment markers are missing on input */ 5150 #if 0 /* Do not currently support holes */ 5151 PetscReal *holeCoords; 5152 PetscInt h, d; 5153 5154 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5155 if (in.numberofholes > 0) { 5156 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5157 for (h = 0; h < in.numberofholes; ++h) { 5158 for (d = 0; d < dim; ++d) { 5159 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5160 } 5161 } 5162 } 5163 #endif 5164 if (!rank) { 5165 char args[32]; 5166 5167 /* Take away 'Q' for verbose output */ 5168 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5169 triangulate(args, &in, &out, PETSC_NULL); 5170 } 5171 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5172 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5173 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5174 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5175 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5176 5177 { 5178 const PetscInt numCorners = 3; 5179 const PetscInt numCells = out.numberoftriangles; 5180 const PetscInt numVertices = out.numberofpoints; 5181 const int *cells = out.trianglelist; 5182 const double *meshCoords = out.pointlist; 5183 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5184 5185 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5186 /* Set labels */ 5187 for (v = 0; v < numVertices; ++v) { 5188 if (out.pointmarkerlist[v]) { 5189 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5190 } 5191 } 5192 if (interpolate) { 5193 PetscInt e; 5194 5195 for (e = 0; e < out.numberofedges; e++) { 5196 if (out.edgemarkerlist[e]) { 5197 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5198 const PetscInt *edges; 5199 PetscInt numEdges; 5200 5201 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5202 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5203 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5204 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5205 } 5206 } 5207 } 5208 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5209 } 5210 #if 0 /* Do not currently support holes */ 5211 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5212 #endif 5213 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5214 PetscFunctionReturn(0); 5215 } 5216 #endif 5217 5218 #if defined(PETSC_HAVE_TETGEN) 5219 #include <tetgen.h> 5220 #undef __FUNCT__ 5221 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5222 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5223 { 5224 MPI_Comm comm = ((PetscObject) boundary)->comm; 5225 const PetscInt dim = 3; 5226 ::tetgenio in; 5227 ::tetgenio out; 5228 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5229 PetscMPIInt rank; 5230 PetscErrorCode ierr; 5231 5232 PetscFunctionBegin; 5233 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5234 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5235 in.numberofpoints = vEnd - vStart; 5236 if (in.numberofpoints > 0) { 5237 PetscSection coordSection; 5238 Vec coordinates; 5239 PetscScalar *array; 5240 5241 in.pointlist = new double[in.numberofpoints*dim]; 5242 in.pointmarkerlist = new int[in.numberofpoints]; 5243 5244 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5245 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5246 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5247 for (v = vStart; v < vEnd; ++v) { 5248 const PetscInt idx = v - vStart; 5249 PetscInt off, d; 5250 5251 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5252 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5253 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5254 } 5255 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5256 } 5257 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5258 5259 in.numberoffacets = fEnd - fStart; 5260 if (in.numberoffacets > 0) { 5261 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5262 in.facetmarkerlist = new int[in.numberoffacets]; 5263 for (f = fStart; f < fEnd; ++f) { 5264 const PetscInt idx = f - fStart; 5265 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5266 5267 in.facetlist[idx].numberofpolygons = 1; 5268 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5269 in.facetlist[idx].numberofholes = 0; 5270 in.facetlist[idx].holelist = NULL; 5271 5272 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5273 for (p = 0; p < numPoints*2; p += 2) { 5274 const PetscInt point = points[p]; 5275 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5276 } 5277 5278 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5279 poly->numberofvertices = numVertices; 5280 poly->vertexlist = new int[poly->numberofvertices]; 5281 for (v = 0; v < numVertices; ++v) { 5282 const PetscInt vIdx = points[v] - vStart; 5283 poly->vertexlist[v] = vIdx; 5284 } 5285 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5286 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5287 } 5288 } 5289 if (!rank) { 5290 char args[32]; 5291 5292 /* Take away 'Q' for verbose output */ 5293 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5294 ::tetrahedralize(args, &in, &out); 5295 } 5296 { 5297 const PetscInt numCorners = 4; 5298 const PetscInt numCells = out.numberoftetrahedra; 5299 const PetscInt numVertices = out.numberofpoints; 5300 const int *cells = out.tetrahedronlist; 5301 const double *meshCoords = out.pointlist; 5302 5303 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5304 /* Set labels */ 5305 for (v = 0; v < numVertices; ++v) { 5306 if (out.pointmarkerlist[v]) { 5307 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5308 } 5309 } 5310 if (interpolate) { 5311 PetscInt e; 5312 5313 for (e = 0; e < out.numberofedges; e++) { 5314 if (out.edgemarkerlist[e]) { 5315 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5316 const PetscInt *edges; 5317 PetscInt numEdges; 5318 5319 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5320 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5321 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5322 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5323 } 5324 } 5325 for (f = 0; f < out.numberoftrifaces; f++) { 5326 if (out.trifacemarkerlist[f]) { 5327 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5328 const PetscInt *faces; 5329 PetscInt numFaces; 5330 5331 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5332 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5333 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5334 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5335 } 5336 } 5337 } 5338 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5339 } 5340 PetscFunctionReturn(0); 5341 } 5342 5343 #undef __FUNCT__ 5344 #define __FUNCT__ "DMPlexRefine_Tetgen" 5345 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5346 { 5347 MPI_Comm comm = ((PetscObject) dm)->comm; 5348 const PetscInt dim = 3; 5349 ::tetgenio in; 5350 ::tetgenio out; 5351 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5352 PetscMPIInt rank; 5353 PetscErrorCode ierr; 5354 5355 PetscFunctionBegin; 5356 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5357 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5358 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5359 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5360 5361 in.numberofpoints = vEnd - vStart; 5362 if (in.numberofpoints > 0) { 5363 PetscSection coordSection; 5364 Vec coordinates; 5365 PetscScalar *array; 5366 5367 in.pointlist = new double[in.numberofpoints*dim]; 5368 in.pointmarkerlist = new int[in.numberofpoints]; 5369 5370 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5371 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5372 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5373 for (v = vStart; v < vEnd; ++v) { 5374 const PetscInt idx = v - vStart; 5375 PetscInt off, d; 5376 5377 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5378 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5379 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5380 } 5381 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5382 } 5383 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5384 5385 in.numberofcorners = 4; 5386 in.numberoftetrahedra = cEnd - cStart; 5387 in.tetrahedronvolumelist = (double*) maxVolumes; 5388 if (in.numberoftetrahedra > 0) { 5389 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5390 for (c = cStart; c < cEnd; ++c) { 5391 const PetscInt idx = c - cStart; 5392 PetscInt *closure = PETSC_NULL; 5393 PetscInt closureSize; 5394 5395 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5396 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5397 for (v = 0; v < 4; ++v) { 5398 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5399 } 5400 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5401 } 5402 } 5403 /* TODO: Put in boundary faces with markers */ 5404 if (!rank) { 5405 char args[32]; 5406 5407 /* Take away 'Q' for verbose output */ 5408 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5409 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5410 ::tetrahedralize(args, &in, &out); 5411 } 5412 in.tetrahedronvolumelist = NULL; 5413 5414 { 5415 const PetscInt numCorners = 4; 5416 const PetscInt numCells = out.numberoftetrahedra; 5417 const PetscInt numVertices = out.numberofpoints; 5418 const int *cells = out.tetrahedronlist; 5419 const double *meshCoords = out.pointlist; 5420 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5421 5422 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5423 /* Set labels */ 5424 for (v = 0; v < numVertices; ++v) { 5425 if (out.pointmarkerlist[v]) { 5426 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5427 } 5428 } 5429 if (interpolate) { 5430 PetscInt e, f; 5431 5432 for (e = 0; e < out.numberofedges; e++) { 5433 if (out.edgemarkerlist[e]) { 5434 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5435 const PetscInt *edges; 5436 PetscInt numEdges; 5437 5438 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5439 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5440 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5441 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5442 } 5443 } 5444 for (f = 0; f < out.numberoftrifaces; f++) { 5445 if (out.trifacemarkerlist[f]) { 5446 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5447 const PetscInt *faces; 5448 PetscInt numFaces; 5449 5450 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5451 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5452 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5453 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5454 } 5455 } 5456 } 5457 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5458 } 5459 PetscFunctionReturn(0); 5460 } 5461 #endif 5462 5463 #if defined(PETSC_HAVE_CTETGEN) 5464 #include "ctetgen.h" 5465 5466 #undef __FUNCT__ 5467 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5468 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5469 { 5470 MPI_Comm comm = ((PetscObject) boundary)->comm; 5471 const PetscInt dim = 3; 5472 PLC *in, *out; 5473 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5474 PetscMPIInt rank; 5475 PetscErrorCode ierr; 5476 5477 PetscFunctionBegin; 5478 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5479 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5480 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5481 ierr = PLCCreate(&in);CHKERRQ(ierr); 5482 ierr = PLCCreate(&out);CHKERRQ(ierr); 5483 5484 in->numberofpoints = vEnd - vStart; 5485 if (in->numberofpoints > 0) { 5486 PetscSection coordSection; 5487 Vec coordinates; 5488 PetscScalar *array; 5489 5490 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5491 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5492 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5493 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5494 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5495 for (v = vStart; v < vEnd; ++v) { 5496 const PetscInt idx = v - vStart; 5497 PetscInt off, d, m; 5498 5499 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5500 for (d = 0; d < dim; ++d) { 5501 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5502 } 5503 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5504 5505 in->pointmarkerlist[idx] = (int) m; 5506 } 5507 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5508 } 5509 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5510 5511 in->numberoffacets = fEnd - fStart; 5512 if (in->numberoffacets > 0) { 5513 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5514 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5515 for (f = fStart; f < fEnd; ++f) { 5516 const PetscInt idx = f - fStart; 5517 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5518 polygon *poly; 5519 5520 in->facetlist[idx].numberofpolygons = 1; 5521 5522 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5523 5524 in->facetlist[idx].numberofholes = 0; 5525 in->facetlist[idx].holelist = PETSC_NULL; 5526 5527 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5528 for (p = 0; p < numPoints*2; p += 2) { 5529 const PetscInt point = points[p]; 5530 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5531 } 5532 5533 poly = in->facetlist[idx].polygonlist; 5534 poly->numberofvertices = numVertices; 5535 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5536 for (v = 0; v < numVertices; ++v) { 5537 const PetscInt vIdx = points[v] - vStart; 5538 poly->vertexlist[v] = vIdx; 5539 } 5540 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5541 in->facetmarkerlist[idx] = (int) m; 5542 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5543 } 5544 } 5545 if (!rank) { 5546 TetGenOpts t; 5547 5548 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5549 t.in = boundary; /* Should go away */ 5550 t.plc = 1; 5551 t.quality = 1; 5552 t.edgesout = 1; 5553 t.zeroindex = 1; 5554 t.quiet = 1; 5555 t.verbose = verbose; 5556 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5557 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5558 } 5559 { 5560 const PetscInt numCorners = 4; 5561 const PetscInt numCells = out->numberoftetrahedra; 5562 const PetscInt numVertices = out->numberofpoints; 5563 const int *cells = out->tetrahedronlist; 5564 const double *meshCoords = out->pointlist; 5565 5566 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5567 /* Set labels */ 5568 for (v = 0; v < numVertices; ++v) { 5569 if (out->pointmarkerlist[v]) { 5570 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5571 } 5572 } 5573 if (interpolate) { 5574 PetscInt e; 5575 5576 for (e = 0; e < out->numberofedges; e++) { 5577 if (out->edgemarkerlist[e]) { 5578 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5579 const PetscInt *edges; 5580 PetscInt numEdges; 5581 5582 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5583 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5584 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5585 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5586 } 5587 } 5588 for (f = 0; f < out->numberoftrifaces; f++) { 5589 if (out->trifacemarkerlist[f]) { 5590 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5591 const PetscInt *faces; 5592 PetscInt numFaces; 5593 5594 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5595 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5596 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5597 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5598 } 5599 } 5600 } 5601 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5602 } 5603 5604 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5605 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5606 PetscFunctionReturn(0); 5607 } 5608 5609 #undef __FUNCT__ 5610 #define __FUNCT__ "DMPlexRefine_CTetgen" 5611 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5612 { 5613 MPI_Comm comm = ((PetscObject) dm)->comm; 5614 const PetscInt dim = 3; 5615 PLC *in, *out; 5616 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5617 PetscMPIInt rank; 5618 PetscErrorCode ierr; 5619 5620 PetscFunctionBegin; 5621 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5622 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5623 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5624 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5625 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5626 ierr = PLCCreate(&in);CHKERRQ(ierr); 5627 ierr = PLCCreate(&out);CHKERRQ(ierr); 5628 5629 in->numberofpoints = vEnd - vStart; 5630 if (in->numberofpoints > 0) { 5631 PetscSection coordSection; 5632 Vec coordinates; 5633 PetscScalar *array; 5634 5635 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5636 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5637 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5638 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5639 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5640 for (v = vStart; v < vEnd; ++v) { 5641 const PetscInt idx = v - vStart; 5642 PetscInt off, d, m; 5643 5644 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5645 for (d = 0; d < dim; ++d) { 5646 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5647 } 5648 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5649 5650 in->pointmarkerlist[idx] = (int) m; 5651 } 5652 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5653 } 5654 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5655 5656 in->numberofcorners = 4; 5657 in->numberoftetrahedra = cEnd - cStart; 5658 in->tetrahedronvolumelist = maxVolumes; 5659 if (in->numberoftetrahedra > 0) { 5660 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5661 for (c = cStart; c < cEnd; ++c) { 5662 const PetscInt idx = c - cStart; 5663 PetscInt *closure = PETSC_NULL; 5664 PetscInt closureSize; 5665 5666 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5667 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5668 for (v = 0; v < 4; ++v) { 5669 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5670 } 5671 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5672 } 5673 } 5674 if (!rank) { 5675 TetGenOpts t; 5676 5677 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5678 5679 t.in = dm; /* Should go away */ 5680 t.refine = 1; 5681 t.varvolume = 1; 5682 t.quality = 1; 5683 t.edgesout = 1; 5684 t.zeroindex = 1; 5685 t.quiet = 1; 5686 t.verbose = verbose; /* Change this */ 5687 5688 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5689 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5690 } 5691 { 5692 const PetscInt numCorners = 4; 5693 const PetscInt numCells = out->numberoftetrahedra; 5694 const PetscInt numVertices = out->numberofpoints; 5695 const int *cells = out->tetrahedronlist; 5696 const double *meshCoords = out->pointlist; 5697 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5698 5699 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5700 /* Set labels */ 5701 for (v = 0; v < numVertices; ++v) { 5702 if (out->pointmarkerlist[v]) { 5703 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5704 } 5705 } 5706 if (interpolate) { 5707 PetscInt e, f; 5708 5709 for (e = 0; e < out->numberofedges; e++) { 5710 if (out->edgemarkerlist[e]) { 5711 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5712 const PetscInt *edges; 5713 PetscInt numEdges; 5714 5715 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5716 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5717 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5718 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5719 } 5720 } 5721 for (f = 0; f < out->numberoftrifaces; f++) { 5722 if (out->trifacemarkerlist[f]) { 5723 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5724 const PetscInt *faces; 5725 PetscInt numFaces; 5726 5727 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5728 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5729 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5730 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5731 } 5732 } 5733 } 5734 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5735 } 5736 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5737 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5738 PetscFunctionReturn(0); 5739 } 5740 #endif 5741 5742 #undef __FUNCT__ 5743 #define __FUNCT__ "DMPlexGenerate" 5744 /*@C 5745 DMPlexGenerate - Generates a mesh. 5746 5747 Not Collective 5748 5749 Input Parameters: 5750 + boundary - The DMPlex boundary object 5751 . name - The mesh generation package name 5752 - interpolate - Flag to create intermediate mesh elements 5753 5754 Output Parameter: 5755 . mesh - The DMPlex object 5756 5757 Level: intermediate 5758 5759 .keywords: mesh, elements 5760 .seealso: DMPlexCreate(), DMRefine() 5761 @*/ 5762 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5763 { 5764 PetscInt dim; 5765 char genname[1024]; 5766 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5767 PetscErrorCode ierr; 5768 5769 PetscFunctionBegin; 5770 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5771 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5772 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5773 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5774 if (flg) name = genname; 5775 if (name) { 5776 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5777 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5778 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5779 } 5780 switch (dim) { 5781 case 1: 5782 if (!name || isTriangle) { 5783 #if defined(PETSC_HAVE_TRIANGLE) 5784 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5785 #else 5786 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5787 #endif 5788 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5789 break; 5790 case 2: 5791 if (!name || isCTetgen) { 5792 #if defined(PETSC_HAVE_CTETGEN) 5793 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5794 #else 5795 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5796 #endif 5797 } else if (isTetgen) { 5798 #if defined(PETSC_HAVE_TETGEN) 5799 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5800 #else 5801 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5802 #endif 5803 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5804 break; 5805 default: 5806 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5807 } 5808 PetscFunctionReturn(0); 5809 } 5810 5811 typedef PetscInt CellRefiner; 5812 5813 #undef __FUNCT__ 5814 #define __FUNCT__ "GetDepthStart_Private" 5815 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5816 { 5817 PetscFunctionBegin; 5818 if (cStart) *cStart = 0; 5819 if (vStart) *vStart = depthSize[depth]; 5820 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5821 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5822 PetscFunctionReturn(0); 5823 } 5824 5825 #undef __FUNCT__ 5826 #define __FUNCT__ "GetDepthEnd_Private" 5827 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5828 { 5829 PetscFunctionBegin; 5830 if (cEnd) *cEnd = depthSize[depth]; 5831 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5832 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5833 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5834 PetscFunctionReturn(0); 5835 } 5836 5837 #undef __FUNCT__ 5838 #define __FUNCT__ "CellRefinerGetSizes" 5839 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5840 { 5841 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5842 PetscErrorCode ierr; 5843 5844 PetscFunctionBegin; 5845 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5846 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5847 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5848 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5849 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5850 switch (refiner) { 5851 case 1: 5852 /* Simplicial 2D */ 5853 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5854 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5855 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5856 break; 5857 case 3: 5858 /* Hybrid 2D */ 5859 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5860 cMax = PetscMin(cEnd, cMax); 5861 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5862 fMax = PetscMin(fEnd, fMax); 5863 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5864 depthSize[1] = 2*(fMax - fStart) + 3*(cMax - cStart) + (fEnd - fMax) + (cEnd - cMax); /* Every interior face is split into 2 faces, 3 faces are added for each interior cell, and one in each hybrid cell */ 5865 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5866 break; 5867 case 2: 5868 /* Hex 2D */ 5869 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5870 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5871 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5872 break; 5873 default: 5874 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5875 } 5876 PetscFunctionReturn(0); 5877 } 5878 5879 #undef __FUNCT__ 5880 #define __FUNCT__ "CellRefinerSetConeSizes" 5881 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5882 { 5883 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5884 PetscErrorCode ierr; 5885 5886 PetscFunctionBegin; 5887 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5888 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5889 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5890 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5891 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5892 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5893 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5894 switch (refiner) { 5895 case 1: 5896 /* Simplicial 2D */ 5897 /* All cells have 3 faces */ 5898 for (c = cStart; c < cEnd; ++c) { 5899 for (r = 0; r < 4; ++r) { 5900 const PetscInt newp = (c - cStart)*4 + r; 5901 5902 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5903 } 5904 } 5905 /* Split faces have 2 vertices and the same cells as the parent */ 5906 for (f = fStart; f < fEnd; ++f) { 5907 for (r = 0; r < 2; ++r) { 5908 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5909 PetscInt size; 5910 5911 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5912 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5913 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5914 } 5915 } 5916 /* Interior faces have 2 vertices and 2 cells */ 5917 for (c = cStart; c < cEnd; ++c) { 5918 for (r = 0; r < 3; ++r) { 5919 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5920 5921 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5922 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5923 } 5924 } 5925 /* Old vertices have identical supports */ 5926 for (v = vStart; v < vEnd; ++v) { 5927 const PetscInt newp = vStartNew + (v - vStart); 5928 PetscInt size; 5929 5930 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5931 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5932 } 5933 /* Face vertices have 2 + cells*2 supports */ 5934 for (f = fStart; f < fEnd; ++f) { 5935 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5936 PetscInt size; 5937 5938 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5939 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5940 } 5941 break; 5942 case 2: 5943 /* Hex 2D */ 5944 /* All cells have 4 faces */ 5945 for (c = cStart; c < cEnd; ++c) { 5946 for (r = 0; r < 4; ++r) { 5947 const PetscInt newp = (c - cStart)*4 + r; 5948 5949 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5950 } 5951 } 5952 /* Split faces have 2 vertices and the same cells as the parent */ 5953 for (f = fStart; f < fEnd; ++f) { 5954 for (r = 0; r < 2; ++r) { 5955 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5956 PetscInt size; 5957 5958 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5959 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5960 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5961 } 5962 } 5963 /* Interior faces have 2 vertices and 2 cells */ 5964 for (c = cStart; c < cEnd; ++c) { 5965 for (r = 0; r < 4; ++r) { 5966 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5967 5968 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5969 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5970 } 5971 } 5972 /* Old vertices have identical supports */ 5973 for (v = vStart; v < vEnd; ++v) { 5974 const PetscInt newp = vStartNew + (v - vStart); 5975 PetscInt size; 5976 5977 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5978 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5979 } 5980 /* Face vertices have 2 + cells supports */ 5981 for (f = fStart; f < fEnd; ++f) { 5982 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5983 PetscInt size; 5984 5985 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5986 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5987 } 5988 /* Cell vertices have 4 supports */ 5989 for (c = cStart; c < cEnd; ++c) { 5990 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5991 5992 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5993 } 5994 break; 5995 case 3: 5996 /* Hybrid 2D */ 5997 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5998 cMax = PetscMin(cEnd, cMax); 5999 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6000 fMax = PetscMin(fEnd, fMax); 6001 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6002 /* Interior cells have 3 faces */ 6003 for (c = cStart; c < cMax; ++c) { 6004 for (r = 0; r < 4; ++r) { 6005 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 6006 6007 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 6008 } 6009 } 6010 /* Hybrid cells have 4 faces */ 6011 for (c = cMax; c < cEnd; ++c) { 6012 for (r = 0; r < 2; ++r) { 6013 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6014 6015 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6016 } 6017 } 6018 /* Interior split faces have 2 vertices and the same cells as the parent */ 6019 for (f = fStart; f < fMax; ++f) { 6020 for (r = 0; r < 2; ++r) { 6021 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6022 PetscInt size; 6023 6024 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6025 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6026 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6027 } 6028 } 6029 /* Interior cell faces have 2 vertices and 2 cells */ 6030 for (c = cStart; c < cMax; ++c) { 6031 for (r = 0; r < 3; ++r) { 6032 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6033 6034 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6035 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6036 } 6037 } 6038 /* Hybrid faces have 2 vertices and the same cells */ 6039 for (f = fMax; f < fEnd; ++f) { 6040 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6041 PetscInt size; 6042 6043 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6044 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6045 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6046 } 6047 /* Hybrid cell faces have 2 vertices and 2 cells */ 6048 for (c = cMax; c < cEnd; ++c) { 6049 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6050 6051 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6052 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6053 } 6054 /* Old vertices have identical supports */ 6055 for (v = vStart; v < vEnd; ++v) { 6056 const PetscInt newp = vStartNew + (v - vStart); 6057 PetscInt size; 6058 6059 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6060 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6061 } 6062 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6063 for (f = fStart; f < fMax; ++f) { 6064 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6065 const PetscInt *support; 6066 PetscInt size, newSize = 2, s; 6067 6068 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6069 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6070 for (s = 0; s < size; ++s) { 6071 if (support[s] >= cMax) newSize += 1; 6072 else newSize += 2; 6073 } 6074 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6075 } 6076 break; 6077 default: 6078 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6079 } 6080 PetscFunctionReturn(0); 6081 } 6082 6083 #undef __FUNCT__ 6084 #define __FUNCT__ "CellRefinerSetCones" 6085 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6086 { 6087 PetscInt depth, cStart, cEnd, cMax, cStartNew, cEndNew, c, vStart, vEnd, vMax, vStartNew, vEndNew, v, fStart, fEnd, fMax, fStartNew, fEndNew, f, eStart, eEnd, eMax, eStartNew, eEndNew, r, p; 6088 PetscInt maxSupportSize, *supportRef; 6089 PetscErrorCode ierr; 6090 6091 PetscFunctionBegin; 6092 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6093 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6094 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6095 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6096 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6097 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6098 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6099 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6100 switch (refiner) { 6101 case 1: 6102 /* Simplicial 2D */ 6103 /* 6104 2 6105 |\ 6106 | \ 6107 | \ 6108 | \ 6109 | C \ 6110 | \ 6111 | \ 6112 2---1---1 6113 |\ D / \ 6114 | 2 0 \ 6115 |A \ / B \ 6116 0---0-------1 6117 */ 6118 /* All cells have 3 faces */ 6119 for (c = cStart; c < cEnd; ++c) { 6120 const PetscInt newp = cStartNew + (c - cStart)*4; 6121 const PetscInt *cone, *ornt; 6122 PetscInt coneNew[3], orntNew[3]; 6123 6124 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6125 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6126 /* A triangle */ 6127 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6128 orntNew[0] = ornt[0]; 6129 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6130 orntNew[1] = -2; 6131 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6132 orntNew[2] = ornt[2]; 6133 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6134 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6135 #if 1 6136 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6137 for (p = 0; p < 3; ++p) { 6138 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6139 } 6140 #endif 6141 /* B triangle */ 6142 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6143 orntNew[0] = ornt[0]; 6144 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6145 orntNew[1] = ornt[1]; 6146 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6147 orntNew[2] = -2; 6148 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6149 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6150 #if 1 6151 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6152 for (p = 0; p < 3; ++p) { 6153 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6154 } 6155 #endif 6156 /* C triangle */ 6157 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6158 orntNew[0] = -2; 6159 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6160 orntNew[1] = ornt[1]; 6161 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6162 orntNew[2] = ornt[2]; 6163 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6164 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6165 #if 1 6166 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6167 for (p = 0; p < 3; ++p) { 6168 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6169 } 6170 #endif 6171 /* D triangle */ 6172 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6173 orntNew[0] = 0; 6174 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6175 orntNew[1] = 0; 6176 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6177 orntNew[2] = 0; 6178 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6179 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6180 #if 1 6181 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6182 for (p = 0; p < 3; ++p) { 6183 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6184 } 6185 #endif 6186 } 6187 /* Split faces have 2 vertices and the same cells as the parent */ 6188 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6189 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6190 for (f = fStart; f < fEnd; ++f) { 6191 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6192 6193 for (r = 0; r < 2; ++r) { 6194 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6195 const PetscInt *cone, *support; 6196 PetscInt coneNew[2], coneSize, c, supportSize, s; 6197 6198 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6199 coneNew[0] = vStartNew + (cone[0] - vStart); 6200 coneNew[1] = vStartNew + (cone[1] - vStart); 6201 coneNew[(r+1)%2] = newv; 6202 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6203 #if 1 6204 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6205 for (p = 0; p < 2; ++p) { 6206 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6207 } 6208 #endif 6209 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6210 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6211 for (s = 0; s < supportSize; ++s) { 6212 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6213 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6214 for (c = 0; c < coneSize; ++c) { 6215 if (cone[c] == f) break; 6216 } 6217 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6218 } 6219 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6220 #if 1 6221 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6222 for (p = 0; p < supportSize; ++p) { 6223 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6224 } 6225 #endif 6226 } 6227 } 6228 /* Interior faces have 2 vertices and 2 cells */ 6229 for (c = cStart; c < cEnd; ++c) { 6230 const PetscInt *cone; 6231 6232 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6233 for (r = 0; r < 3; ++r) { 6234 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6235 PetscInt coneNew[2]; 6236 PetscInt supportNew[2]; 6237 6238 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6239 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6240 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6241 #if 1 6242 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6243 for (p = 0; p < 2; ++p) { 6244 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6245 } 6246 #endif 6247 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6248 supportNew[1] = (c - cStart)*4 + 3; 6249 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6250 #if 1 6251 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6252 for (p = 0; p < 2; ++p) { 6253 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6254 } 6255 #endif 6256 } 6257 } 6258 /* Old vertices have identical supports */ 6259 for (v = vStart; v < vEnd; ++v) { 6260 const PetscInt newp = vStartNew + (v - vStart); 6261 const PetscInt *support, *cone; 6262 PetscInt size, s; 6263 6264 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6265 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6266 for (s = 0; s < size; ++s) { 6267 PetscInt r = 0; 6268 6269 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6270 if (cone[1] == v) r = 1; 6271 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6272 } 6273 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6274 #if 1 6275 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6276 for (p = 0; p < size; ++p) { 6277 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6278 } 6279 #endif 6280 } 6281 /* Face vertices have 2 + cells*2 supports */ 6282 for (f = fStart; f < fEnd; ++f) { 6283 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6284 const PetscInt *cone, *support; 6285 PetscInt size, s; 6286 6287 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6288 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6289 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6290 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6291 for (s = 0; s < size; ++s) { 6292 PetscInt r = 0; 6293 6294 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6295 if (cone[1] == f) r = 1; 6296 else if (cone[2] == f) r = 2; 6297 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6298 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6299 } 6300 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6301 #if 1 6302 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6303 for (p = 0; p < 2+size*2; ++p) { 6304 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6305 } 6306 #endif 6307 } 6308 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6309 break; 6310 case 2: 6311 /* Hex 2D */ 6312 /* 6313 3---------2---------2 6314 | | | 6315 | D 2 C | 6316 | | | 6317 3----3----0----1----1 6318 | | | 6319 | A 0 B | 6320 | | | 6321 0---------0---------1 6322 */ 6323 /* All cells have 4 faces */ 6324 for (c = cStart; c < cEnd; ++c) { 6325 const PetscInt newp = (c - cStart)*4; 6326 const PetscInt *cone, *ornt; 6327 PetscInt coneNew[4], orntNew[4]; 6328 6329 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6330 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6331 /* A quad */ 6332 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6333 orntNew[0] = ornt[0]; 6334 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6335 orntNew[1] = 0; 6336 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6337 orntNew[2] = -2; 6338 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6339 orntNew[3] = ornt[3]; 6340 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6341 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6342 #if 1 6343 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6344 for (p = 0; p < 4; ++p) { 6345 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6346 } 6347 #endif 6348 /* B quad */ 6349 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6350 orntNew[0] = ornt[0]; 6351 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6352 orntNew[1] = ornt[1]; 6353 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6354 orntNew[2] = 0; 6355 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6356 orntNew[3] = -2; 6357 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6358 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6359 #if 1 6360 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6361 for (p = 0; p < 4; ++p) { 6362 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6363 } 6364 #endif 6365 /* C quad */ 6366 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6367 orntNew[0] = -2; 6368 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6369 orntNew[1] = ornt[1]; 6370 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6371 orntNew[2] = ornt[2]; 6372 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6373 orntNew[3] = 0; 6374 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6375 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6376 #if 1 6377 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6378 for (p = 0; p < 4; ++p) { 6379 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6380 } 6381 #endif 6382 /* D quad */ 6383 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6384 orntNew[0] = 0; 6385 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6386 orntNew[1] = -2; 6387 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6388 orntNew[2] = ornt[2]; 6389 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6390 orntNew[3] = ornt[3]; 6391 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6392 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6393 #if 1 6394 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6395 for (p = 0; p < 4; ++p) { 6396 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6397 } 6398 #endif 6399 } 6400 /* Split faces have 2 vertices and the same cells as the parent */ 6401 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6402 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6403 for (f = fStart; f < fEnd; ++f) { 6404 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6405 6406 for (r = 0; r < 2; ++r) { 6407 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6408 const PetscInt *cone, *support; 6409 PetscInt coneNew[2], coneSize, c, supportSize, s; 6410 6411 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6412 coneNew[0] = vStartNew + (cone[0] - vStart); 6413 coneNew[1] = vStartNew + (cone[1] - vStart); 6414 coneNew[(r+1)%2] = newv; 6415 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6416 #if 1 6417 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6418 for (p = 0; p < 2; ++p) { 6419 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6420 } 6421 #endif 6422 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6423 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6424 for (s = 0; s < supportSize; ++s) { 6425 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6426 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6427 for (c = 0; c < coneSize; ++c) { 6428 if (cone[c] == f) break; 6429 } 6430 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6431 } 6432 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6433 #if 1 6434 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6435 for (p = 0; p < supportSize; ++p) { 6436 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6437 } 6438 #endif 6439 } 6440 } 6441 /* Interior faces have 2 vertices and 2 cells */ 6442 for (c = cStart; c < cEnd; ++c) { 6443 const PetscInt *cone; 6444 PetscInt coneNew[2], supportNew[2]; 6445 6446 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6447 for (r = 0; r < 4; ++r) { 6448 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6449 6450 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6451 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6452 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6453 #if 1 6454 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6455 for (p = 0; p < 2; ++p) { 6456 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6457 } 6458 #endif 6459 supportNew[0] = (c - cStart)*4 + r; 6460 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6461 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6462 #if 1 6463 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6464 for (p = 0; p < 2; ++p) { 6465 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6466 } 6467 #endif 6468 } 6469 } 6470 /* Old vertices have identical supports */ 6471 for (v = vStart; v < vEnd; ++v) { 6472 const PetscInt newp = vStartNew + (v - vStart); 6473 const PetscInt *support, *cone; 6474 PetscInt size, s; 6475 6476 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6477 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6478 for (s = 0; s < size; ++s) { 6479 PetscInt r = 0; 6480 6481 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6482 if (cone[1] == v) r = 1; 6483 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6484 } 6485 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6486 #if 1 6487 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6488 for (p = 0; p < size; ++p) { 6489 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6490 } 6491 #endif 6492 } 6493 /* Face vertices have 2 + cells supports */ 6494 for (f = fStart; f < fEnd; ++f) { 6495 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6496 const PetscInt *cone, *support; 6497 PetscInt size, s; 6498 6499 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6500 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6501 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6502 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6503 for (s = 0; s < size; ++s) { 6504 PetscInt r = 0; 6505 6506 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6507 if (cone[1] == f) r = 1; 6508 else if (cone[2] == f) r = 2; 6509 else if (cone[3] == f) r = 3; 6510 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6511 } 6512 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6513 #if 1 6514 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6515 for (p = 0; p < 2+size; ++p) { 6516 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6517 } 6518 #endif 6519 } 6520 /* Cell vertices have 4 supports */ 6521 for (c = cStart; c < cEnd; ++c) { 6522 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6523 PetscInt supportNew[4]; 6524 6525 for (r = 0; r < 4; ++r) { 6526 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6527 } 6528 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6529 } 6530 break; 6531 case 3: 6532 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6533 cMax = PetscMin(cEnd, cMax); 6534 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6535 fMax = PetscMin(fEnd, fMax); 6536 /* Interior cells have 3 faces */ 6537 for (c = cStart; c < cMax; ++c) { 6538 const PetscInt newp = cStartNew + (c - cStart)*4; 6539 const PetscInt *cone, *ornt; 6540 PetscInt coneNew[3], orntNew[3]; 6541 6542 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6543 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6544 /* A triangle */ 6545 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6546 orntNew[0] = ornt[0]; 6547 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6548 orntNew[1] = -2; 6549 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6550 orntNew[2] = ornt[2]; 6551 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6552 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6553 #if 1 6554 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6555 for (p = 0; p < 3; ++p) { 6556 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6557 } 6558 #endif 6559 /* B triangle */ 6560 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6561 orntNew[0] = ornt[0]; 6562 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6563 orntNew[1] = ornt[1]; 6564 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6565 orntNew[2] = -2; 6566 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6567 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6568 #if 1 6569 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6570 for (p = 0; p < 3; ++p) { 6571 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6572 } 6573 #endif 6574 /* C triangle */ 6575 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6576 orntNew[0] = -2; 6577 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6578 orntNew[1] = ornt[1]; 6579 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6580 orntNew[2] = ornt[2]; 6581 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6582 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6583 #if 1 6584 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6585 for (p = 0; p < 3; ++p) { 6586 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6587 } 6588 #endif 6589 /* D triangle */ 6590 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6591 orntNew[0] = 0; 6592 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6593 orntNew[1] = 0; 6594 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6595 orntNew[2] = 0; 6596 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6597 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6598 #if 1 6599 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6600 for (p = 0; p < 3; ++p) { 6601 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6602 } 6603 #endif 6604 } 6605 /* 6606 2----3----3 6607 | | 6608 | B | 6609 | | 6610 0----4--- 1 6611 | | 6612 | A | 6613 | | 6614 0----2----1 6615 */ 6616 /* Hybrid cells have 4 faces */ 6617 for (c = cMax; c < cEnd; ++c) { 6618 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6619 const PetscInt *cone, *ornt; 6620 PetscInt coneNew[4], orntNew[4]; 6621 6622 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6623 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6624 /* A quad */ 6625 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6626 orntNew[0] = ornt[0]; 6627 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6628 orntNew[1] = ornt[1]; 6629 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6630 orntNew[2] = 0; 6631 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6632 orntNew[3] = 0; 6633 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6634 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6635 #if 1 6636 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6637 for (p = 0; p < 4; ++p) { 6638 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6639 } 6640 #endif 6641 /* B quad */ 6642 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6643 orntNew[0] = ornt[0]; 6644 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6645 orntNew[1] = ornt[1]; 6646 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6647 orntNew[2] = 0; 6648 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6649 orntNew[3] = 0; 6650 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6651 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6652 #if 1 6653 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6654 for (p = 0; p < 4; ++p) { 6655 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6656 } 6657 #endif 6658 } 6659 /* Interior split faces have 2 vertices and the same cells as the parent */ 6660 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6661 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6662 for (f = fStart; f < fMax; ++f) { 6663 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6664 6665 for (r = 0; r < 2; ++r) { 6666 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6667 const PetscInt *cone, *support; 6668 PetscInt coneNew[2], coneSize, c, supportSize, s; 6669 6670 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6671 coneNew[0] = vStartNew + (cone[0] - vStart); 6672 coneNew[1] = vStartNew + (cone[1] - vStart); 6673 coneNew[(r+1)%2] = newv; 6674 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6675 #if 1 6676 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6677 for (p = 0; p < 2; ++p) { 6678 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6679 } 6680 #endif 6681 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6682 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6683 for (s = 0; s < supportSize; ++s) { 6684 if (support[s] >= cMax) { 6685 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6686 } else { 6687 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6688 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6689 for (c = 0; c < coneSize; ++c) { 6690 if (cone[c] == f) break; 6691 } 6692 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6693 } 6694 } 6695 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6696 #if 1 6697 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6698 for (p = 0; p < supportSize; ++p) { 6699 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6700 } 6701 #endif 6702 } 6703 } 6704 /* Interior cell faces have 2 vertices and 2 cells */ 6705 for (c = cStart; c < cMax; ++c) { 6706 const PetscInt *cone; 6707 6708 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6709 for (r = 0; r < 3; ++r) { 6710 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6711 PetscInt coneNew[2]; 6712 PetscInt supportNew[2]; 6713 6714 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6715 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6716 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6717 #if 1 6718 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6719 for (p = 0; p < 2; ++p) { 6720 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6721 } 6722 #endif 6723 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6724 supportNew[1] = (c - cStart)*4 + 3; 6725 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6726 #if 1 6727 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6728 for (p = 0; p < 2; ++p) { 6729 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6730 } 6731 #endif 6732 } 6733 } 6734 /* Interior hybrid faces have 2 vertices and the same cells */ 6735 for (f = fMax; f < fEnd; ++f) { 6736 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6737 const PetscInt *cone; 6738 const PetscInt *support; 6739 PetscInt coneNew[2]; 6740 PetscInt supportNew[2]; 6741 PetscInt size, s, r; 6742 6743 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6744 coneNew[0] = vStartNew + (cone[0] - vStart); 6745 coneNew[1] = vStartNew + (cone[1] - vStart); 6746 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6747 #if 1 6748 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6749 for (p = 0; p < 2; ++p) { 6750 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6751 } 6752 #endif 6753 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6754 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6755 for (s = 0; s < size; ++s) { 6756 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6757 for (r = 0; r < 2; ++r) { 6758 if (cone[r+2] == f) break; 6759 } 6760 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6761 } 6762 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6763 #if 1 6764 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6765 for (p = 0; p < size; ++p) { 6766 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6767 } 6768 #endif 6769 } 6770 /* Cell hybrid faces have 2 vertices and 2 cells */ 6771 for (c = cMax; c < cEnd; ++c) { 6772 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6773 const PetscInt *cone; 6774 PetscInt coneNew[2]; 6775 PetscInt supportNew[2]; 6776 6777 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6778 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6779 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6780 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6781 #if 1 6782 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6783 for (p = 0; p < 2; ++p) { 6784 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6785 } 6786 #endif 6787 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6788 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6789 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6790 #if 1 6791 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6792 for (p = 0; p < 2; ++p) { 6793 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6794 } 6795 #endif 6796 } 6797 /* Old vertices have identical supports */ 6798 for (v = vStart; v < vEnd; ++v) { 6799 const PetscInt newp = vStartNew + (v - vStart); 6800 const PetscInt *support, *cone; 6801 PetscInt size, s; 6802 6803 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6804 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6805 for (s = 0; s < size; ++s) { 6806 if (support[s] >= fMax) { 6807 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6808 } else { 6809 PetscInt r = 0; 6810 6811 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6812 if (cone[1] == v) r = 1; 6813 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6814 } 6815 } 6816 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6817 #if 1 6818 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6819 for (p = 0; p < size; ++p) { 6820 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6821 } 6822 #endif 6823 } 6824 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6825 for (f = fStart; f < fMax; ++f) { 6826 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6827 const PetscInt *cone, *support; 6828 PetscInt size, newSize = 2, s; 6829 6830 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6831 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6832 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6833 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6834 for (s = 0; s < size; ++s) { 6835 PetscInt r = 0; 6836 6837 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6838 if (support[s] >= cMax) { 6839 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6840 6841 newSize += 1; 6842 } else { 6843 if (cone[1] == f) r = 1; 6844 else if (cone[2] == f) r = 2; 6845 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6846 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6847 6848 newSize += 2; 6849 } 6850 } 6851 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6852 #if 1 6853 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6854 for (p = 0; p < newSize; ++p) { 6855 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6856 } 6857 #endif 6858 } 6859 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6860 break; 6861 default: 6862 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6863 } 6864 PetscFunctionReturn(0); 6865 } 6866 6867 #undef __FUNCT__ 6868 #define __FUNCT__ "CellRefinerSetCoordinates" 6869 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6870 { 6871 PetscSection coordSection, coordSectionNew; 6872 Vec coordinates, coordinatesNew; 6873 PetscScalar *coords, *coordsNew; 6874 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6875 PetscErrorCode ierr; 6876 6877 PetscFunctionBegin; 6878 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6879 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6880 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6881 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6882 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6883 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6884 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6885 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6886 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6887 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6888 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6889 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6890 if (fMax < 0) fMax = fEnd; 6891 switch (refiner) { 6892 case 1: 6893 case 2: 6894 case 3: 6895 /* Simplicial and Hex 2D */ 6896 /* All vertices have the dim coordinates */ 6897 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6898 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6899 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6900 } 6901 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6902 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6903 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6904 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6905 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6906 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6907 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6908 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6909 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6910 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6911 /* Old vertices have the same coordinates */ 6912 for (v = vStart; v < vEnd; ++v) { 6913 const PetscInt newv = vStartNew + (v - vStart); 6914 PetscInt off, offnew, d; 6915 6916 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6917 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6918 for (d = 0; d < dim; ++d) { 6919 coordsNew[offnew+d] = coords[off+d]; 6920 } 6921 } 6922 /* Face vertices have the average of endpoint coordinates */ 6923 for (f = fStart; f < fMax; ++f) { 6924 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6925 const PetscInt *cone; 6926 PetscInt coneSize, offA, offB, offnew, d; 6927 6928 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6929 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6930 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6931 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6932 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6933 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6934 for (d = 0; d < dim; ++d) { 6935 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6936 } 6937 } 6938 /* Just Hex 2D */ 6939 if (refiner == 2) { 6940 /* Cell vertices have the average of corner coordinates */ 6941 for (c = cStart; c < cEnd; ++c) { 6942 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6943 PetscInt *cone = PETSC_NULL; 6944 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6945 6946 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6947 for (p = 0; p < closureSize*2; p += 2) { 6948 const PetscInt point = cone[p]; 6949 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6950 } 6951 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6952 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6953 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6954 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6955 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6956 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6957 for (d = 0; d < dim; ++d) { 6958 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6959 } 6960 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6961 } 6962 } 6963 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6964 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6965 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6966 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6967 break; 6968 default: 6969 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6970 } 6971 PetscFunctionReturn(0); 6972 } 6973 6974 #undef __FUNCT__ 6975 #define __FUNCT__ "DMPlexCreateProcessSF" 6976 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6977 { 6978 PetscInt numRoots, numLeaves, l; 6979 const PetscInt *localPoints; 6980 const PetscSFNode *remotePoints; 6981 PetscInt *localPointsNew; 6982 PetscSFNode *remotePointsNew; 6983 PetscInt *ranks, *ranksNew; 6984 PetscErrorCode ierr; 6985 6986 PetscFunctionBegin; 6987 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6988 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6989 for (l = 0; l < numLeaves; ++l) { 6990 ranks[l] = remotePoints[l].rank; 6991 } 6992 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6993 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6994 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6995 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6996 for (l = 0; l < numLeaves; ++l) { 6997 ranksNew[l] = ranks[l]; 6998 localPointsNew[l] = l; 6999 remotePointsNew[l].index = 0; 7000 remotePointsNew[l].rank = ranksNew[l]; 7001 } 7002 ierr = PetscFree(ranks);CHKERRQ(ierr); 7003 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 7004 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 7005 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 7006 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7007 PetscFunctionReturn(0); 7008 } 7009 7010 #undef __FUNCT__ 7011 #define __FUNCT__ "CellRefinerCreateSF" 7012 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7013 { 7014 PetscSF sf, sfNew, sfProcess; 7015 IS processRanks; 7016 MPI_Datatype depthType; 7017 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7018 const PetscInt *localPoints, *neighbors; 7019 const PetscSFNode *remotePoints; 7020 PetscInt *localPointsNew; 7021 PetscSFNode *remotePointsNew; 7022 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7023 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7024 PetscErrorCode ierr; 7025 7026 PetscFunctionBegin; 7027 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7028 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7029 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7030 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7031 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7032 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7033 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7034 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7035 switch (refiner) { 7036 case 3: 7037 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7038 cMax = PetscMin(cEnd, cMax); 7039 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7040 fMax = PetscMin(fEnd, fMax); 7041 } 7042 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7043 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7044 /* Caculate size of new SF */ 7045 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7046 if (numRoots < 0) PetscFunctionReturn(0); 7047 for (l = 0; l < numLeaves; ++l) { 7048 const PetscInt p = localPoints[l]; 7049 7050 switch (refiner) { 7051 case 1: 7052 /* Simplicial 2D */ 7053 if ((p >= vStart) && (p < vEnd)) { 7054 /* Old vertices stay the same */ 7055 ++numLeavesNew; 7056 } else if ((p >= fStart) && (p < fEnd)) { 7057 /* Old faces add new faces and vertex */ 7058 numLeavesNew += 1 + 2; 7059 } else if ((p >= cStart) && (p < cEnd)) { 7060 /* Old cells add new cells and interior faces */ 7061 numLeavesNew += 4 + 3; 7062 } 7063 break; 7064 case 2: 7065 /* Hex 2D */ 7066 if ((p >= vStart) && (p < vEnd)) { 7067 /* Old vertices stay the same */ 7068 ++numLeavesNew; 7069 } else if ((p >= fStart) && (p < fEnd)) { 7070 /* Old faces add new faces and vertex */ 7071 numLeavesNew += 1 + 2; 7072 } else if ((p >= cStart) && (p < cEnd)) { 7073 /* Old cells add new cells and interior faces */ 7074 numLeavesNew += 4 + 4; 7075 } 7076 break; 7077 default: 7078 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7079 } 7080 } 7081 /* Communicate depthSizes for each remote rank */ 7082 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7083 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7084 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7085 ierr = PetscMalloc7(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthMaxOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr); 7086 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7087 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7088 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7089 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7090 for (n = 0; n < numNeighbors; ++n) { 7091 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7092 } 7093 depthSizeOld[depth] = cMax; 7094 depthSizeOld[0] = vMax; 7095 depthSizeOld[depth-1] = fMax; 7096 depthSizeOld[1] = eMax; 7097 7098 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7099 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7100 7101 depthSizeOld[depth] = cEnd - cStart; 7102 depthSizeOld[0] = vEnd - vStart; 7103 depthSizeOld[depth-1] = fEnd - fStart; 7104 depthSizeOld[1] = eEnd - eStart; 7105 7106 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7107 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7108 for (n = 0; n < numNeighbors; ++n) { 7109 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7110 } 7111 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7112 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7113 /* Calculate new point SF */ 7114 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7115 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7116 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7117 for (l = 0, m = 0; l < numLeaves; ++l) { 7118 PetscInt p = localPoints[l]; 7119 PetscInt rp = remotePoints[l].index, n; 7120 PetscMPIInt rrank = remotePoints[l].rank; 7121 7122 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7123 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7124 switch (refiner) { 7125 case 1: 7126 /* Simplicial 2D */ 7127 if ((p >= vStart) && (p < vEnd)) { 7128 /* Old vertices stay the same */ 7129 localPointsNew[m] = vStartNew + (p - vStart); 7130 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7131 remotePointsNew[m].rank = rrank; 7132 ++m; 7133 } else if ((p >= fStart) && (p < fEnd)) { 7134 /* Old faces add new faces and vertex */ 7135 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7136 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7137 remotePointsNew[m].rank = rrank; 7138 ++m; 7139 for (r = 0; r < 2; ++r, ++m) { 7140 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7141 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7142 remotePointsNew[m].rank = rrank; 7143 } 7144 } else if ((p >= cStart) && (p < cEnd)) { 7145 /* Old cells add new cells and interior faces */ 7146 for (r = 0; r < 4; ++r, ++m) { 7147 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7148 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7149 remotePointsNew[m].rank = rrank; 7150 } 7151 for (r = 0; r < 3; ++r, ++m) { 7152 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7153 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7154 remotePointsNew[m].rank = rrank; 7155 } 7156 } 7157 break; 7158 case 2: 7159 /* Hex 2D */ 7160 if ((p >= vStart) && (p < vEnd)) { 7161 /* Old vertices stay the same */ 7162 localPointsNew[m] = vStartNew + (p - vStart); 7163 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7164 remotePointsNew[m].rank = rrank; 7165 ++m; 7166 } else if ((p >= fStart) && (p < fEnd)) { 7167 /* Old faces add new faces and vertex */ 7168 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7169 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7170 remotePointsNew[m].rank = rrank; 7171 ++m; 7172 for (r = 0; r < 2; ++r, ++m) { 7173 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7174 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7175 remotePointsNew[m].rank = rrank; 7176 } 7177 } else if ((p >= cStart) && (p < cEnd)) { 7178 /* Old cells add new cells and interior faces */ 7179 for (r = 0; r < 4; ++r, ++m) { 7180 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7181 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7182 remotePointsNew[m].rank = rrank; 7183 } 7184 for (r = 0; r < 4; ++r, ++m) { 7185 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7186 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7187 remotePointsNew[m].rank = rrank; 7188 } 7189 } 7190 break; 7191 case 3: 7192 /* Hybrid simplicial 2D */ 7193 if ((p >= vStart) && (p < vEnd)) { 7194 /* Old vertices stay the same */ 7195 localPointsNew[m] = vStartNew + (p - vStart); 7196 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7197 remotePointsNew[m].rank = rrank; 7198 ++m; 7199 } else if ((p >= fStart) && (p < fMax)) { 7200 /* Old interior faces add new faces and vertex */ 7201 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7202 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7203 remotePointsNew[m].rank = rrank; 7204 ++m; 7205 for (r = 0; r < 2; ++r, ++m) { 7206 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7207 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7208 remotePointsNew[m].rank = rrank; 7209 } 7210 } else if ((p >= fMax) && (p < fEnd)) { 7211 /* Old hybrid faces stay the same */ 7212 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7213 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7214 remotePointsNew[m].rank = rrank; 7215 ++m; 7216 } else if ((p >= cStart) && (p < cMax)) { 7217 /* Old interior cells add new cells and interior faces */ 7218 for (r = 0; r < 4; ++r, ++m) { 7219 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7220 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7221 remotePointsNew[m].rank = rrank; 7222 } 7223 for (r = 0; r < 3; ++r, ++m) { 7224 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7225 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7226 remotePointsNew[m].rank = rrank; 7227 } 7228 } else if ((p >= cStart) && (p < cMax)) { 7229 /* Old hybrid cells add new cells and hybrid face */ 7230 for (r = 0; r < 2; ++r, ++m) { 7231 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7232 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7233 remotePointsNew[m].rank = rrank; 7234 } 7235 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7236 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth]); 7237 remotePointsNew[m].rank = rrank; 7238 ++m; 7239 } 7240 break; 7241 default: 7242 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7243 } 7244 } 7245 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7246 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7247 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7248 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7249 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7250 PetscFunctionReturn(0); 7251 } 7252 7253 #undef __FUNCT__ 7254 #define __FUNCT__ "CellRefinerCreateLabels" 7255 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7256 { 7257 PetscInt numLabels, l; 7258 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7259 PetscErrorCode ierr; 7260 7261 PetscFunctionBegin; 7262 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7263 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7264 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7265 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7266 7267 cStartNew = 0; 7268 vStartNew = depthSize[2]; 7269 fStartNew = depthSize[2] + depthSize[0]; 7270 7271 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7272 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7273 switch (refiner) { 7274 case 3: 7275 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7276 cMax = PetscMin(cEnd, cMax); 7277 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7278 fMax = PetscMin(fEnd, fMax); 7279 } 7280 for (l = 0; l < numLabels; ++l) { 7281 DMLabel label, labelNew; 7282 const char *lname; 7283 PetscBool isDepth; 7284 IS valueIS; 7285 const PetscInt *values; 7286 PetscInt numValues, val; 7287 7288 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7289 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7290 if (isDepth) continue; 7291 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7292 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7293 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7294 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7295 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7296 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7297 for (val = 0; val < numValues; ++val) { 7298 IS pointIS; 7299 const PetscInt *points; 7300 PetscInt numPoints, n; 7301 7302 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7303 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7304 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7305 for (n = 0; n < numPoints; ++n) { 7306 const PetscInt p = points[n]; 7307 switch (refiner) { 7308 case 1: 7309 /* Simplicial 2D */ 7310 if ((p >= vStart) && (p < vEnd)) { 7311 /* Old vertices stay the same */ 7312 newp = vStartNew + (p - vStart); 7313 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7314 } else if ((p >= fStart) && (p < fEnd)) { 7315 /* Old faces add new faces and vertex */ 7316 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7317 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7318 for (r = 0; r < 2; ++r) { 7319 newp = fStartNew + (p - fStart)*2 + r; 7320 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7321 } 7322 } else if ((p >= cStart) && (p < cEnd)) { 7323 /* Old cells add new cells and interior faces */ 7324 for (r = 0; r < 4; ++r) { 7325 newp = cStartNew + (p - cStart)*4 + r; 7326 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7327 } 7328 for (r = 0; r < 3; ++r) { 7329 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7330 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7331 } 7332 } 7333 break; 7334 case 2: 7335 /* Hex 2D */ 7336 if ((p >= vStart) && (p < vEnd)) { 7337 /* Old vertices stay the same */ 7338 newp = vStartNew + (p - vStart); 7339 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7340 } else if ((p >= fStart) && (p < fEnd)) { 7341 /* Old faces add new faces and vertex */ 7342 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7343 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7344 for (r = 0; r < 2; ++r) { 7345 newp = fStartNew + (p - fStart)*2 + r; 7346 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7347 } 7348 } else if ((p >= cStart) && (p < cEnd)) { 7349 /* Old cells add new cells and interior faces and vertex */ 7350 for (r = 0; r < 4; ++r) { 7351 newp = cStartNew + (p - cStart)*4 + r; 7352 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7353 } 7354 for (r = 0; r < 4; ++r) { 7355 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7356 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7357 } 7358 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7359 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7360 } 7361 break; 7362 case 3: 7363 /* Hybrid simplicial 2D */ 7364 if ((p >= vStart) && (p < vEnd)) { 7365 /* Old vertices stay the same */ 7366 newp = vStartNew + (p - vStart); 7367 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7368 } else if ((p >= fStart) && (p < fMax)) { 7369 /* Old interior faces add new faces and vertex */ 7370 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7371 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7372 for (r = 0; r < 2; ++r) { 7373 newp = fStartNew + (p - fStart)*2 + r; 7374 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7375 } 7376 } else if ((p >= fMax) && (p < fEnd)) { 7377 /* Old hybrid faces stay the same */ 7378 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7379 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7380 } else if ((p >= cStart) && (p < cMax)) { 7381 /* Old interior cells add new cells and interior faces */ 7382 for (r = 0; r < 4; ++r) { 7383 newp = cStartNew + (p - cStart)*4 + r; 7384 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7385 } 7386 for (r = 0; r < 3; ++r) { 7387 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7388 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7389 } 7390 } else if ((p >= cMax) && (p < cEnd)) { 7391 /* Old hybrid cells add new cells and hybrid face */ 7392 for (r = 0; r < 2; ++r) { 7393 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7394 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7395 } 7396 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7397 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7398 } 7399 break; 7400 default: 7401 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7402 } 7403 } 7404 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7405 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7406 } 7407 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7408 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7409 if (0) { 7410 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7411 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7412 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7413 } 7414 } 7415 PetscFunctionReturn(0); 7416 } 7417 7418 #undef __FUNCT__ 7419 #define __FUNCT__ "DMPlexRefine_Uniform" 7420 /* This will only work for interpolated meshes */ 7421 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7422 { 7423 DM rdm; 7424 PetscInt *depthSize; 7425 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7426 PetscErrorCode ierr; 7427 7428 PetscFunctionBegin; 7429 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7430 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7431 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7432 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7433 /* Calculate number of new points of each depth */ 7434 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7435 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7436 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7437 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7438 /* Step 1: Set chart */ 7439 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7440 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7441 /* Step 2: Set cone/support sizes */ 7442 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7443 /* Step 3: Setup refined DM */ 7444 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7445 /* Step 4: Set cones and supports */ 7446 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7447 /* Step 5: Stratify */ 7448 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7449 /* Step 6: Set coordinates for vertices */ 7450 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7451 /* Step 7: Create pointSF */ 7452 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7453 /* Step 8: Create labels */ 7454 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7455 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7456 7457 *dmRefined = rdm; 7458 PetscFunctionReturn(0); 7459 } 7460 7461 #undef __FUNCT__ 7462 #define __FUNCT__ "DMPlexSetRefinementUniform" 7463 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7464 { 7465 DM_Plex *mesh = (DM_Plex*) dm->data; 7466 7467 PetscFunctionBegin; 7468 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7469 mesh->refinementUniform = refinementUniform; 7470 PetscFunctionReturn(0); 7471 } 7472 7473 #undef __FUNCT__ 7474 #define __FUNCT__ "DMPlexGetRefinementUniform" 7475 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7476 { 7477 DM_Plex *mesh = (DM_Plex*) dm->data; 7478 7479 PetscFunctionBegin; 7480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7481 PetscValidPointer(refinementUniform, 2); 7482 *refinementUniform = mesh->refinementUniform; 7483 PetscFunctionReturn(0); 7484 } 7485 7486 #undef __FUNCT__ 7487 #define __FUNCT__ "DMPlexSetRefinementLimit" 7488 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7489 { 7490 DM_Plex *mesh = (DM_Plex*) dm->data; 7491 7492 PetscFunctionBegin; 7493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7494 mesh->refinementLimit = refinementLimit; 7495 PetscFunctionReturn(0); 7496 } 7497 7498 #undef __FUNCT__ 7499 #define __FUNCT__ "DMPlexGetRefinementLimit" 7500 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7501 { 7502 DM_Plex *mesh = (DM_Plex*) dm->data; 7503 7504 PetscFunctionBegin; 7505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7506 PetscValidPointer(refinementLimit, 2); 7507 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7508 *refinementLimit = mesh->refinementLimit; 7509 PetscFunctionReturn(0); 7510 } 7511 7512 #undef __FUNCT__ 7513 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7514 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7515 { 7516 PetscInt dim, cStart, coneSize, cMax; 7517 PetscErrorCode ierr; 7518 7519 PetscFunctionBegin; 7520 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7521 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7522 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7523 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7524 switch (dim) { 7525 case 2: 7526 switch (coneSize) { 7527 case 3: 7528 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7529 else *cellRefiner = 1; /* Triangular */ 7530 break; 7531 case 4: 7532 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7533 else *cellRefiner = 2; /* Quadrilateral */ 7534 break; 7535 default: 7536 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7537 } 7538 break; 7539 default: 7540 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7541 } 7542 PetscFunctionReturn(0); 7543 } 7544 7545 #undef __FUNCT__ 7546 #define __FUNCT__ "DMRefine_Plex" 7547 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7548 { 7549 PetscReal refinementLimit; 7550 PetscInt dim, cStart, cEnd; 7551 char genname[1024], *name = PETSC_NULL; 7552 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7553 PetscErrorCode ierr; 7554 7555 PetscFunctionBegin; 7556 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7557 if (isUniform) { 7558 CellRefiner cellRefiner; 7559 7560 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7561 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7562 PetscFunctionReturn(0); 7563 } 7564 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7565 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7566 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7567 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7568 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7569 if (flg) name = genname; 7570 if (name) { 7571 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7572 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7573 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7574 } 7575 switch (dim) { 7576 case 2: 7577 if (!name || isTriangle) { 7578 #if defined(PETSC_HAVE_TRIANGLE) 7579 double *maxVolumes; 7580 PetscInt c; 7581 7582 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7583 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7584 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7585 #else 7586 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7587 #endif 7588 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7589 break; 7590 case 3: 7591 if (!name || isCTetgen) { 7592 #if defined(PETSC_HAVE_CTETGEN) 7593 PetscReal *maxVolumes; 7594 PetscInt c; 7595 7596 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7597 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7598 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7599 #else 7600 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7601 #endif 7602 } else if (isTetgen) { 7603 #if defined(PETSC_HAVE_TETGEN) 7604 double *maxVolumes; 7605 PetscInt c; 7606 7607 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7608 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7609 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7610 #else 7611 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7612 #endif 7613 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7614 break; 7615 default: 7616 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7617 } 7618 PetscFunctionReturn(0); 7619 } 7620 7621 #undef __FUNCT__ 7622 #define __FUNCT__ "DMPlexGetDepth" 7623 /*@ 7624 DMPlexGetDepth - get the number of strata 7625 7626 Not Collective 7627 7628 Input Parameters: 7629 . dm - The DMPlex object 7630 7631 Output Parameters: 7632 . depth - number of strata 7633 7634 Level: developer 7635 7636 Notes: 7637 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7638 7639 .keywords: mesh, points 7640 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7641 @*/ 7642 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7643 { 7644 PetscInt d; 7645 PetscErrorCode ierr; 7646 7647 PetscFunctionBegin; 7648 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7649 PetscValidPointer(depth, 2); 7650 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7651 *depth = d-1; 7652 PetscFunctionReturn(0); 7653 } 7654 7655 #undef __FUNCT__ 7656 #define __FUNCT__ "DMPlexGetDepthStratum" 7657 /*@ 7658 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7659 7660 Not Collective 7661 7662 Input Parameters: 7663 + dm - The DMPlex object 7664 - stratumValue - The requested depth 7665 7666 Output Parameters: 7667 + start - The first point at this depth 7668 - end - One beyond the last point at this depth 7669 7670 Level: developer 7671 7672 .keywords: mesh, points 7673 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7674 @*/ 7675 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7676 { 7677 DM_Plex *mesh = (DM_Plex*) dm->data; 7678 DMLabel next = mesh->labels; 7679 PetscBool flg = PETSC_FALSE; 7680 PetscInt depth; 7681 PetscErrorCode ierr; 7682 7683 PetscFunctionBegin; 7684 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7685 if (stratumValue < 0) { 7686 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7687 PetscFunctionReturn(0); 7688 } else { 7689 PetscInt pStart, pEnd; 7690 7691 if (start) *start = 0; 7692 if (end) *end = 0; 7693 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7694 if (pStart == pEnd) PetscFunctionReturn(0); 7695 } 7696 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7697 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7698 /* We should have a generic GetLabel() and a Label class */ 7699 while (next) { 7700 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7701 if (flg) break; 7702 next = next->next; 7703 } 7704 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7705 depth = stratumValue; 7706 if ((depth < 0) || (depth >= next->numStrata)) { 7707 if (start) *start = 0; 7708 if (end) *end = 0; 7709 } else { 7710 if (start) *start = next->points[next->stratumOffsets[depth]]; 7711 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7712 } 7713 PetscFunctionReturn(0); 7714 } 7715 7716 #undef __FUNCT__ 7717 #define __FUNCT__ "DMPlexGetHeightStratum" 7718 /*@ 7719 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7720 7721 Not Collective 7722 7723 Input Parameters: 7724 + dm - The DMPlex object 7725 - stratumValue - The requested height 7726 7727 Output Parameters: 7728 + start - The first point at this height 7729 - end - One beyond the last point at this height 7730 7731 Level: developer 7732 7733 .keywords: mesh, points 7734 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7735 @*/ 7736 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7737 { 7738 DM_Plex *mesh = (DM_Plex*) dm->data; 7739 DMLabel next = mesh->labels; 7740 PetscBool flg = PETSC_FALSE; 7741 PetscInt depth; 7742 PetscErrorCode ierr; 7743 7744 PetscFunctionBegin; 7745 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7746 if (stratumValue < 0) { 7747 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7748 } else { 7749 PetscInt pStart, pEnd; 7750 7751 if (start) *start = 0; 7752 if (end) *end = 0; 7753 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7754 if (pStart == pEnd) PetscFunctionReturn(0); 7755 } 7756 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7757 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7758 /* We should have a generic GetLabel() and a Label class */ 7759 while (next) { 7760 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7761 if (flg) break; 7762 next = next->next; 7763 } 7764 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7765 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7766 if ((depth < 0) || (depth >= next->numStrata)) { 7767 if (start) *start = 0; 7768 if (end) *end = 0; 7769 } else { 7770 if (start) *start = next->points[next->stratumOffsets[depth]]; 7771 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7772 } 7773 PetscFunctionReturn(0); 7774 } 7775 7776 #undef __FUNCT__ 7777 #define __FUNCT__ "DMPlexCreateSectionInitial" 7778 /* Set the number of dof on each point and separate by fields */ 7779 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7780 { 7781 PetscInt *numDofTot; 7782 PetscInt pStart = 0, pEnd = 0; 7783 PetscInt p, d, f; 7784 PetscErrorCode ierr; 7785 7786 PetscFunctionBegin; 7787 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7788 for (d = 0; d <= dim; ++d) { 7789 numDofTot[d] = 0; 7790 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7791 } 7792 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7793 if (numFields > 0) { 7794 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7795 if (numComp) { 7796 for (f = 0; f < numFields; ++f) { 7797 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7798 } 7799 } 7800 } 7801 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7802 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7803 for (d = 0; d <= dim; ++d) { 7804 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7805 for (p = pStart; p < pEnd; ++p) { 7806 for (f = 0; f < numFields; ++f) { 7807 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7808 } 7809 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7810 } 7811 } 7812 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7813 PetscFunctionReturn(0); 7814 } 7815 7816 #undef __FUNCT__ 7817 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7818 /* Set the number of dof on each point and separate by fields 7819 If constDof is PETSC_DETERMINE, constrain every dof on the point 7820 */ 7821 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7822 { 7823 PetscInt numFields; 7824 PetscInt bc; 7825 PetscErrorCode ierr; 7826 7827 PetscFunctionBegin; 7828 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7829 for (bc = 0; bc < numBC; ++bc) { 7830 PetscInt field = 0; 7831 const PetscInt *idx; 7832 PetscInt n, i; 7833 7834 if (numFields) field = bcField[bc]; 7835 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7836 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7837 for (i = 0; i < n; ++i) { 7838 const PetscInt p = idx[i]; 7839 PetscInt numConst = constDof; 7840 7841 /* Constrain every dof on the point */ 7842 if (numConst < 0) { 7843 if (numFields) { 7844 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7845 } else { 7846 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7847 } 7848 } 7849 if (numFields) { 7850 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7851 } 7852 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7853 } 7854 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7855 } 7856 PetscFunctionReturn(0); 7857 } 7858 7859 #undef __FUNCT__ 7860 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7861 /* Set the constrained indices on each point and separate by fields */ 7862 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7863 { 7864 PetscInt *maxConstraints; 7865 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7866 PetscErrorCode ierr; 7867 7868 PetscFunctionBegin; 7869 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7870 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7871 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7872 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7873 for (p = pStart; p < pEnd; ++p) { 7874 PetscInt cdof; 7875 7876 if (numFields) { 7877 for (f = 0; f < numFields; ++f) { 7878 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7879 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7880 } 7881 } else { 7882 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7883 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7884 } 7885 } 7886 for (f = 0; f < numFields; ++f) { 7887 maxConstraints[numFields] += maxConstraints[f]; 7888 } 7889 if (maxConstraints[numFields]) { 7890 PetscInt *indices; 7891 7892 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7893 for (p = pStart; p < pEnd; ++p) { 7894 PetscInt cdof, d; 7895 7896 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7897 if (cdof) { 7898 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7899 if (numFields) { 7900 PetscInt numConst = 0, foff = 0; 7901 7902 for (f = 0; f < numFields; ++f) { 7903 PetscInt cfdof, fdof; 7904 7905 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7906 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7907 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7908 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7909 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7910 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7911 numConst += cfdof; 7912 foff += fdof; 7913 } 7914 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7915 } else { 7916 for (d = 0; d < cdof; ++d) indices[d] = d; 7917 } 7918 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7919 } 7920 } 7921 ierr = PetscFree(indices);CHKERRQ(ierr); 7922 } 7923 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7924 PetscFunctionReturn(0); 7925 } 7926 7927 #undef __FUNCT__ 7928 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7929 /* Set the constrained field indices on each point */ 7930 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7931 { 7932 const PetscInt *points, *indices; 7933 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7934 PetscErrorCode ierr; 7935 7936 PetscFunctionBegin; 7937 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7938 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7939 7940 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7941 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7942 if (!constraintIndices) { 7943 PetscInt *idx, i; 7944 7945 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7946 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7947 for (i = 0; i < maxDof; ++i) idx[i] = i; 7948 for (p = 0; p < numPoints; ++p) { 7949 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7950 } 7951 ierr = PetscFree(idx);CHKERRQ(ierr); 7952 } else { 7953 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7954 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7955 for (p = 0; p < numPoints; ++p) { 7956 PetscInt fcdof; 7957 7958 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7959 if (fcdof != numConstraints) SETERRQ4(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 7960 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7961 } 7962 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7963 } 7964 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7965 PetscFunctionReturn(0); 7966 } 7967 7968 #undef __FUNCT__ 7969 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7970 /* Set the constrained indices on each point and separate by fields */ 7971 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7972 { 7973 PetscInt *indices; 7974 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7975 PetscErrorCode ierr; 7976 7977 PetscFunctionBegin; 7978 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7979 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7980 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7981 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7982 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7983 for (p = pStart; p < pEnd; ++p) { 7984 PetscInt cdof, d; 7985 7986 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7987 if (cdof) { 7988 PetscInt numConst = 0, foff = 0; 7989 7990 for (f = 0; f < numFields; ++f) { 7991 const PetscInt *fcind; 7992 PetscInt fdof, fcdof; 7993 7994 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7995 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7996 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7997 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7998 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7999 foff += fdof; 8000 numConst += fcdof; 8001 } 8002 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8003 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8004 } 8005 } 8006 ierr = PetscFree(indices);CHKERRQ(ierr); 8007 PetscFunctionReturn(0); 8008 } 8009 8010 #undef __FUNCT__ 8011 #define __FUNCT__ "DMPlexCreateSection" 8012 /*@C 8013 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8014 8015 Not Collective 8016 8017 Input Parameters: 8018 + dm - The DMPlex object 8019 . dim - The spatial dimension of the problem 8020 . numFields - The number of fields in the problem 8021 . numComp - An array of size numFields that holds the number of components for each field 8022 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8023 . numBC - The number of boundary conditions 8024 . bcField - An array of size numBC giving the field number for each boundry condition 8025 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8026 8027 Output Parameter: 8028 . section - The PetscSection object 8029 8030 Notes: numDof[f*(dim+1)+d] gives the number of dof for field f on sieve points of dimension d. For instance, numDof[1] is the 8031 nubmer of dof for field 0 on each edge. 8032 8033 Level: developer 8034 8035 .keywords: mesh, elements 8036 .seealso: DMPlexCreate(), PetscSectionCreate() 8037 @*/ 8038 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8039 { 8040 PetscErrorCode ierr; 8041 8042 PetscFunctionBegin; 8043 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8044 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8045 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8046 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8047 { 8048 PetscBool view = PETSC_FALSE; 8049 8050 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8051 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8052 } 8053 PetscFunctionReturn(0); 8054 } 8055 8056 #undef __FUNCT__ 8057 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8058 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8059 { 8060 PetscSection section; 8061 PetscErrorCode ierr; 8062 8063 PetscFunctionBegin; 8064 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8065 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8066 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8067 PetscFunctionReturn(0); 8068 } 8069 8070 #undef __FUNCT__ 8071 #define __FUNCT__ "DMPlexGetCoordinateSection" 8072 /*@ 8073 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8074 8075 Not Collective 8076 8077 Input Parameter: 8078 . dm - The DMPlex object 8079 8080 Output Parameter: 8081 . section - The PetscSection object 8082 8083 Level: intermediate 8084 8085 .keywords: mesh, coordinates 8086 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8087 @*/ 8088 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8089 { 8090 DM cdm; 8091 PetscErrorCode ierr; 8092 8093 PetscFunctionBegin; 8094 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8095 PetscValidPointer(section, 2); 8096 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8097 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8098 PetscFunctionReturn(0); 8099 } 8100 8101 #undef __FUNCT__ 8102 #define __FUNCT__ "DMPlexSetCoordinateSection" 8103 /*@ 8104 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8105 8106 Not Collective 8107 8108 Input Parameters: 8109 + dm - The DMPlex object 8110 - section - The PetscSection object 8111 8112 Level: intermediate 8113 8114 .keywords: mesh, coordinates 8115 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8116 @*/ 8117 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8118 { 8119 DM cdm; 8120 PetscErrorCode ierr; 8121 8122 PetscFunctionBegin; 8123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8125 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8126 PetscFunctionReturn(0); 8127 } 8128 8129 #undef __FUNCT__ 8130 #define __FUNCT__ "DMPlexGetConeSection" 8131 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8132 { 8133 DM_Plex *mesh = (DM_Plex*) dm->data; 8134 8135 PetscFunctionBegin; 8136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8137 if (section) *section = mesh->coneSection; 8138 PetscFunctionReturn(0); 8139 } 8140 8141 #undef __FUNCT__ 8142 #define __FUNCT__ "DMPlexGetCones" 8143 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8144 { 8145 DM_Plex *mesh = (DM_Plex*) dm->data; 8146 8147 PetscFunctionBegin; 8148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8149 if (cones) *cones = mesh->cones; 8150 PetscFunctionReturn(0); 8151 } 8152 8153 #undef __FUNCT__ 8154 #define __FUNCT__ "DMPlexGetConeOrientations" 8155 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8156 { 8157 DM_Plex *mesh = (DM_Plex*) dm->data; 8158 8159 PetscFunctionBegin; 8160 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8161 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8162 PetscFunctionReturn(0); 8163 } 8164 8165 #undef __FUNCT__ 8166 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8167 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8168 { 8169 const PetscInt embedDim = 2; 8170 PetscReal x = PetscRealPart(point[0]); 8171 PetscReal y = PetscRealPart(point[1]); 8172 PetscReal v0[2], J[4], invJ[4], detJ; 8173 PetscReal xi, eta; 8174 PetscErrorCode ierr; 8175 8176 PetscFunctionBegin; 8177 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8178 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8179 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8180 8181 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8182 else *cell = -1; 8183 PetscFunctionReturn(0); 8184 } 8185 8186 #undef __FUNCT__ 8187 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8188 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8189 { 8190 PetscSection coordSection; 8191 Vec coordsLocal; 8192 const PetscScalar *coords; 8193 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8194 PetscReal x = PetscRealPart(point[0]); 8195 PetscReal y = PetscRealPart(point[1]); 8196 PetscInt crossings = 0, f; 8197 PetscErrorCode ierr; 8198 8199 PetscFunctionBegin; 8200 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8201 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8202 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8203 for (f = 0; f < 4; ++f) { 8204 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8205 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8206 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8207 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8208 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8209 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8210 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8211 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8212 if ((cond1 || cond2) && above) ++crossings; 8213 } 8214 if (crossings % 2) *cell = c; 8215 else *cell = -1; 8216 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8217 PetscFunctionReturn(0); 8218 } 8219 8220 #undef __FUNCT__ 8221 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8222 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8223 { 8224 const PetscInt embedDim = 3; 8225 PetscReal v0[3], J[9], invJ[9], detJ; 8226 PetscReal x = PetscRealPart(point[0]); 8227 PetscReal y = PetscRealPart(point[1]); 8228 PetscReal z = PetscRealPart(point[2]); 8229 PetscReal xi, eta, zeta; 8230 PetscErrorCode ierr; 8231 8232 PetscFunctionBegin; 8233 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8234 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8235 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8236 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8237 8238 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8239 else *cell = -1; 8240 PetscFunctionReturn(0); 8241 } 8242 8243 #undef __FUNCT__ 8244 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8245 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8246 { 8247 PetscSection coordSection; 8248 Vec coordsLocal; 8249 const PetscScalar *coords; 8250 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8251 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8252 PetscBool found = PETSC_TRUE; 8253 PetscInt f; 8254 PetscErrorCode ierr; 8255 8256 PetscFunctionBegin; 8257 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8258 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8259 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8260 for (f = 0; f < 6; ++f) { 8261 /* Check the point is under plane */ 8262 /* Get face normal */ 8263 PetscReal v_i[3]; 8264 PetscReal v_j[3]; 8265 PetscReal normal[3]; 8266 PetscReal pp[3]; 8267 PetscReal dot; 8268 8269 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8270 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8271 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8272 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8273 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8274 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8275 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8276 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8277 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8278 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8279 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8280 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8281 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8282 8283 /* Check that projected point is in face (2D location problem) */ 8284 if (dot < 0.0) { 8285 found = PETSC_FALSE; 8286 break; 8287 } 8288 } 8289 if (found) *cell = c; 8290 else *cell = -1; 8291 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8292 PetscFunctionReturn(0); 8293 } 8294 8295 #undef __FUNCT__ 8296 #define __FUNCT__ "DMLocatePoints_Plex" 8297 /* 8298 Need to implement using the guess 8299 */ 8300 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8301 { 8302 PetscInt cell = -1 /*, guess = -1*/; 8303 PetscInt bs, numPoints, p; 8304 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8305 PetscInt *cells; 8306 PetscScalar *a; 8307 PetscErrorCode ierr; 8308 8309 PetscFunctionBegin; 8310 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8311 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8312 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8313 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8314 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8315 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8316 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8317 if (bs != dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 8318 numPoints /= bs; 8319 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8320 for (p = 0; p < numPoints; ++p) { 8321 const PetscScalar *point = &a[p*bs]; 8322 8323 switch (dim) { 8324 case 2: 8325 for (c = cStart; c < cEnd; ++c) { 8326 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8327 switch (coneSize) { 8328 case 3: 8329 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8330 break; 8331 case 4: 8332 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8333 break; 8334 default: 8335 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8336 } 8337 if (cell >= 0) break; 8338 } 8339 break; 8340 case 3: 8341 for (c = cStart; c < cEnd; ++c) { 8342 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8343 switch (coneSize) { 8344 case 4: 8345 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8346 break; 8347 case 8: 8348 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8349 break; 8350 default: 8351 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8352 } 8353 if (cell >= 0) break; 8354 } 8355 break; 8356 default: 8357 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8358 } 8359 cells[p] = cell; 8360 } 8361 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8362 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8363 PetscFunctionReturn(0); 8364 } 8365 8366 /******************************** FEM Support **********************************/ 8367 8368 #undef __FUNCT__ 8369 #define __FUNCT__ "DMPlexVecGetClosure" 8370 /*@C 8371 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8372 8373 Not collective 8374 8375 Input Parameters: 8376 + dm - The DM 8377 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8378 . v - The local vector 8379 - point - The sieve point in the DM 8380 8381 Output Parameters: 8382 + csize - The number of values in the closure, or PETSC_NULL 8383 - values - The array of values, which is a borrowed array and should not be freed 8384 8385 Level: intermediate 8386 8387 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8388 @*/ 8389 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8390 { 8391 PetscScalar *array, *vArray; 8392 PetscInt *points = PETSC_NULL; 8393 PetscInt offsets[32]; 8394 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8395 PetscErrorCode ierr; 8396 8397 PetscFunctionBegin; 8398 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8399 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8400 if (!section) { 8401 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8402 } 8403 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8404 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8405 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8406 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8407 /* Compress out points not in the section */ 8408 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8409 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8410 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8411 points[q*2] = points[p]; 8412 points[q*2+1] = points[p+1]; 8413 ++q; 8414 } 8415 } 8416 numPoints = q; 8417 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8418 PetscInt dof, fdof; 8419 8420 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8421 for (f = 0; f < numFields; ++f) { 8422 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8423 offsets[f+1] += fdof; 8424 } 8425 size += dof; 8426 } 8427 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8428 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8429 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8430 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8431 for (p = 0; p < numPoints*2; p += 2) { 8432 PetscInt o = points[p+1]; 8433 PetscInt dof, off, d; 8434 PetscScalar *varr; 8435 8436 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8437 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8438 varr = &vArray[off]; 8439 if (numFields) { 8440 PetscInt fdof, foff, fcomp, f, c; 8441 8442 for (f = 0, foff = 0; f < numFields; ++f) { 8443 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8444 if (o >= 0) { 8445 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8446 array[offsets[f]] = varr[foff+d]; 8447 } 8448 } else { 8449 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8450 for (d = fdof/fcomp-1; d >= 0; --d) { 8451 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8452 array[offsets[f]] = varr[foff+d*fcomp+c]; 8453 } 8454 } 8455 } 8456 foff += fdof; 8457 } 8458 } else { 8459 if (o >= 0) { 8460 for (d = 0; d < dof; ++d, ++offsets[0]) { 8461 array[offsets[0]] = varr[d]; 8462 } 8463 } else { 8464 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8465 array[offsets[0]] = varr[d]; 8466 } 8467 } 8468 } 8469 } 8470 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8471 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8472 if (csize) *csize = size; 8473 *values = array; 8474 PetscFunctionReturn(0); 8475 } 8476 8477 #undef __FUNCT__ 8478 #define __FUNCT__ "DMPlexVecRestoreClosure" 8479 /*@C 8480 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8481 8482 Not collective 8483 8484 Input Parameters: 8485 + dm - The DM 8486 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8487 . v - The local vector 8488 . point - The sieve point in the DM 8489 . csize - The number of values in the closure, or PETSC_NULL 8490 - values - The array of values, which is a borrowed array and should not be freed 8491 8492 Level: intermediate 8493 8494 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8495 @*/ 8496 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8497 { 8498 PetscInt size = 0; 8499 PetscErrorCode ierr; 8500 8501 PetscFunctionBegin; 8502 /* Should work without recalculating size */ 8503 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8504 PetscFunctionReturn(0); 8505 } 8506 8507 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8508 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8509 8510 #undef __FUNCT__ 8511 #define __FUNCT__ "updatePoint_private" 8512 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8513 { 8514 PetscInt cdof; /* The number of constraints on this point */ 8515 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8516 PetscScalar *a; 8517 PetscInt off, cind = 0, k; 8518 PetscErrorCode ierr; 8519 8520 PetscFunctionBegin; 8521 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8522 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8523 a = &array[off]; 8524 if (!cdof || setBC) { 8525 if (orientation >= 0) { 8526 for (k = 0; k < dof; ++k) { 8527 fuse(&a[k], values[k]); 8528 } 8529 } else { 8530 for (k = 0; k < dof; ++k) { 8531 fuse(&a[k], values[dof-k-1]); 8532 } 8533 } 8534 } else { 8535 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8536 if (orientation >= 0) { 8537 for (k = 0; k < dof; ++k) { 8538 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8539 fuse(&a[k], values[k]); 8540 } 8541 } else { 8542 for (k = 0; k < dof; ++k) { 8543 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8544 fuse(&a[k], values[dof-k-1]); 8545 } 8546 } 8547 } 8548 PetscFunctionReturn(0); 8549 } 8550 8551 #undef __FUNCT__ 8552 #define __FUNCT__ "updatePointFields_private" 8553 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8554 { 8555 PetscScalar *a; 8556 PetscInt numFields, off, foff, f; 8557 PetscErrorCode ierr; 8558 8559 PetscFunctionBegin; 8560 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8561 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8562 a = &array[off]; 8563 for (f = 0, foff = 0; f < numFields; ++f) { 8564 PetscInt fdof, fcomp, fcdof; 8565 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8566 PetscInt cind = 0, k, c; 8567 8568 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8569 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8570 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8571 if (!fcdof || setBC) { 8572 if (orientation >= 0) { 8573 for (k = 0; k < fdof; ++k) { 8574 fuse(&a[foff+k], values[foffs[f]+k]); 8575 } 8576 } else { 8577 for (k = fdof/fcomp-1; k >= 0; --k) { 8578 for (c = 0; c < fcomp; ++c) { 8579 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8580 } 8581 } 8582 } 8583 } else { 8584 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8585 if (orientation >= 0) { 8586 for (k = 0; k < fdof; ++k) { 8587 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8588 fuse(&a[foff+k], values[foffs[f]+k]); 8589 } 8590 } else { 8591 for (k = fdof/fcomp-1; k >= 0; --k) { 8592 for (c = 0; c < fcomp; ++c) { 8593 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8594 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8595 } 8596 } 8597 } 8598 } 8599 foff += fdof; 8600 foffs[f] += fdof; 8601 } 8602 PetscFunctionReturn(0); 8603 } 8604 8605 #undef __FUNCT__ 8606 #define __FUNCT__ "DMPlexVecSetClosure" 8607 /*@C 8608 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8609 8610 Not collective 8611 8612 Input Parameters: 8613 + dm - The DM 8614 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8615 . v - The local vector 8616 . point - The sieve point in the DM 8617 . values - The array of values, which is a borrowed array and should not be freed 8618 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8619 8620 Level: intermediate 8621 8622 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8623 @*/ 8624 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8625 { 8626 PetscScalar *array; 8627 PetscInt *points = PETSC_NULL; 8628 PetscInt offsets[32]; 8629 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8630 PetscErrorCode ierr; 8631 8632 PetscFunctionBegin; 8633 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8634 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8635 if (!section) { 8636 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8637 } 8638 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8639 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8640 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8641 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8642 /* Compress out points not in the section */ 8643 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8644 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8645 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8646 points[q*2] = points[p]; 8647 points[q*2+1] = points[p+1]; 8648 ++q; 8649 } 8650 } 8651 numPoints = q; 8652 for (p = 0; p < numPoints*2; p += 2) { 8653 PetscInt fdof; 8654 8655 for (f = 0; f < numFields; ++f) { 8656 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8657 offsets[f+1] += fdof; 8658 } 8659 } 8660 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8661 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8662 if (numFields) { 8663 switch (mode) { 8664 case INSERT_VALUES: 8665 for (p = 0; p < numPoints*2; p += 2) { 8666 PetscInt o = points[p+1]; 8667 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8668 } break; 8669 case INSERT_ALL_VALUES: 8670 for (p = 0; p < numPoints*2; p += 2) { 8671 PetscInt o = points[p+1]; 8672 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8673 } break; 8674 case ADD_VALUES: 8675 for (p = 0; p < numPoints*2; p += 2) { 8676 PetscInt o = points[p+1]; 8677 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8678 } break; 8679 case ADD_ALL_VALUES: 8680 for (p = 0; p < numPoints*2; p += 2) { 8681 PetscInt o = points[p+1]; 8682 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8683 } break; 8684 default: 8685 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8686 } 8687 } else { 8688 switch (mode) { 8689 case INSERT_VALUES: 8690 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8691 PetscInt o = points[p+1]; 8692 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8693 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8694 } break; 8695 case INSERT_ALL_VALUES: 8696 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8697 PetscInt o = points[p+1]; 8698 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8699 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8700 } break; 8701 case ADD_VALUES: 8702 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8703 PetscInt o = points[p+1]; 8704 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8705 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8706 } break; 8707 case ADD_ALL_VALUES: 8708 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8709 PetscInt o = points[p+1]; 8710 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8711 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8712 } break; 8713 default: 8714 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8715 } 8716 } 8717 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8718 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8719 PetscFunctionReturn(0); 8720 } 8721 8722 #undef __FUNCT__ 8723 #define __FUNCT__ "DMPlexPrintMatSetValues" 8724 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8725 { 8726 PetscMPIInt rank; 8727 PetscInt i, j; 8728 PetscErrorCode ierr; 8729 8730 PetscFunctionBegin; 8731 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8732 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8733 for (i = 0; i < numIndices; i++) { 8734 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8735 } 8736 for (i = 0; i < numIndices; i++) { 8737 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8738 for (j = 0; j < numIndices; j++) { 8739 #if defined(PETSC_USE_COMPLEX) 8740 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8741 #else 8742 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8743 #endif 8744 } 8745 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8746 } 8747 PetscFunctionReturn(0); 8748 } 8749 8750 #undef __FUNCT__ 8751 #define __FUNCT__ "indicesPoint_private" 8752 /* . off - The global offset of this point */ 8753 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8754 { 8755 PetscInt cdof; /* The number of constraints on this point */ 8756 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8757 PetscInt cind = 0, k; 8758 PetscErrorCode ierr; 8759 8760 PetscFunctionBegin; 8761 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8762 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8763 if (!cdof || setBC) { 8764 if (orientation >= 0) { 8765 for (k = 0; k < dof; ++k) indices[k] = off+k; 8766 } else { 8767 for (k = 0; k < dof; ++k) indices[dof-k-1] = off+k; 8768 } 8769 } else { 8770 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8771 if (orientation >= 0) { 8772 for (k = 0; k < dof; ++k) { 8773 if ((cind < cdof) && (k == cdofs[cind])) { 8774 /* Insert check for returning constrained indices */ 8775 indices[k] = -(off+k+1); 8776 ++cind; 8777 } else { 8778 indices[k] = off+k-cind; 8779 } 8780 } 8781 } else { 8782 for (k = 0; k < dof; ++k) { 8783 if ((cind < cdof) && (k == cdofs[cind])) { 8784 /* Insert check for returning constrained indices */ 8785 indices[dof-k-1] = -(off+k+1); 8786 ++cind; 8787 } else { 8788 indices[dof-k-1] = off+k-cind; 8789 } 8790 } 8791 } 8792 } 8793 PetscFunctionReturn(0); 8794 } 8795 8796 #undef __FUNCT__ 8797 #define __FUNCT__ "indicesPointFields_private" 8798 /* . off - The global offset of this point */ 8799 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8800 { 8801 PetscInt numFields, foff, f; 8802 PetscErrorCode ierr; 8803 8804 PetscFunctionBegin; 8805 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8806 for (f = 0, foff = 0; f < numFields; ++f) { 8807 PetscInt fdof, fcomp, cfdof; 8808 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8809 PetscInt cind = 0, k, c; 8810 8811 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8812 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8813 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8814 if (!cfdof || setBC) { 8815 if (orientation >= 0) { 8816 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8817 } else { 8818 for (k = fdof/fcomp-1; k >= 0; --k) { 8819 for (c = 0; c < fcomp; ++c) { 8820 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8821 } 8822 } 8823 } 8824 } else { 8825 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8826 if (orientation >= 0) { 8827 for (k = 0; k < fdof; ++k) { 8828 if ((cind < cfdof) && (k == fcdofs[cind])) { 8829 indices[foffs[f]+k] = -(off+foff+k+1); 8830 ++cind; 8831 } else { 8832 indices[foffs[f]+k] = off+foff+k-cind; 8833 } 8834 } 8835 } else { 8836 for (k = fdof/fcomp-1; k >= 0; --k) { 8837 for (c = 0; c < fcomp; ++c) { 8838 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8839 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8840 ++cind; 8841 } else { 8842 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8843 } 8844 } 8845 } 8846 } 8847 } 8848 foff += fdof - cfdof; 8849 foffs[f] += fdof; 8850 } 8851 PetscFunctionReturn(0); 8852 } 8853 8854 #undef __FUNCT__ 8855 #define __FUNCT__ "DMPlexMatSetClosure" 8856 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8857 { 8858 DM_Plex *mesh = (DM_Plex*) dm->data; 8859 PetscInt *points = PETSC_NULL; 8860 PetscInt *indices; 8861 PetscInt offsets[32]; 8862 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8863 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8864 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8865 PetscErrorCode ierr; 8866 8867 PetscFunctionBegin; 8868 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8869 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8870 if (useDefault) { 8871 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8872 } 8873 if (useGlobalDefault) { 8874 if (useDefault) { 8875 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8876 } else { 8877 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8878 } 8879 } 8880 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8881 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8882 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8883 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8884 /* Compress out points not in the section */ 8885 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8886 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8887 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8888 points[q*2] = points[p]; 8889 points[q*2+1] = points[p+1]; 8890 ++q; 8891 } 8892 } 8893 numPoints = q; 8894 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8895 PetscInt fdof; 8896 8897 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8898 for (f = 0; f < numFields; ++f) { 8899 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8900 offsets[f+1] += fdof; 8901 } 8902 numIndices += dof; 8903 } 8904 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8905 8906 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8907 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8908 if (numFields) { 8909 for (p = 0; p < numPoints*2; p += 2) { 8910 PetscInt o = points[p+1]; 8911 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8912 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8913 } 8914 } else { 8915 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8916 PetscInt o = points[p+1]; 8917 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8918 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8919 } 8920 } 8921 if (useGlobalDefault && !useDefault) { 8922 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8923 } 8924 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8925 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8926 if (ierr) { 8927 PetscMPIInt rank; 8928 PetscErrorCode ierr2; 8929 8930 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8931 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8932 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8933 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8934 CHKERRQ(ierr); 8935 } 8936 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8937 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8938 PetscFunctionReturn(0); 8939 } 8940 8941 #undef __FUNCT__ 8942 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8943 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8944 { 8945 PetscSection coordSection; 8946 Vec coordinates; 8947 const PetscScalar *coords; 8948 const PetscInt dim = 2; 8949 PetscInt d, f; 8950 PetscErrorCode ierr; 8951 8952 PetscFunctionBegin; 8953 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8954 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8955 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8956 if (v0) { 8957 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8958 } 8959 if (J) { 8960 for (d = 0; d < dim; d++) { 8961 for (f = 0; f < dim; f++) { 8962 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8963 } 8964 } 8965 *detJ = J[0]*J[3] - J[1]*J[2]; 8966 #if 0 8967 if (detJ < 0.0) { 8968 const PetscReal xLength = mesh->periodicity[0]; 8969 8970 if (xLength != 0.0) { 8971 PetscReal v0x = coords[0*dim+0]; 8972 8973 if (v0x == 0.0) v0x = v0[0] = xLength; 8974 for (f = 0; f < dim; f++) { 8975 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8976 8977 J[0*dim+f] = 0.5*(px - v0x); 8978 } 8979 } 8980 detJ = J[0]*J[3] - J[1]*J[2]; 8981 } 8982 #endif 8983 PetscLogFlops(8.0 + 3.0); 8984 } 8985 if (invJ) { 8986 const PetscReal invDet = 1.0/(*detJ); 8987 8988 invJ[0] = invDet*J[3]; 8989 invJ[1] = -invDet*J[1]; 8990 invJ[2] = -invDet*J[2]; 8991 invJ[3] = invDet*J[0]; 8992 PetscLogFlops(5.0); 8993 } 8994 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8995 PetscFunctionReturn(0); 8996 } 8997 8998 #undef __FUNCT__ 8999 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9000 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9001 { 9002 PetscSection coordSection; 9003 Vec coordinates; 9004 const PetscScalar *coords; 9005 const PetscInt dim = 2; 9006 PetscInt d, f; 9007 PetscErrorCode ierr; 9008 9009 PetscFunctionBegin; 9010 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9011 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9012 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9013 if (v0) { 9014 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9015 } 9016 if (J) { 9017 for (d = 0; d < dim; d++) { 9018 for (f = 0; f < dim; f++) { 9019 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9020 } 9021 } 9022 *detJ = J[0]*J[3] - J[1]*J[2]; 9023 PetscLogFlops(8.0 + 3.0); 9024 } 9025 if (invJ) { 9026 const PetscReal invDet = 1.0/(*detJ); 9027 9028 invJ[0] = invDet*J[3]; 9029 invJ[1] = -invDet*J[1]; 9030 invJ[2] = -invDet*J[2]; 9031 invJ[3] = invDet*J[0]; 9032 PetscLogFlops(5.0); 9033 } 9034 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9035 PetscFunctionReturn(0); 9036 } 9037 9038 #undef __FUNCT__ 9039 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9040 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9041 { 9042 PetscSection coordSection; 9043 Vec coordinates; 9044 const PetscScalar *coords; 9045 const PetscInt dim = 3; 9046 PetscInt d, f; 9047 PetscErrorCode ierr; 9048 9049 PetscFunctionBegin; 9050 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9051 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9052 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9053 if (v0) { 9054 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9055 } 9056 if (J) { 9057 for (d = 0; d < dim; d++) { 9058 for (f = 0; f < dim; f++) { 9059 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9060 } 9061 } 9062 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9063 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9064 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9065 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9066 PetscLogFlops(18.0 + 12.0); 9067 } 9068 if (invJ) { 9069 const PetscReal invDet = 1.0/(*detJ); 9070 9071 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9072 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9073 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9074 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9075 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9076 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9077 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9078 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9079 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9080 PetscLogFlops(37.0); 9081 } 9082 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9083 PetscFunctionReturn(0); 9084 } 9085 9086 #undef __FUNCT__ 9087 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9088 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9089 { 9090 PetscSection coordSection; 9091 Vec coordinates; 9092 const PetscScalar *coords; 9093 const PetscInt dim = 3; 9094 PetscInt d; 9095 PetscErrorCode ierr; 9096 9097 PetscFunctionBegin; 9098 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9099 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9100 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9101 if (v0) { 9102 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9103 } 9104 if (J) { 9105 for (d = 0; d < dim; d++) { 9106 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9107 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9108 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9109 } 9110 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9111 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9112 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9113 PetscLogFlops(18.0 + 12.0); 9114 } 9115 if (invJ) { 9116 const PetscReal invDet = -1.0/(*detJ); 9117 9118 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9119 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9120 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9121 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9122 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9123 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9124 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9125 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9126 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9127 PetscLogFlops(37.0); 9128 } 9129 *detJ *= 8.0; 9130 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9131 PetscFunctionReturn(0); 9132 } 9133 9134 #undef __FUNCT__ 9135 #define __FUNCT__ "DMPlexComputeCellGeometry" 9136 /*@C 9137 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9138 9139 Collective on DM 9140 9141 Input Arguments: 9142 + dm - the DM 9143 - cell - the cell 9144 9145 Output Arguments: 9146 + v0 - the translation part of this affine transform 9147 . J - the Jacobian of the transform to the reference element 9148 . invJ - the inverse of the Jacobian 9149 - detJ - the Jacobian determinant 9150 9151 Level: advanced 9152 9153 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9154 @*/ 9155 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9156 { 9157 PetscInt dim, coneSize; 9158 PetscErrorCode ierr; 9159 9160 PetscFunctionBegin; 9161 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9162 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9163 switch (dim) { 9164 case 2: 9165 switch (coneSize) { 9166 case 3: 9167 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9168 break; 9169 case 4: 9170 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9171 break; 9172 default: 9173 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9174 } 9175 break; 9176 case 3: 9177 switch (coneSize) { 9178 case 4: 9179 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9180 break; 9181 case 8: 9182 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9183 break; 9184 default: 9185 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9186 } 9187 break; 9188 default: 9189 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9190 } 9191 PetscFunctionReturn(0); 9192 } 9193 9194 #undef __FUNCT__ 9195 #define __FUNCT__ "DMPlexGetFaceOrientation" 9196 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9197 { 9198 MPI_Comm comm = ((PetscObject) dm)->comm; 9199 PetscBool posOrient = PETSC_FALSE; 9200 const PetscInt debug = 0; 9201 PetscInt cellDim, faceSize, f; 9202 PetscErrorCode ierr; 9203 9204 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9205 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9206 9207 if (cellDim == numCorners-1) { 9208 /* Simplices */ 9209 faceSize = numCorners-1; 9210 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9211 } else if (cellDim == 1 && numCorners == 3) { 9212 /* Quadratic line */ 9213 faceSize = 1; 9214 posOrient = PETSC_TRUE; 9215 } else if (cellDim == 2 && numCorners == 4) { 9216 /* Quads */ 9217 faceSize = 2; 9218 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9219 posOrient = PETSC_TRUE; 9220 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9221 posOrient = PETSC_TRUE; 9222 } else { 9223 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9224 posOrient = PETSC_FALSE; 9225 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9226 } 9227 } else if (cellDim == 2 && numCorners == 6) { 9228 /* Quadratic triangle (I hate this) */ 9229 /* Edges are determined by the first 2 vertices (corners of edges) */ 9230 const PetscInt faceSizeTri = 3; 9231 PetscInt sortedIndices[3], i, iFace; 9232 PetscBool found = PETSC_FALSE; 9233 PetscInt faceVerticesTriSorted[9] = { 9234 0, 3, 4, /* bottom */ 9235 1, 4, 5, /* right */ 9236 2, 3, 5, /* left */ 9237 }; 9238 PetscInt faceVerticesTri[9] = { 9239 0, 3, 4, /* bottom */ 9240 1, 4, 5, /* right */ 9241 2, 5, 3, /* left */ 9242 }; 9243 9244 faceSize = faceSizeTri; 9245 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9246 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9247 for (iFace = 0; iFace < 3; ++iFace) { 9248 const PetscInt ii = iFace*faceSizeTri; 9249 PetscInt fVertex, cVertex; 9250 9251 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9252 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9253 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9254 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9255 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9256 faceVertices[fVertex] = origVertices[cVertex]; 9257 break; 9258 } 9259 } 9260 } 9261 found = PETSC_TRUE; 9262 break; 9263 } 9264 } 9265 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9266 if (posOriented) *posOriented = PETSC_TRUE; 9267 PetscFunctionReturn(0); 9268 } else if (cellDim == 2 && numCorners == 9) { 9269 /* Quadratic quad (I hate this) */ 9270 /* Edges are determined by the first 2 vertices (corners of edges) */ 9271 const PetscInt faceSizeQuad = 3; 9272 PetscInt sortedIndices[3], i, iFace; 9273 PetscBool found = PETSC_FALSE; 9274 PetscInt faceVerticesQuadSorted[12] = { 9275 0, 1, 4, /* bottom */ 9276 1, 2, 5, /* right */ 9277 2, 3, 6, /* top */ 9278 0, 3, 7, /* left */ 9279 }; 9280 PetscInt faceVerticesQuad[12] = { 9281 0, 1, 4, /* bottom */ 9282 1, 2, 5, /* right */ 9283 2, 3, 6, /* top */ 9284 3, 0, 7, /* left */ 9285 }; 9286 9287 faceSize = faceSizeQuad; 9288 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9289 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9290 for (iFace = 0; iFace < 4; ++iFace) { 9291 const PetscInt ii = iFace*faceSizeQuad; 9292 PetscInt fVertex, cVertex; 9293 9294 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9295 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9296 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9297 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9298 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9299 faceVertices[fVertex] = origVertices[cVertex]; 9300 break; 9301 } 9302 } 9303 } 9304 found = PETSC_TRUE; 9305 break; 9306 } 9307 } 9308 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9309 if (posOriented) *posOriented = PETSC_TRUE; 9310 PetscFunctionReturn(0); 9311 } else if (cellDim == 3 && numCorners == 8) { 9312 /* Hexes 9313 A hex is two oriented quads with the normal of the first 9314 pointing up at the second. 9315 9316 7---6 9317 /| /| 9318 4---5 | 9319 | 3-|-2 9320 |/ |/ 9321 0---1 9322 9323 Faces are determined by the first 4 vertices (corners of faces) */ 9324 const PetscInt faceSizeHex = 4; 9325 PetscInt sortedIndices[4], i, iFace; 9326 PetscBool found = PETSC_FALSE; 9327 PetscInt faceVerticesHexSorted[24] = { 9328 0, 1, 2, 3, /* bottom */ 9329 4, 5, 6, 7, /* top */ 9330 0, 1, 4, 5, /* front */ 9331 1, 2, 5, 6, /* right */ 9332 2, 3, 6, 7, /* back */ 9333 0, 3, 4, 7, /* left */ 9334 }; 9335 PetscInt faceVerticesHex[24] = { 9336 3, 2, 1, 0, /* bottom */ 9337 4, 5, 6, 7, /* top */ 9338 0, 1, 5, 4, /* front */ 9339 1, 2, 6, 5, /* right */ 9340 2, 3, 7, 6, /* back */ 9341 3, 0, 4, 7, /* left */ 9342 }; 9343 9344 faceSize = faceSizeHex; 9345 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9346 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9347 for (iFace = 0; iFace < 6; ++iFace) { 9348 const PetscInt ii = iFace*faceSizeHex; 9349 PetscInt fVertex, cVertex; 9350 9351 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9352 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9353 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9354 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9355 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9356 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9357 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9358 faceVertices[fVertex] = origVertices[cVertex]; 9359 break; 9360 } 9361 } 9362 } 9363 found = PETSC_TRUE; 9364 break; 9365 } 9366 } 9367 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9368 if (posOriented) *posOriented = PETSC_TRUE; 9369 PetscFunctionReturn(0); 9370 } else if (cellDim == 3 && numCorners == 10) { 9371 /* Quadratic tet */ 9372 /* Faces are determined by the first 3 vertices (corners of faces) */ 9373 const PetscInt faceSizeTet = 6; 9374 PetscInt sortedIndices[6], i, iFace; 9375 PetscBool found = PETSC_FALSE; 9376 PetscInt faceVerticesTetSorted[24] = { 9377 0, 1, 2, 6, 7, 8, /* bottom */ 9378 0, 3, 4, 6, 7, 9, /* front */ 9379 1, 4, 5, 7, 8, 9, /* right */ 9380 2, 3, 5, 6, 8, 9, /* left */ 9381 }; 9382 PetscInt faceVerticesTet[24] = { 9383 0, 1, 2, 6, 7, 8, /* bottom */ 9384 0, 4, 3, 6, 7, 9, /* front */ 9385 1, 5, 4, 7, 8, 9, /* right */ 9386 2, 3, 5, 8, 6, 9, /* left */ 9387 }; 9388 9389 faceSize = faceSizeTet; 9390 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9391 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9392 for (iFace=0; iFace < 4; ++iFace) { 9393 const PetscInt ii = iFace*faceSizeTet; 9394 PetscInt fVertex, cVertex; 9395 9396 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9397 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9398 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9399 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9400 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9401 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9402 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9403 faceVertices[fVertex] = origVertices[cVertex]; 9404 break; 9405 } 9406 } 9407 } 9408 found = PETSC_TRUE; 9409 break; 9410 } 9411 } 9412 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9413 if (posOriented) *posOriented = PETSC_TRUE; 9414 PetscFunctionReturn(0); 9415 } else if (cellDim == 3 && numCorners == 27) { 9416 /* Quadratic hexes (I hate this) 9417 A hex is two oriented quads with the normal of the first 9418 pointing up at the second. 9419 9420 7---6 9421 /| /| 9422 4---5 | 9423 | 3-|-2 9424 |/ |/ 9425 0---1 9426 9427 Faces are determined by the first 4 vertices (corners of faces) */ 9428 const PetscInt faceSizeQuadHex = 9; 9429 PetscInt sortedIndices[9], i, iFace; 9430 PetscBool found = PETSC_FALSE; 9431 PetscInt faceVerticesQuadHexSorted[54] = { 9432 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9433 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9434 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9435 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9436 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9437 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9438 }; 9439 PetscInt faceVerticesQuadHex[54] = { 9440 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9441 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9442 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9443 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9444 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9445 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9446 }; 9447 9448 faceSize = faceSizeQuadHex; 9449 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9450 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9451 for (iFace = 0; iFace < 6; ++iFace) { 9452 const PetscInt ii = iFace*faceSizeQuadHex; 9453 PetscInt fVertex, cVertex; 9454 9455 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9456 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9457 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9458 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9459 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9460 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9461 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9462 faceVertices[fVertex] = origVertices[cVertex]; 9463 break; 9464 } 9465 } 9466 } 9467 found = PETSC_TRUE; 9468 break; 9469 } 9470 } 9471 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9472 if (posOriented) *posOriented = PETSC_TRUE; 9473 PetscFunctionReturn(0); 9474 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9475 if (!posOrient) { 9476 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9477 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize-1 - f]; 9478 } else { 9479 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9480 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f]; 9481 } 9482 if (posOriented) *posOriented = posOrient; 9483 PetscFunctionReturn(0); 9484 } 9485 9486 #undef __FUNCT__ 9487 #define __FUNCT__ "DMPlexGetOrientedFace" 9488 /* 9489 Given a cell and a face, as a set of vertices, 9490 return the oriented face, as a set of vertices, in faceVertices 9491 The orientation is such that the face normal points out of the cell 9492 */ 9493 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9494 { 9495 const PetscInt *cone = PETSC_NULL; 9496 PetscInt coneSize, v, f, v2; 9497 PetscInt oppositeVertex = -1; 9498 PetscErrorCode ierr; 9499 9500 PetscFunctionBegin; 9501 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9502 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9503 for (v = 0, v2 = 0; v < coneSize; ++v) { 9504 PetscBool found = PETSC_FALSE; 9505 9506 for (f = 0; f < faceSize; ++f) { 9507 if (face[f] == cone[v]) { 9508 found = PETSC_TRUE; break; 9509 } 9510 } 9511 if (found) { 9512 indices[v2] = v; 9513 origVertices[v2] = cone[v]; 9514 ++v2; 9515 } else { 9516 oppositeVertex = v; 9517 } 9518 } 9519 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9520 PetscFunctionReturn(0); 9521 } 9522 9523 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9524 { 9525 switch (i) { 9526 case 0: 9527 switch (j) { 9528 case 0: return 0; 9529 case 1: 9530 switch (k) { 9531 case 0: return 0; 9532 case 1: return 0; 9533 case 2: return 1; 9534 } 9535 case 2: 9536 switch (k) { 9537 case 0: return 0; 9538 case 1: return -1; 9539 case 2: return 0; 9540 } 9541 } 9542 case 1: 9543 switch (j) { 9544 case 0: 9545 switch (k) { 9546 case 0: return 0; 9547 case 1: return 0; 9548 case 2: return -1; 9549 } 9550 case 1: return 0; 9551 case 2: 9552 switch (k) { 9553 case 0: return 1; 9554 case 1: return 0; 9555 case 2: return 0; 9556 } 9557 } 9558 case 2: 9559 switch (j) { 9560 case 0: 9561 switch (k) { 9562 case 0: return 0; 9563 case 1: return 1; 9564 case 2: return 0; 9565 } 9566 case 1: 9567 switch (k) { 9568 case 0: return -1; 9569 case 1: return 0; 9570 case 2: return 0; 9571 } 9572 case 2: return 0; 9573 } 9574 } 9575 return 0; 9576 } 9577 9578 #undef __FUNCT__ 9579 #define __FUNCT__ "DMPlexCreateRigidBody" 9580 /*@C 9581 DMPlexCreateRigidBody - create rigid body modes from coordinates 9582 9583 Collective on DM 9584 9585 Input Arguments: 9586 + dm - the DM 9587 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9588 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9589 9590 Output Argument: 9591 . sp - the null space 9592 9593 Note: This is necessary to take account of Dirichlet conditions on the displacements 9594 9595 Level: advanced 9596 9597 .seealso: MatNullSpaceCreate() 9598 @*/ 9599 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9600 { 9601 MPI_Comm comm = ((PetscObject) dm)->comm; 9602 Vec coordinates, localMode, mode[6]; 9603 PetscSection coordSection; 9604 PetscScalar *coords; 9605 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9606 PetscErrorCode ierr; 9607 9608 PetscFunctionBegin; 9609 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9610 if (dim == 1) { 9611 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9612 PetscFunctionReturn(0); 9613 } 9614 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9615 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9616 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9617 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9618 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9619 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9620 m = (dim*(dim+1))/2; 9621 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9622 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9623 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9624 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9625 /* Assume P1 */ 9626 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9627 for (d = 0; d < dim; ++d) { 9628 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9629 9630 values[d] = 1.0; 9631 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9632 for (v = vStart; v < vEnd; ++v) { 9633 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9634 } 9635 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9636 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9637 } 9638 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9639 for (d = dim; d < dim*(dim+1)/2; ++d) { 9640 PetscInt i, j, k = dim > 2 ? d - dim : d; 9641 9642 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9643 for (v = vStart; v < vEnd; ++v) { 9644 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9645 PetscInt off; 9646 9647 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9648 for (i = 0; i < dim; ++i) { 9649 for (j = 0; j < dim; ++j) { 9650 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9651 } 9652 } 9653 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9654 } 9655 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9656 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9657 } 9658 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9659 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9660 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9661 /* Orthonormalize system */ 9662 for (i = dim; i < m; ++i) { 9663 PetscScalar dots[6]; 9664 9665 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9666 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9667 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9668 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9669 } 9670 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9671 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9672 PetscFunctionReturn(0); 9673 } 9674 9675 #undef __FUNCT__ 9676 #define __FUNCT__ "DMPlexGetHybridBounds" 9677 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9678 { 9679 DM_Plex *mesh = (DM_Plex*) dm->data; 9680 PetscInt dim; 9681 PetscErrorCode ierr; 9682 9683 PetscFunctionBegin; 9684 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9685 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9686 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9687 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9688 if (eMax) *eMax = mesh->hybridPointMax[1]; 9689 if (vMax) *vMax = mesh->hybridPointMax[0]; 9690 PetscFunctionReturn(0); 9691 } 9692 9693 #undef __FUNCT__ 9694 #define __FUNCT__ "DMPlexSetHybridBounds" 9695 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9696 { 9697 DM_Plex *mesh = (DM_Plex*) dm->data; 9698 PetscInt dim; 9699 PetscErrorCode ierr; 9700 9701 PetscFunctionBegin; 9702 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9703 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9704 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9705 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9706 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9707 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9708 PetscFunctionReturn(0); 9709 } 9710 9711 #undef __FUNCT__ 9712 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9713 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9714 { 9715 DM_Plex *mesh = (DM_Plex*) dm->data; 9716 9717 PetscFunctionBegin; 9718 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9719 PetscValidPointer(cellHeight, 2); 9720 *cellHeight = mesh->vtkCellHeight; 9721 PetscFunctionReturn(0); 9722 } 9723 9724 #undef __FUNCT__ 9725 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9726 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9727 { 9728 DM_Plex *mesh = (DM_Plex*) dm->data; 9729 9730 PetscFunctionBegin; 9731 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9732 mesh->vtkCellHeight = cellHeight; 9733 PetscFunctionReturn(0); 9734 } 9735 9736 #undef __FUNCT__ 9737 #define __FUNCT__ "DMPlexInsertFace_Private" 9738 /* 9739 DMPlexInsertFace_Private - Puts a face into the mesh 9740 9741 Not collective 9742 9743 Input Parameters: 9744 + dm - The DMPlex 9745 . numFaceVertex - The number of vertices in the face 9746 . faceVertices - The vertices in the face for dm 9747 . subfaceVertices - The vertices in the face for subdm 9748 . numCorners - The number of vertices in the cell 9749 . cell - A cell in dm containing the face 9750 . subcell - A cell in subdm containing the face 9751 . firstFace - First face in the mesh 9752 - newFacePoint - Next face in the mesh 9753 9754 Output Parameters: 9755 . newFacePoint - Contains next face point number on input, updated on output 9756 9757 Level: developer 9758 */ 9759 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) 9760 { 9761 MPI_Comm comm = ((PetscObject) dm)->comm; 9762 DM_Plex *submesh = (DM_Plex*) subdm->data; 9763 const PetscInt *faces; 9764 PetscInt numFaces, coneSize; 9765 PetscErrorCode ierr; 9766 9767 PetscFunctionBegin; 9768 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9769 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9770 #if 0 9771 /* Cannot use this because support() has not been constructed yet */ 9772 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9773 #else 9774 { 9775 PetscInt f; 9776 9777 numFaces = 0; 9778 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void**) &faces);CHKERRQ(ierr); 9779 for (f = firstFace; f < *newFacePoint; ++f) { 9780 PetscInt dof, off, d; 9781 9782 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9783 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9784 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9785 for (d = 0; d < dof; ++d) { 9786 const PetscInt p = submesh->cones[off+d]; 9787 PetscInt v; 9788 9789 for (v = 0; v < numFaceVertices; ++v) { 9790 if (subfaceVertices[v] == p) break; 9791 } 9792 if (v == numFaceVertices) break; 9793 } 9794 if (d == dof) { 9795 numFaces = 1; 9796 ((PetscInt*) faces)[0] = f; 9797 } 9798 } 9799 } 9800 #endif 9801 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 9802 else if (numFaces == 1) { 9803 /* Add the other cell neighbor for this face */ 9804 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 9805 } else { 9806 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 9807 PetscBool posOriented; 9808 9809 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9810 origVertices = &orientedVertices[numFaceVertices]; 9811 indices = &orientedVertices[numFaceVertices*2]; 9812 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 9813 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 9814 /* TODO: I know that routine should return a permutation, not the indices */ 9815 for (v = 0; v < numFaceVertices; ++v) { 9816 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 9817 for (ov = 0; ov < numFaceVertices; ++ov) { 9818 if (orientedVertices[ov] == vertex) { 9819 orientedSubVertices[ov] = subvertex; 9820 break; 9821 } 9822 } 9823 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 9824 } 9825 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 9826 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 9827 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9828 ++(*newFacePoint); 9829 } 9830 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9831 PetscFunctionReturn(0); 9832 } 9833 9834 #undef __FUNCT__ 9835 #define __FUNCT__ "DMPlexCreateSubmesh_Uninterpolated" 9836 static PetscErrorCode DMPlexCreateSubmesh_Uninterpolated(DM dm, const char label[], DM subdm) 9837 { 9838 MPI_Comm comm = ((PetscObject) dm)->comm; 9839 PetscBool boundaryFaces = PETSC_FALSE; 9840 PetscSection coordSection, subCoordSection; 9841 Vec coordinates, subCoordinates; 9842 PetscScalar *coords, *subCoords; 9843 DMLabel subpointMap; 9844 IS labelIS; 9845 const PetscInt *subVertices; 9846 PetscInt *subVerticesActive; 9847 PetscInt *subCells = PETSC_NULL; 9848 PetscInt numSubVertices = 0, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 9849 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 9850 PetscInt dim; /* Right now, do not specify dimension */ 9851 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 9852 PetscErrorCode ierr; 9853 9854 PetscFunctionBegin; 9855 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9856 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9857 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9858 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 9859 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9860 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9861 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9862 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9863 subface = &face[maxConeSize]; 9864 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 9865 if (labelIS) { 9866 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 9867 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 9868 } 9869 maxSubCells = numSubVertices; 9870 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 9871 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 9872 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 9873 for (v = 0; v < numSubVertices; ++v) { 9874 const PetscInt vertex = subVertices[v]; 9875 PetscInt *star = PETSC_NULL; 9876 PetscInt starSize, numCells = 0; 9877 9878 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9879 for (p = 0; p < starSize*2; p += 2) { 9880 const PetscInt point = star[p]; 9881 if ((point >= cStart) && (point < cEnd)) star[numCells++] = point; 9882 } 9883 numOldSubCells = numSubCells; 9884 for (c = 0; c < numCells; ++c) { 9885 const PetscInt cell = star[c]; 9886 PetscInt *closure = PETSC_NULL; 9887 PetscInt closureSize, numCorners = 0, faceSize = 0; 9888 PetscInt cellLoc; 9889 9890 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 9891 if (cellLoc >= 0) continue; 9892 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9893 for (p = 0; p < closureSize*2; p += 2) { 9894 const PetscInt point = closure[p]; 9895 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 9896 } 9897 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9898 for (corner = 0; corner < numCorners; ++corner) { 9899 const PetscInt cellVertex = closure[corner]; 9900 PetscInt subVertex; 9901 9902 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9903 if (subVertex >= 0) { /* contains submesh vertex */ 9904 for (i = 0; i < faceSize; ++i) { 9905 if (cellVertex == face[i]) break; 9906 } 9907 if (i == faceSize) { 9908 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9909 face[faceSize] = cellVertex; 9910 subface[faceSize] = subVertex; 9911 ++faceSize; 9912 } 9913 } 9914 } 9915 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9916 if (faceSize >= nFV) { 9917 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9918 if (numSubCells >= maxSubCells) { 9919 PetscInt *tmpCells; 9920 maxSubCells *= 2; 9921 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9922 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9923 ierr = PetscFree(subCells);CHKERRQ(ierr); 9924 9925 subCells = tmpCells; 9926 } 9927 /* TOOD: Maybe overestimate then squeeze out empty faces */ 9928 if (faceSize > nFV) { 9929 /* TODO: This is tricky. Maybe just add all faces */ 9930 numSubFaces++; 9931 } else { 9932 numSubFaces++; 9933 } 9934 for (f = 0; f < faceSize; ++f) subVerticesActive[subface[f]] = 1; 9935 subCells[numSubCells++] = cell; 9936 } 9937 } 9938 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9939 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9940 } 9941 /* Pick out active subvertices */ 9942 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9943 if (subVerticesActive[v]) { 9944 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9945 } 9946 } 9947 ierr = DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9948 /* Set cone sizes */ 9949 firstSubVertex = numSubCells; 9950 firstSubFace = numSubCells+numSubVerticesActive; 9951 newFacePoint = firstSubFace; 9952 for (c = 0; c < numSubCells; ++c) { 9953 ierr = DMPlexSetConeSize(subdm, c, 1);CHKERRQ(ierr); 9954 } 9955 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9956 ierr = DMPlexSetConeSize(subdm, f, nFV);CHKERRQ(ierr); 9957 } 9958 ierr = DMSetUp(subdm);CHKERRQ(ierr); 9959 /* Create face cones */ 9960 for (c = 0; c < numSubCells; ++c) { 9961 const PetscInt cell = subCells[c]; 9962 PetscInt *closure = PETSC_NULL; 9963 PetscInt closureSize, numCorners = 0, faceSize = 0; 9964 9965 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9966 for (p = 0; p < closureSize*2; p += 2) { 9967 const PetscInt point = closure[p]; 9968 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 9969 } 9970 for (corner = 0; corner < numCorners; ++corner) { 9971 const PetscInt cellVertex = closure[corner]; 9972 PetscInt subVertex; 9973 9974 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9975 if (subVertex >= 0) { /* contains submesh vertex */ 9976 for (i = 0; i < faceSize; ++i) { 9977 if (cellVertex == face[i]) break; 9978 } 9979 if (i == faceSize) { 9980 face[faceSize] = cellVertex; 9981 subface[faceSize] = numSubCells+subVertex; 9982 ++faceSize; 9983 } 9984 } 9985 } 9986 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9987 if (faceSize >= nFV) { 9988 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9989 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 9990 /* We have to take all the faces, and discard those in the interior */ 9991 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 9992 #if 0 9993 /* This object just calls insert on each face that comes from subsets() */ 9994 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 9995 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9996 PointArray faceVec(face->begin(), face->end()); 9997 9998 subsets(faceVec, nFV, inserter); 9999 #endif 10000 ierr = DMPlexInsertFace_Private(dm, subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 10001 } 10002 } 10003 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 10004 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 10005 /* Build coordinates */ 10006 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10007 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10008 ierr = DMPlexGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 10009 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 10010 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 10011 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 10012 } 10013 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10014 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10015 ierr = VecCreate(comm, &subCoordinates);CHKERRQ(ierr); 10016 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10017 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10018 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10019 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10020 for (v = 0; v < numSubVerticesActive; ++v) { 10021 const PetscInt vertex = subVerticesActive[v]; 10022 const PetscInt subVertex = firstSubVertex+v; 10023 PetscInt dof, off, sdof, soff; 10024 10025 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10026 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10027 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10028 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10029 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10030 for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d]; 10031 } 10032 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10033 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10034 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 10035 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10036 10037 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 10038 /* Create map from submesh points to original mesh points */ 10039 ierr = DMLabelCreate("subpoint_map", &subpointMap);CHKERRQ(ierr); 10040 for (c = 0; c < numSubCells; ++c) {ierr = DMLabelSetValue(subpointMap, subCells[c], 1);CHKERRQ(ierr);} 10041 for (v = 0; v < numSubVerticesActive; ++v) {ierr = DMLabelSetValue(subpointMap, subVerticesActive[v], 0);CHKERRQ(ierr);} 10042 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 10043 ierr = DMLabelDestroy(&subpointMap);CHKERRQ(ierr); 10044 10045 ierr = PetscFree(subCells);CHKERRQ(ierr); 10046 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10047 if (labelIS) { 10048 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10049 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10050 } 10051 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10052 PetscFunctionReturn(0); 10053 } 10054 10055 #undef __FUNCT__ 10056 #define __FUNCT__ "DMPlexCreateSubmesh_Interpolated" 10057 static PetscErrorCode DMPlexCreateSubmesh_Interpolated(DM dm, const char vertexLabelName[], DM subdm) 10058 { 10059 MPI_Comm comm = ((PetscObject) dm)->comm; 10060 DMLabel subpointMap, vertexLabel; 10061 IS *subpointIS, subvertexIS; 10062 const PetscInt **subpoints, *subvertices; 10063 PetscInt *pStart, *pEnd, *numSubPoints, *firstSubPoint, *coneNew; 10064 PetscInt numSubVerticesInitial, totSubPoints = 0, maxConeSize, dim, p, d, v; 10065 PetscErrorCode ierr; 10066 10067 PetscFunctionBegin; 10068 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10069 ierr = PetscMalloc6(dim+1,PetscInt,&pStart,dim+1,PetscInt,&pEnd,dim+1,PetscInt,&numSubPoints,dim+1,PetscInt,&firstSubPoint,dim+1,IS,&subpointIS,dim+1,const PetscInt *,&subpoints);CHKERRQ(ierr); 10070 for (d = 0; d <= dim; ++d) { 10071 ierr = DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d]);CHKERRQ(ierr); 10072 } 10073 ierr = DMLabelCreate("subpoint_map", &subpointMap);CHKERRQ(ierr); 10074 ierr = DMPlexGetLabel(dm, vertexLabelName, &vertexLabel);CHKERRQ(ierr); 10075 ierr = DMLabelGetStratumIS(vertexLabel, 1, &subvertexIS);CHKERRQ(ierr); 10076 ierr = ISGetSize(subvertexIS, &numSubVerticesInitial);CHKERRQ(ierr); 10077 ierr = ISGetIndices(subvertexIS, &subvertices);CHKERRQ(ierr); 10078 /* Loop over initial vertices and mark all faces in the collective star() */ 10079 for (v = 0; v < numSubVerticesInitial; ++v) { 10080 const PetscInt vertex = subvertices[v]; 10081 PetscInt *star = PETSC_NULL; 10082 PetscInt starSize, s, numFaces = 0, f; 10083 10084 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10085 for (s = 0; s < starSize*2; s += 2) { 10086 const PetscInt point = star[s]; 10087 if ((point >= pStart[dim-1]) && (point < pEnd[dim-1])) { 10088 star[numFaces++] = point; 10089 } 10090 } 10091 for (f = 0; f < numFaces; ++f) { 10092 const PetscInt face = star[f]; 10093 PetscInt *closure = PETSC_NULL; 10094 PetscInt closureSize, c; 10095 PetscInt faceLoc; 10096 10097 ierr = DMLabelGetValue(subpointMap, face, &faceLoc);CHKERRQ(ierr); 10098 if (faceLoc == dim-1) continue; 10099 if (faceLoc >= 0) SETERRQ2(comm, PETSC_ERR_PLIB, "Face %d has dimension %d in the surface label", face, faceLoc); 10100 ierr = DMPlexGetTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10101 for (c = 0; c < closureSize*2; c += 2) { 10102 const PetscInt point = closure[c]; 10103 PetscInt vertexLoc; 10104 10105 if ((point >= pStart[0]) && (point < pEnd[0])) { 10106 ierr = DMLabelGetValue(vertexLabel, point, &vertexLoc);CHKERRQ(ierr); 10107 if (vertexLoc < 0) break; 10108 } 10109 } 10110 if (c == closureSize*2) { 10111 const PetscInt *support; 10112 PetscInt supportSize, s; 10113 10114 for (c = 0; c < closureSize*2; c += 2) { 10115 const PetscInt point = closure[c]; 10116 10117 for (d = 0; d < dim; ++d) { 10118 if ((point >= pStart[d]) && (point < pEnd[d])) { 10119 ierr = DMLabelSetValue(subpointMap, point, d);CHKERRQ(ierr); 10120 break; 10121 } 10122 } 10123 } 10124 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10125 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10126 for (s = 0; s < supportSize; ++s) { 10127 ierr = DMLabelSetValue(subpointMap, support[s], dim);CHKERRQ(ierr); 10128 } 10129 } 10130 ierr = DMPlexRestoreTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10131 } 10132 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10133 } 10134 ierr = ISRestoreIndices(subvertexIS, &subvertices);CHKERRQ(ierr); 10135 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 10136 for (d = 0; d <= dim; ++d) { 10137 ierr = DMLabelGetStratumSize(subpointMap, d, &numSubPoints[d]);CHKERRQ(ierr); 10138 totSubPoints += numSubPoints[d]; 10139 } 10140 ierr = DMPlexSetChart(subdm, 0, totSubPoints);CHKERRQ(ierr); 10141 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 10142 /* Set cone sizes */ 10143 firstSubPoint[dim] = 0; 10144 firstSubPoint[0] = firstSubPoint[dim] + numSubPoints[dim]; 10145 if (dim > 1) {firstSubPoint[dim-1] = firstSubPoint[0] + numSubPoints[0];} 10146 if (dim > 2) {firstSubPoint[dim-2] = firstSubPoint[dim-1] + numSubPoints[dim-1];} 10147 for (d = 0; d <= dim; ++d) { 10148 ierr = DMLabelGetStratumIS(subpointMap, d, &subpointIS[d]);CHKERRQ(ierr); 10149 ierr = ISGetIndices(subpointIS[d], &subpoints[d]);CHKERRQ(ierr); 10150 } 10151 for (d = 0; d <= dim; ++d) { 10152 for (p = 0; p < numSubPoints[d]; ++p) { 10153 const PetscInt point = subpoints[d][p]; 10154 const PetscInt subpoint = firstSubPoint[d] + p; 10155 const PetscInt *cone; 10156 PetscInt coneSize, coneSizeNew, c, val; 10157 10158 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 10159 ierr = DMPlexSetConeSize(subdm, subpoint, coneSize);CHKERRQ(ierr); 10160 if (d == dim) { 10161 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 10162 for (c = 0, coneSizeNew = 0; c < coneSize; ++c) { 10163 ierr = DMLabelGetValue(subpointMap, cone[c], &val);CHKERRQ(ierr); 10164 if (val >= 0) coneSizeNew++; 10165 } 10166 ierr = DMPlexSetConeSize(subdm, subpoint, coneSizeNew);CHKERRQ(ierr); 10167 } 10168 } 10169 } 10170 ierr = DMSetUp(subdm);CHKERRQ(ierr); 10171 /* Set cones */ 10172 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 10173 ierr = PetscMalloc(maxConeSize * sizeof(PetscInt), &coneNew);CHKERRQ(ierr); 10174 for (d = 0; d <= dim; ++d) { 10175 for (p = 0; p < numSubPoints[d]; ++p) { 10176 const PetscInt point = subpoints[d][p]; 10177 const PetscInt subpoint = firstSubPoint[d] + p; 10178 const PetscInt *cone; 10179 PetscInt coneSize, subconeSize, coneSizeNew, c, subc; 10180 10181 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 10182 ierr = DMPlexGetConeSize(subdm, subpoint, &subconeSize);CHKERRQ(ierr); 10183 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 10184 for (c = 0, coneSizeNew = 0; c < coneSize; ++c) { 10185 ierr = PetscFindInt(cone[c], numSubPoints[d-1], subpoints[d-1], &subc);CHKERRQ(ierr); 10186 if (subc >= 0) coneNew[coneSizeNew++] = firstSubPoint[d-1] + subc; 10187 } 10188 if (coneSizeNew != subconeSize) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of cone points located %d does not match subcone size %d", coneSizeNew, subconeSize); 10189 ierr = DMPlexSetCone(subdm, subpoint, coneNew);CHKERRQ(ierr); 10190 } 10191 } 10192 ierr = PetscFree(coneNew);CHKERRQ(ierr); 10193 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 10194 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 10195 /* Build coordinates */ 10196 { 10197 PetscSection coordSection, subCoordSection; 10198 Vec coordinates, subCoordinates; 10199 PetscScalar *coords, *subCoords; 10200 PetscInt coordSize; 10201 10202 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10203 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10204 ierr = DMPlexGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 10205 ierr = PetscSectionSetChart(subCoordSection, firstSubPoint[0], firstSubPoint[0]+numSubPoints[0]);CHKERRQ(ierr); 10206 for (v = 0; v < numSubPoints[0]; ++v) { 10207 const PetscInt vertex = subpoints[0][v]; 10208 const PetscInt subvertex = firstSubPoint[0]+v; 10209 PetscInt dof; 10210 10211 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10212 ierr = PetscSectionSetDof(subCoordSection, subvertex, dof);CHKERRQ(ierr); 10213 } 10214 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10215 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10216 ierr = VecCreate(comm, &subCoordinates);CHKERRQ(ierr); 10217 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10218 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10219 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10220 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10221 for (v = 0; v < numSubPoints[0]; ++v) { 10222 const PetscInt vertex = subpoints[0][v]; 10223 const PetscInt subvertex = firstSubPoint[0]+v; 10224 PetscInt dof, off, sdof, soff, d; 10225 10226 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10227 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10228 ierr = PetscSectionGetDof(subCoordSection, subvertex, &sdof);CHKERRQ(ierr); 10229 ierr = PetscSectionGetOffset(subCoordSection, subvertex, &soff);CHKERRQ(ierr); 10230 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subvertex, vertex, dof); 10231 for (d = 0; d < dof; ++d) { 10232 subCoords[soff+d] = coords[off+d]; 10233 } 10234 } 10235 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10236 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10237 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 10238 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10239 } 10240 for (d = 0; d <= dim; ++d) { 10241 ierr = ISRestoreIndices(subpointIS[d], &subpoints[d]);CHKERRQ(ierr); 10242 ierr = ISDestroy(&subpointIS[d]);CHKERRQ(ierr); 10243 } 10244 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 10245 ierr = DMLabelDestroy(&subpointMap);CHKERRQ(ierr); 10246 PetscFunctionReturn(0); 10247 } 10248 10249 #undef __FUNCT__ 10250 #define __FUNCT__ "DMPlexCreateSubmesh" 10251 /* 10252 DMPlexCreateSubmesh - Extract a hypersurface from the mesh using vertices defined by a label 10253 10254 Input Parameters: 10255 + dm - The original mesh 10256 - vertexLabel - The DMLabel marking vertices contained in the surface 10257 10258 Output Parameter: 10259 . subdm - The surface mesh 10260 10261 Note: This function produces a DMLabel mapping original points in the submesh to their depth. This can be obtained using DMPlexGetSubpointMap(). 10262 10263 Level: developer 10264 10265 .seealso: DMPlexGetSubpointMap(), DMPlexGetLabel(), DMLabelSetValue() 10266 */ 10267 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char vertexLabel[], DM *subdm) 10268 { 10269 PetscInt dim, depth; 10270 PetscErrorCode ierr; 10271 10272 PetscFunctionBegin; 10273 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10274 PetscValidCharPointer(vertexLabel, 2); 10275 PetscValidPointer(subdm, 4); 10276 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10277 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 10278 ierr = DMCreate(((PetscObject) dm)->comm, subdm);CHKERRQ(ierr); 10279 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 10280 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 10281 /* TODO Remove the dim guard */ 10282 if ((dim > 1) && (depth == dim)) { 10283 ierr = DMPlexCreateSubmesh_Interpolated(dm, vertexLabel, *subdm);CHKERRQ(ierr); 10284 } else { 10285 ierr = DMPlexCreateSubmesh_Uninterpolated(dm, vertexLabel, *subdm);CHKERRQ(ierr); 10286 } 10287 PetscFunctionReturn(0); 10288 } 10289 10290 #undef __FUNCT__ 10291 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10292 /* We can easily have a form that takes an IS instead */ 10293 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10294 { 10295 PetscSection section, globalSection; 10296 PetscInt *numbers, p; 10297 PetscErrorCode ierr; 10298 10299 PetscFunctionBegin; 10300 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10301 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10302 for (p = pStart; p < pEnd; ++p) { 10303 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10304 } 10305 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10306 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10307 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10308 for (p = pStart; p < pEnd; ++p) { 10309 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10310 } 10311 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10312 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10313 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10314 PetscFunctionReturn(0); 10315 } 10316 10317 #undef __FUNCT__ 10318 #define __FUNCT__ "DMPlexGetCellNumbering" 10319 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10320 { 10321 DM_Plex *mesh = (DM_Plex*) dm->data; 10322 PetscInt cellHeight, cStart, cEnd, cMax; 10323 PetscErrorCode ierr; 10324 10325 PetscFunctionBegin; 10326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10327 if (!mesh->globalCellNumbers) { 10328 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10329 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10330 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10331 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 10332 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10333 } 10334 *globalCellNumbers = mesh->globalCellNumbers; 10335 PetscFunctionReturn(0); 10336 } 10337 10338 #undef __FUNCT__ 10339 #define __FUNCT__ "DMPlexGetVertexNumbering" 10340 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10341 { 10342 DM_Plex *mesh = (DM_Plex*) dm->data; 10343 PetscInt vStart, vEnd, vMax; 10344 PetscErrorCode ierr; 10345 10346 PetscFunctionBegin; 10347 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10348 if (!mesh->globalVertexNumbers) { 10349 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10350 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10351 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 10352 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10353 } 10354 *globalVertexNumbers = mesh->globalVertexNumbers; 10355 PetscFunctionReturn(0); 10356 } 10357 10358 #undef __FUNCT__ 10359 #define __FUNCT__ "DMPlexGetSubpointMap" 10360 PetscErrorCode DMPlexGetSubpointMap(DM dm, DMLabel *subpointMap) 10361 { 10362 DM_Plex *mesh = (DM_Plex*) dm->data; 10363 10364 PetscFunctionBegin; 10365 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10366 PetscValidPointer(subpointMap, 2); 10367 *subpointMap = mesh->subpointMap; 10368 PetscFunctionReturn(0); 10369 } 10370 10371 #undef __FUNCT__ 10372 #define __FUNCT__ "DMPlexSetSubpointMap" 10373 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10374 PetscErrorCode DMPlexSetSubpointMap(DM dm, DMLabel subpointMap) 10375 { 10376 DM_Plex *mesh = (DM_Plex*) dm->data; 10377 PetscErrorCode ierr; 10378 10379 PetscFunctionBegin; 10380 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10381 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 10382 mesh->subpointMap = subpointMap; 10383 ++mesh->subpointMap->refct;CHKERRQ(ierr); 10384 PetscFunctionReturn(0); 10385 } 10386 10387 #undef __FUNCT__ 10388 #define __FUNCT__ "DMPlexGetScale" 10389 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10390 { 10391 DM_Plex *mesh = (DM_Plex*) dm->data; 10392 10393 PetscFunctionBegin; 10394 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10395 PetscValidPointer(scale, 3); 10396 *scale = mesh->scale[unit]; 10397 PetscFunctionReturn(0); 10398 } 10399 10400 #undef __FUNCT__ 10401 #define __FUNCT__ "DMPlexSetScale" 10402 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10403 { 10404 DM_Plex *mesh = (DM_Plex*) dm->data; 10405 10406 PetscFunctionBegin; 10407 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10408 mesh->scale[unit] = scale; 10409 PetscFunctionReturn(0); 10410 } 10411 10412 10413 /******************************************************************************* 10414 This should be in a separate Discretization object, but I am not sure how to lay 10415 it out yet, so I am stuffing things here while I experiment. 10416 *******************************************************************************/ 10417 #undef __FUNCT__ 10418 #define __FUNCT__ "DMPlexSetFEMIntegration" 10419 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10420 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10421 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10422 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10423 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10424 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10425 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10426 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10427 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10428 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10429 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10430 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10431 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10432 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10433 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10434 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10435 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 10436 { 10437 DM_Plex *mesh = (DM_Plex*) dm->data; 10438 10439 PetscFunctionBegin; 10440 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10441 mesh->integrateResidualFEM = integrateResidualFEM; 10442 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10443 mesh->integrateJacobianFEM = integrateJacobianFEM; 10444 PetscFunctionReturn(0); 10445 } 10446 10447 #undef __FUNCT__ 10448 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10449 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10450 { 10451 Vec coordinates; 10452 PetscSection section, cSection; 10453 PetscInt dim, vStart, vEnd, v, c, d; 10454 PetscScalar *values, *cArray; 10455 PetscReal *coords; 10456 PetscErrorCode ierr; 10457 10458 PetscFunctionBegin; 10459 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10460 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10461 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10462 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10463 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10464 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10465 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10466 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10467 for (v = vStart; v < vEnd; ++v) { 10468 PetscInt dof, off; 10469 10470 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10471 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10472 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10473 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 10474 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10475 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10476 } 10477 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10478 /* Temporary, must be replaced by a projection on the finite element basis */ 10479 { 10480 PetscInt eStart = 0, eEnd = 0, e, depth; 10481 10482 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10483 --depth; 10484 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10485 for (e = eStart; e < eEnd; ++e) { 10486 const PetscInt *cone = PETSC_NULL; 10487 PetscInt coneSize, d; 10488 PetscScalar *coordsA, *coordsB; 10489 10490 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10491 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10492 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10493 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10494 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10495 for (d = 0; d < dim; ++d) { 10496 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10497 } 10498 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10499 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10500 } 10501 } 10502 10503 ierr = PetscFree(coords);CHKERRQ(ierr); 10504 ierr = PetscFree(values);CHKERRQ(ierr); 10505 #if 0 10506 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10507 PetscReal detJ; 10508 10509 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10510 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10511 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10512 10513 for (PetscInt c = cStart; c < cEnd; ++c) { 10514 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10515 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10516 const int oSize = pV.getSize(); 10517 int v = 0; 10518 10519 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10520 for (PetscInt cl = 0; cl < oSize; ++cl) { 10521 const PetscInt fDim; 10522 10523 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10524 if (pointDim) { 10525 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10526 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10527 } 10528 } 10529 } 10530 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10531 pV.clear(); 10532 } 10533 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10534 ierr = PetscFree(values);CHKERRQ(ierr); 10535 #endif 10536 PetscFunctionReturn(0); 10537 } 10538 10539 #undef __FUNCT__ 10540 #define __FUNCT__ "DMPlexProjectFunction" 10541 /*@C 10542 DMPlexProjectFunction - This projects the given function into the function space provided. 10543 10544 Input Parameters: 10545 + dm - The DM 10546 . numComp - The number of components (functions) 10547 . funcs - The coordinate functions to evaluate 10548 - mode - The insertion mode for values 10549 10550 Output Parameter: 10551 . X - vector 10552 10553 Level: developer 10554 10555 Note: 10556 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10557 We will eventually fix it. 10558 10559 ,seealso: DMPlexComputeL2Diff() 10560 */ 10561 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10562 { 10563 Vec localX; 10564 PetscErrorCode ierr; 10565 10566 PetscFunctionBegin; 10567 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10568 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10569 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10570 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10571 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10572 PetscFunctionReturn(0); 10573 } 10574 10575 #undef __FUNCT__ 10576 #define __FUNCT__ "DMPlexComputeL2Diff" 10577 /*@C 10578 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10579 10580 Input Parameters: 10581 + dm - The DM 10582 . quad - The PetscQuadrature object for each field 10583 . funcs - The functions to evaluate for each field component 10584 - X - The coefficient vector u_h 10585 10586 Output Parameter: 10587 . diff - The diff ||u - u_h||_2 10588 10589 Level: developer 10590 10591 .seealso: DMPlexProjectFunction() 10592 */ 10593 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10594 { 10595 const PetscInt debug = 0; 10596 PetscSection section; 10597 Vec localX; 10598 PetscReal *coords, *v0, *J, *invJ, detJ; 10599 PetscReal localDiff = 0.0; 10600 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10601 PetscErrorCode ierr; 10602 10603 PetscFunctionBegin; 10604 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10605 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10606 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10607 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10608 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10609 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10610 for (field = 0; field < numFields; ++field) { 10611 numComponents += quad[field].numComponents; 10612 } 10613 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10614 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10615 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10616 for (c = cStart; c < cEnd; ++c) { 10617 const PetscScalar *x; 10618 PetscReal elemDiff = 0.0; 10619 10620 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10621 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10622 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10623 10624 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10625 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10626 const PetscReal *quadPoints = quad[field].quadPoints; 10627 const PetscReal *quadWeights = quad[field].quadWeights; 10628 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10629 const PetscInt numBasisComps = quad[field].numComponents; 10630 const PetscReal *basis = quad[field].basis; 10631 PetscInt q, d, e, fc, f; 10632 10633 if (debug) { 10634 char title[1024]; 10635 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10636 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10637 } 10638 for (q = 0; q < numQuadPoints; ++q) { 10639 for (d = 0; d < dim; d++) { 10640 coords[d] = v0[d]; 10641 for (e = 0; e < dim; e++) { 10642 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10643 } 10644 } 10645 for (fc = 0; fc < numBasisComps; ++fc) { 10646 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10647 PetscReal interpolant = 0.0; 10648 for (f = 0; f < numBasisFuncs; ++f) { 10649 const PetscInt fidx = f*numBasisComps+fc; 10650 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10651 } 10652 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10653 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10654 } 10655 } 10656 comp += numBasisComps; 10657 fieldOffset += numBasisFuncs*numBasisComps; 10658 } 10659 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10660 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10661 localDiff += elemDiff; 10662 } 10663 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10664 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10665 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10666 *diff = PetscSqrtReal(*diff); 10667 PetscFunctionReturn(0); 10668 } 10669 10670 #undef __FUNCT__ 10671 #define __FUNCT__ "DMPlexComputeResidualFEM" 10672 /*@ 10673 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10674 10675 Input Parameters: 10676 + dm - The mesh 10677 . X - Local input vector 10678 - user - The user context 10679 10680 Output Parameter: 10681 . F - Local output vector 10682 10683 Note: 10684 The second member of the user context must be an FEMContext. 10685 10686 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10687 like a GPU, or vectorize on a multicore machine. 10688 10689 .seealso: DMPlexComputeJacobianActionFEM() 10690 */ 10691 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10692 { 10693 DM_Plex *mesh = (DM_Plex*) dm->data; 10694 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10695 PetscQuadrature *quad = fem->quad; 10696 PetscSection section; 10697 PetscReal *v0, *J, *invJ, *detJ; 10698 PetscScalar *elemVec, *u; 10699 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10700 PetscInt cellDof = 0, numComponents = 0; 10701 PetscErrorCode ierr; 10702 10703 PetscFunctionBegin; 10704 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10705 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10706 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10707 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10708 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10709 numCells = cEnd - cStart; 10710 for (field = 0; field < numFields; ++field) { 10711 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10712 numComponents += quad[field].numComponents; 10713 } 10714 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10715 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10716 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); 10717 for (c = cStart; c < cEnd; ++c) { 10718 const PetscScalar *x; 10719 PetscInt i; 10720 10721 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10722 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10723 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10724 10725 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10726 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10727 } 10728 for (field = 0; field < numFields; ++field) { 10729 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10730 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10731 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10732 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10733 /* Conforming batches */ 10734 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10735 PetscInt numBlocks = 1; 10736 PetscInt batchSize = numBlocks * blockSize; 10737 PetscInt numBatches = numBatchesTmp; 10738 PetscInt numChunks = numCells / (numBatches*batchSize); 10739 /* Remainder */ 10740 PetscInt numRemainder = numCells % (numBatches * batchSize); 10741 PetscInt offset = numCells - numRemainder; 10742 10743 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10744 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10745 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10746 } 10747 for (c = cStart; c < cEnd; ++c) { 10748 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10749 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10750 } 10751 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10752 if (mesh->printFEM) { 10753 PetscMPIInt rank, numProcs; 10754 PetscInt p; 10755 10756 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10757 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10758 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10759 for (p = 0; p < numProcs; ++p) { 10760 if (p == rank) { 10761 Vec f; 10762 10763 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10764 ierr = VecCopy(F, f);CHKERRQ(ierr); 10765 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10766 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10767 ierr = VecDestroy(&f);CHKERRQ(ierr); 10768 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10769 } 10770 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10771 } 10772 } 10773 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10774 PetscFunctionReturn(0); 10775 } 10776 10777 #undef __FUNCT__ 10778 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10779 /*@C 10780 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10781 10782 Input Parameters: 10783 + dm - The mesh 10784 . J - The Jacobian shell matrix 10785 . X - Local input vector 10786 - user - The user context 10787 10788 Output Parameter: 10789 . F - Local output vector 10790 10791 Note: 10792 The second member of the user context must be an FEMContext. 10793 10794 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10795 like a GPU, or vectorize on a multicore machine. 10796 10797 .seealso: DMPlexComputeResidualFEM() 10798 */ 10799 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10800 { 10801 DM_Plex *mesh = (DM_Plex*) dm->data; 10802 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10803 PetscQuadrature *quad = fem->quad; 10804 PetscSection section; 10805 JacActionCtx *jctx; 10806 PetscReal *v0, *J, *invJ, *detJ; 10807 PetscScalar *elemVec, *u, *a; 10808 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10809 PetscInt cellDof = 0; 10810 PetscErrorCode ierr; 10811 10812 PetscFunctionBegin; 10813 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10814 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10815 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10816 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10817 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10818 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10819 numCells = cEnd - cStart; 10820 for (field = 0; field < numFields; ++field) { 10821 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10822 } 10823 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10824 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); 10825 for (c = cStart; c < cEnd; ++c) { 10826 const PetscScalar *x; 10827 PetscInt i; 10828 10829 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10830 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10831 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10832 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10833 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10834 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10835 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 10836 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10837 } 10838 for (field = 0; field < numFields; ++field) { 10839 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10840 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10841 /* Conforming batches */ 10842 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10843 PetscInt numBlocks = 1; 10844 PetscInt batchSize = numBlocks * blockSize; 10845 PetscInt numBatches = numBatchesTmp; 10846 PetscInt numChunks = numCells / (numBatches*batchSize); 10847 /* Remainder */ 10848 PetscInt numRemainder = numCells % (numBatches * batchSize); 10849 PetscInt offset = numCells - numRemainder; 10850 10851 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); 10852 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], 10853 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10854 } 10855 for (c = cStart; c < cEnd; ++c) { 10856 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10857 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10858 } 10859 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10860 if (mesh->printFEM) { 10861 PetscMPIInt rank, numProcs; 10862 PetscInt p; 10863 10864 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10865 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10866 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10867 for (p = 0; p < numProcs; ++p) { 10868 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10869 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10870 } 10871 } 10872 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10873 PetscFunctionReturn(0); 10874 } 10875 10876 #undef __FUNCT__ 10877 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10878 /*@ 10879 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10880 10881 Input Parameters: 10882 + dm - The mesh 10883 . X - Local input vector 10884 - user - The user context 10885 10886 Output Parameter: 10887 . Jac - Jacobian matrix 10888 10889 Note: 10890 The second member of the user context must be an FEMContext. 10891 10892 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10893 like a GPU, or vectorize on a multicore machine. 10894 10895 .seealso: FormFunctionLocal() 10896 */ 10897 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10898 { 10899 DM_Plex *mesh = (DM_Plex*) dm->data; 10900 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10901 PetscQuadrature *quad = fem->quad; 10902 PetscSection section; 10903 PetscReal *v0, *J, *invJ, *detJ; 10904 PetscScalar *elemMat, *u; 10905 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10906 PetscInt cellDof = 0, numComponents = 0; 10907 PetscBool isShell; 10908 PetscErrorCode ierr; 10909 10910 PetscFunctionBegin; 10911 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10912 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10913 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10914 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10915 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10916 numCells = cEnd - cStart; 10917 for (field = 0; field < numFields; ++field) { 10918 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10919 numComponents += quad[field].numComponents; 10920 } 10921 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10922 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10923 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); 10924 for (c = cStart; c < cEnd; ++c) { 10925 const PetscScalar *x; 10926 PetscInt i; 10927 10928 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10929 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10930 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10931 10932 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10933 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10934 } 10935 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10936 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10937 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10938 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10939 PetscInt fieldJ; 10940 10941 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10942 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10943 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10944 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10945 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10946 /* Conforming batches */ 10947 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10948 PetscInt numBlocks = 1; 10949 PetscInt batchSize = numBlocks * blockSize; 10950 PetscInt numBatches = numBatchesTmp; 10951 PetscInt numChunks = numCells / (numBatches*batchSize); 10952 /* Remainder */ 10953 PetscInt numRemainder = numCells % (numBatches * batchSize); 10954 PetscInt offset = numCells - numRemainder; 10955 10956 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10957 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10958 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10959 } 10960 } 10961 for (c = cStart; c < cEnd; ++c) { 10962 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10963 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10964 } 10965 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10966 10967 /* Assemble matrix, using the 2-step process: 10968 MatAssemblyBegin(), MatAssemblyEnd(). */ 10969 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10970 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10971 10972 if (mesh->printFEM) { 10973 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10974 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10975 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10976 } 10977 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10978 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10979 if (isShell) { 10980 JacActionCtx *jctx; 10981 10982 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10983 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10984 } 10985 *str = SAME_NONZERO_PATTERN; 10986 PetscFunctionReturn(0); 10987 } 10988 10989 10990 #undef __FUNCT__ 10991 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10992 /*@C 10993 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10994 the local section and an SF describing the section point overlap. 10995 10996 Input Parameters: 10997 + s - The PetscSection for the local field layout 10998 . sf - The SF describing parallel layout of the section points 10999 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 11000 . label - The label specifying the points 11001 - labelValue - The label stratum specifying the points 11002 11003 Output Parameter: 11004 . gsection - The PetscSection for the global field layout 11005 11006 Note: This gives negative sizes and offsets to points not owned by this process 11007 11008 Level: developer 11009 11010 .seealso: PetscSectionCreate() 11011 @*/ 11012 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 11013 { 11014 PetscInt *neg; 11015 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 11016 PetscErrorCode ierr; 11017 11018 PetscFunctionBegin; 11019 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 11020 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 11021 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 11022 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 11023 /* Mark ghost points with negative dof */ 11024 for (p = pStart; p < pEnd; ++p) { 11025 PetscInt value; 11026 11027 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 11028 if (value != labelValue) continue; 11029 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 11030 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 11031 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 11032 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 11033 neg[p-pStart] = -(dof+1); 11034 } 11035 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 11036 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 11037 if (nroots >= 0) { 11038 if (nroots > pEnd - pStart) { 11039 PetscInt *tmpDof; 11040 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11041 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 11042 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11043 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11044 for (p = pStart; p < pEnd; ++p) { 11045 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 11046 } 11047 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 11048 } else { 11049 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11050 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11051 } 11052 } 11053 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 11054 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11055 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 11056 11057 (*gsection)->atlasOff[p] = off; 11058 11059 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 11060 } 11061 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 11062 globalOff -= off; 11063 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11064 (*gsection)->atlasOff[p] += globalOff; 11065 11066 neg[p] = -((*gsection)->atlasOff[p]+1); 11067 } 11068 /* Put in negative offsets for ghost points */ 11069 if (nroots >= 0) { 11070 if (nroots > pEnd - pStart) { 11071 PetscInt *tmpOff; 11072 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11073 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 11074 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11075 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11076 for (p = pStart; p < pEnd; ++p) { 11077 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 11078 } 11079 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 11080 } else { 11081 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11082 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11083 } 11084 } 11085 ierr = PetscFree(neg);CHKERRQ(ierr); 11086 PetscFunctionReturn(0); 11087 } 11088