1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex*) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 167 if (size > 1) { 168 PetscSF sf; 169 170 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 171 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 172 } 173 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 174 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 175 const char *name; 176 const char *colors[3] = {"red", "blue", "green"}; 177 const int numColors = 3; 178 PetscReal scale = 2.0; 179 PetscScalar *coords; 180 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 181 PetscMPIInt rank, size; 182 183 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 184 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 185 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 186 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 187 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 188 ierr = PetscViewerASCIIPrintf(viewer, "\ 189 \\documentclass[crop,multi=false]{standalone}\n\n\ 190 \\usepackage{tikz}\n\ 191 \\usepackage{pgflibraryshapes}\n\ 192 \\usetikzlibrary{backgrounds}\n\ 193 \\usetikzlibrary{arrows}\n\ 194 \\begin{document}\n\ 195 \\section{%s}\n\ 196 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 197 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 198 for (p = 0; p < size; ++p) { 199 if (p > 0 && p == size-1) { 200 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 201 } else if (p > 0) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 203 } 204 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 207 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 208 /* Plot vertices */ 209 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 210 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 211 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 212 for (v = vStart; v < vEnd; ++v) { 213 PetscInt off, dof, d; 214 215 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 216 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 217 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 218 for (d = 0; d < dof; ++d) { 219 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 220 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 221 } 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 223 } 224 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 225 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 226 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 227 /* Plot edges */ 228 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 229 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 230 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 231 for (e = eStart; e < eEnd; ++e) { 232 const PetscInt *cone; 233 PetscInt coneSize, offA, offB, dof, d; 234 235 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 236 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 237 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 238 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 239 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 240 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 241 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 242 for (d = 0; d < dof; ++d) { 243 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 244 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 245 } 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 247 } 248 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 249 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 250 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 251 /* Plot cells */ 252 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 253 for (c = cStart; c < cEnd; ++c) { 254 PetscInt *closure = PETSC_NULL; 255 PetscInt closureSize, firstPoint = -1; 256 257 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 258 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 259 for (p = 0; p < closureSize*2; p += 2) { 260 const PetscInt point = closure[p]; 261 262 if ((point < vStart) || (point >= vEnd)) continue; 263 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 264 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 265 if (firstPoint < 0) firstPoint = point; 266 } 267 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 268 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 269 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 270 } 271 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 272 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 273 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 274 } else { 275 MPI_Comm comm = ((PetscObject) dm)->comm; 276 PetscInt *sizes; 277 PetscInt locDepth, depth, dim, d; 278 PetscInt pStart, pEnd, p; 279 PetscMPIInt size; 280 281 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 282 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 283 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 284 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 285 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 286 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 287 if (depth == 1) { 288 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 289 pEnd = pEnd - pStart; 290 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 291 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 292 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 293 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 294 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 295 pEnd = pEnd - pStart; 296 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 297 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 298 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 299 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 300 } else { 301 for (d = 0; d <= dim; d++) { 302 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 303 pEnd = pEnd - pStart; 304 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 305 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 306 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 307 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 308 } 309 } 310 ierr = PetscFree(sizes);CHKERRQ(ierr); 311 } 312 PetscFunctionReturn(0); 313 } 314 315 #undef __FUNCT__ 316 #define __FUNCT__ "DMView_Plex" 317 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 318 { 319 PetscBool iascii, isbinary; 320 PetscErrorCode ierr; 321 322 PetscFunctionBegin; 323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 324 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 325 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 326 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 327 if (iascii) { 328 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 329 #if 0 330 } else if (isbinary) { 331 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 332 #endif 333 } 334 PetscFunctionReturn(0); 335 } 336 337 #undef __FUNCT__ 338 #define __FUNCT__ "DMDestroy_Plex" 339 PetscErrorCode DMDestroy_Plex(DM dm) 340 { 341 DM_Plex *mesh = (DM_Plex*) dm->data; 342 DMLabel next = mesh->labels; 343 PetscErrorCode ierr; 344 345 PetscFunctionBegin; 346 if (--mesh->refct > 0) PetscFunctionReturn(0); 347 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 348 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 349 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 350 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 353 while (next) { 354 DMLabel tmp = next->next; 355 356 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 357 next = tmp; 358 } 359 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 360 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 361 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 362 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 363 ierr = PetscFree(mesh);CHKERRQ(ierr); 364 PetscFunctionReturn(0); 365 } 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 369 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 370 { 371 const PetscInt *support = PETSC_NULL; 372 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 373 PetscErrorCode ierr; 374 375 PetscFunctionBegin; 376 if (useClosure) { 377 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 378 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 379 for (s = 0; s < supportSize; ++s) { 380 const PetscInt *cone = PETSC_NULL; 381 PetscInt coneSize, c, q; 382 383 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 384 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 385 for (c = 0; c < coneSize; ++c) { 386 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 387 if (cone[c] == adj[q]) break; 388 } 389 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 390 } 391 } 392 } else { 393 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 394 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 395 for (s = 0; s < supportSize; ++s) { 396 const PetscInt *cone = PETSC_NULL; 397 PetscInt coneSize, c, q; 398 399 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 400 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 401 for (c = 0; c < coneSize; ++c) { 402 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 403 if (cone[c] == adj[q]) break; 404 } 405 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 406 } 407 } 408 } 409 *adjSize = numAdj; 410 PetscFunctionReturn(0); 411 } 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "DMPlexGetAdjacency_Private" 415 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 416 { 417 const PetscInt *star = tmpClosure; 418 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 419 PetscErrorCode ierr; 420 421 PetscFunctionBegin; 422 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 423 for (s = 2; s < starSize*2; s += 2) { 424 const PetscInt *closure = PETSC_NULL; 425 PetscInt closureSize, c, q; 426 427 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 428 for (c = 0; c < closureSize*2; c += 2) { 429 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 430 if (closure[c] == adj[q]) break; 431 } 432 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 433 } 434 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 435 } 436 *adjSize = numAdj; 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNCT__ 441 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 442 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 443 { 444 DM_Plex *mesh = (DM_Plex*) dm->data; 445 446 PetscFunctionBegin; 447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 448 mesh->preallocCenterDim = preallocCenterDim; 449 PetscFunctionReturn(0); 450 } 451 452 #undef __FUNCT__ 453 #define __FUNCT__ "DMPlexPreallocateOperator" 454 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 455 { 456 DM_Plex *mesh = (DM_Plex*) dm->data; 457 MPI_Comm comm = ((PetscObject) dm)->comm; 458 PetscSF sf, sfDof, sfAdj; 459 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 460 PetscInt nleaves, l, p; 461 const PetscInt *leaves; 462 const PetscSFNode *remotes; 463 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 464 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 465 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 466 PetscLayout rLayout; 467 PetscInt locRows, rStart, rEnd, r; 468 PetscMPIInt size; 469 PetscBool useClosure, debug = PETSC_FALSE; 470 PetscErrorCode ierr; 471 472 PetscFunctionBegin; 473 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 474 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 475 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 476 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 477 /* Create dof SF based on point SF */ 478 if (debug) { 479 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 480 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 481 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 485 } 486 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 487 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 488 if (debug) { 489 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 490 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 491 } 492 /* Create section for dof adjacency (dof ==> # adj dof) */ 493 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 494 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 495 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 496 if (mesh->preallocCenterDim == dim) { 497 useClosure = PETSC_FALSE; 498 } else if (mesh->preallocCenterDim == 0) { 499 useClosure = PETSC_TRUE; 500 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 501 502 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 503 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 504 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 505 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 508 /* Fill in the ghost dofs on the interface */ 509 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 510 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 511 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 512 513 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 514 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 515 516 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 517 518 /* 519 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 520 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 521 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 522 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 523 Create sfAdj connecting rootSectionAdj and leafSectionAdj 524 3. Visit unowned points on interface, write adjacencies to adj 525 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 526 4. Visit owned points on interface, write adjacencies to rootAdj 527 Remove redundancy in rootAdj 528 ** The last two traversals use transitive closure 529 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 530 Allocate memory addressed by sectionAdj (cols) 531 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 532 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 533 */ 534 535 for (l = 0; l < nleaves; ++l) { 536 PetscInt dof, off, d, q; 537 PetscInt p = leaves[l], numAdj = maxAdjSize; 538 539 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 540 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 541 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 542 for (q = 0; q < numAdj; ++q) { 543 PetscInt ndof, ncdof; 544 545 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 546 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 547 for (d = off; d < off+dof; ++d) { 548 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 549 } 550 } 551 } 552 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 553 if (debug) { 554 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 555 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 556 } 557 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 558 if (size > 1) { 559 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 560 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 561 } 562 if (debug) { 563 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 564 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 565 } 566 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 567 for (p = pStart; p < pEnd; ++p) { 568 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 569 570 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 571 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 572 if (!dof) continue; 573 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 574 if (adof <= 0) continue; 575 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 576 for (q = 0; q < numAdj; ++q) { 577 PetscInt ndof, ncdof; 578 579 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 580 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 581 for (d = off; d < off+dof; ++d) { 582 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 583 } 584 } 585 } 586 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 587 if (debug) { 588 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 589 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 590 } 591 /* Create adj SF based on dof SF */ 592 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 593 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 594 if (debug) { 595 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 596 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 597 } 598 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 599 /* Create leaf adjacency */ 600 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 601 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 602 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 603 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 604 for (l = 0; l < nleaves; ++l) { 605 PetscInt dof, off, d, q; 606 PetscInt p = leaves[l], numAdj = maxAdjSize; 607 608 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 609 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 610 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 611 for (d = off; d < off+dof; ++d) { 612 PetscInt aoff, i = 0; 613 614 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 615 for (q = 0; q < numAdj; ++q) { 616 PetscInt ndof, ncdof, ngoff, nd; 617 618 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 619 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 621 for (nd = 0; nd < ndof-ncdof; ++nd) { 622 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 623 ++i; 624 } 625 } 626 } 627 } 628 /* Debugging */ 629 if (debug) { 630 IS tmp; 631 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 632 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 633 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 634 } 635 /* Gather adjacenct indices to root */ 636 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 637 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 638 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 639 if (size > 1) { 640 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 641 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 642 } 643 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 644 ierr = PetscFree(adj);CHKERRQ(ierr); 645 /* Debugging */ 646 if (debug) { 647 IS tmp; 648 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 649 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 650 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 651 } 652 /* Add in local adjacency indices for owned dofs on interface (roots) */ 653 for (p = pStart; p < pEnd; ++p) { 654 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 655 656 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 657 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 658 if (!dof) continue; 659 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 660 if (adof <= 0) continue; 661 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 662 for (d = off; d < off+dof; ++d) { 663 PetscInt adof, aoff, i; 664 665 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 666 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 667 i = adof-1; 668 for (q = 0; q < numAdj; ++q) { 669 PetscInt ndof, ncdof, ngoff, nd; 670 671 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 672 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 673 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 674 for (nd = 0; nd < ndof-ncdof; ++nd) { 675 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 676 --i; 677 } 678 } 679 } 680 } 681 /* Debugging */ 682 if (debug) { 683 IS tmp; 684 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 685 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 686 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 687 } 688 /* Compress indices */ 689 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 690 for (p = pStart; p < pEnd; ++p) { 691 PetscInt dof, cdof, off, d; 692 PetscInt adof, aoff; 693 694 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 695 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 696 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 697 if (!dof) continue; 698 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 699 if (adof <= 0) continue; 700 for (d = off; d < off+dof-cdof; ++d) { 701 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 702 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 703 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 704 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 705 } 706 } 707 /* Debugging */ 708 if (debug) { 709 IS tmp; 710 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 711 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 712 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 713 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 714 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 715 } 716 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 717 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 718 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 719 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 720 for (p = pStart; p < pEnd; ++p) { 721 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 722 PetscBool found = PETSC_TRUE; 723 724 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 725 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 727 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 728 for (d = 0; d < dof-cdof; ++d) { 729 PetscInt ldof, rdof; 730 731 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 732 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 733 if (ldof > 0) { 734 /* We do not own this point */ 735 } else if (rdof > 0) { 736 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 737 } else { 738 found = PETSC_FALSE; 739 } 740 } 741 if (found) continue; 742 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 743 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 744 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 745 for (q = 0; q < numAdj; ++q) { 746 PetscInt ndof, ncdof, noff; 747 748 /* Adjacent points may not be in the section chart */ 749 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 750 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 751 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 752 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 753 for (d = goff; d < goff+dof-cdof; ++d) { 754 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 755 } 756 } 757 } 758 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 759 if (debug) { 760 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 761 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 762 } 763 /* Get adjacent indices */ 764 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 765 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 768 PetscBool found = PETSC_TRUE; 769 770 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 771 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 772 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 773 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 774 for (d = 0; d < dof-cdof; ++d) { 775 PetscInt ldof, rdof; 776 777 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 778 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 779 if (ldof > 0) { 780 /* We do not own this point */ 781 } else if (rdof > 0) { 782 PetscInt aoff, roff; 783 784 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 786 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 787 } else { 788 found = PETSC_FALSE; 789 } 790 } 791 if (found) continue; 792 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 793 for (d = goff; d < goff+dof-cdof; ++d) { 794 PetscInt adof, aoff, i = 0; 795 796 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 797 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 798 for (q = 0; q < numAdj; ++q) { 799 PetscInt ndof, ncdof, ngoff, nd; 800 const PetscInt *ncind; 801 802 /* Adjacent points may not be in the section chart */ 803 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 804 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 805 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 806 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 807 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 808 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 809 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 810 } 811 } 812 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 813 } 814 } 815 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 816 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 817 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 818 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 819 /* Debugging */ 820 if (debug) { 821 IS tmp; 822 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 823 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 824 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 825 } 826 /* Create allocation vectors from adjacency graph */ 827 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 828 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 829 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 830 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 831 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 832 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 833 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 834 /* Only loop over blocks of rows */ 835 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 836 for (r = rStart/bs; r < rEnd/bs; ++r) { 837 const PetscInt row = r*bs; 838 PetscInt numCols, cStart, c; 839 840 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 841 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 842 for (c = cStart; c < cStart+numCols; ++c) { 843 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 844 ++dnz[r-rStart]; 845 if (cols[c] >= row) ++dnzu[r-rStart]; 846 } else { 847 ++onz[r-rStart]; 848 if (cols[c] >= row) ++onzu[r-rStart]; 849 } 850 } 851 } 852 if (bs > 1) { 853 for (r = 0; r < locRows/bs; ++r) { 854 dnz[r] /= bs; 855 onz[r] /= bs; 856 dnzu[r] /= bs; 857 onzu[r] /= bs; 858 } 859 } 860 /* Set matrix pattern */ 861 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 862 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 863 /* Fill matrix with zeros */ 864 if (fillMatrix) { 865 PetscScalar *values; 866 PetscInt maxRowLen = 0; 867 868 for (r = rStart; r < rEnd; ++r) { 869 PetscInt len; 870 871 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 872 maxRowLen = PetscMax(maxRowLen, len); 873 } 874 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 875 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 876 for (r = rStart; r < rEnd; ++r) { 877 PetscInt numCols, cStart; 878 879 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 880 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 881 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 882 } 883 ierr = PetscFree(values);CHKERRQ(ierr); 884 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 885 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 886 } 887 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 888 ierr = PetscFree(cols);CHKERRQ(ierr); 889 PetscFunctionReturn(0); 890 } 891 892 #if 0 893 #undef __FUNCT__ 894 #define __FUNCT__ "DMPlexPreallocateOperator_2" 895 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 896 { 897 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, const char labelName[], DM sdm) 3913 { 3914 MPI_Comm comm = ((PetscObject) dm)->comm; 3915 DMLabel label; 3916 IS valueIS, *pointIS; 3917 const PetscInt *values, **splitPoints; 3918 PetscSection coordSection; 3919 Vec coordinates; 3920 PetscScalar *coords; 3921 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3922 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3923 PetscErrorCode ierr; 3924 3925 PetscFunctionBegin; 3926 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3927 /* Count split points and add cohesive cells */ 3928 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 3929 if (label) { 3930 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3931 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3932 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3933 } 3934 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3935 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3936 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3937 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3938 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3939 for (d = 0; d <= depth; ++d) { 3940 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3941 numSplitPoints[d] = 0; 3942 splitPoints[d] = PETSC_NULL; 3943 pointIS[d] = PETSC_NULL; 3944 } 3945 for (sp = 0; sp < numSP; ++sp) { 3946 const PetscInt dep = values[sp]; 3947 3948 if ((dep < 0) || (dep > depth)) continue; 3949 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3950 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3951 if (pointIS[dep]) { 3952 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3953 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3954 } 3955 } 3956 if (depth >= 0) { 3957 /* Calculate number of additional points */ 3958 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3959 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3960 /* Calculate hybrid bound for each dimension */ 3961 pMaxNew[0] += depthShift[depth]; 3962 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3963 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3964 3965 /* Calculate point offset for each dimension */ 3966 depthOffset[depth] = 0; 3967 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3968 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3969 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3970 } 3971 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3972 /* Step 3: Set cone/support sizes for new points */ 3973 for (dep = 0; dep <= depth; ++dep) { 3974 for (p = 0; p < numSplitPoints[dep]; ++p) { 3975 const PetscInt oldp = splitPoints[dep][p]; 3976 const PetscInt newp = depthOffset[dep] + oldp; 3977 const PetscInt splitp = pMaxNew[dep] + p; 3978 const PetscInt *support; 3979 PetscInt coneSize, supportSize, q, e; 3980 3981 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3982 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3983 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3984 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3985 if (dep == depth-1) { 3986 const PetscInt ccell = pMaxNew[depth] + p; 3987 /* Add cohesive cells, they are prisms */ 3988 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3989 } else if (dep == 0) { 3990 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3991 3992 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3993 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3994 for (e = 0, q = 0; e < supportSize; ++e) { 3995 PetscInt val; 3996 3997 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3998 if ((val == 1) || (val == (shift + 1))) ++q; 3999 } 4000 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 4001 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4002 for (e = 0, q = 0; e < supportSize; ++e) { 4003 PetscInt val; 4004 4005 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4006 if ((val == 1) || (val == -(shift + 1))) ++q; 4007 } 4008 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 4009 /* Add cohesive edges */ 4010 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 4011 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4012 } else if (dep == dim-2) { 4013 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4014 /* Split old edge: Faces in positive side cells and old split faces */ 4015 for (e = 0, q = 0; e < supportSize; ++e) { 4016 PetscInt val; 4017 4018 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4019 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4020 } 4021 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4022 /* Split new edge: Faces in negative side cells and new split faces */ 4023 for (e = 0, q = 0; e < supportSize; ++e) { 4024 PetscInt val; 4025 4026 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4027 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4028 } 4029 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4030 } 4031 } 4032 } 4033 /* Step 4: Setup split DM */ 4034 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4035 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4036 /* Step 6: Set cones and supports for new points */ 4037 for (dep = 0; dep <= depth; ++dep) { 4038 for (p = 0; p < numSplitPoints[dep]; ++p) { 4039 const PetscInt oldp = splitPoints[dep][p]; 4040 const PetscInt newp = depthOffset[dep] + oldp; 4041 const PetscInt splitp = pMaxNew[dep] + p; 4042 const PetscInt *cone, *support, *ornt; 4043 PetscInt coneSize, supportSize, q, v, e, s; 4044 4045 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4046 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4047 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4048 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4049 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4050 if (dep == depth-1) { 4051 const PetscInt ccell = pMaxNew[depth] + p; 4052 const PetscInt *supportF; 4053 4054 /* Split face: copy in old face to new face to start */ 4055 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4056 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4057 /* Split old face: old vertices/edges in cone so no change */ 4058 /* Split new face: new vertices/edges in cone */ 4059 for (q = 0; q < coneSize; ++q) { 4060 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4061 4062 coneNew[2+q] = pMaxNew[dim-2] + v; 4063 } 4064 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4065 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4066 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4067 coneNew[0] = newp; 4068 coneNew[1] = splitp; 4069 for (q = 0; q < coneSize; ++q) { 4070 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4071 } 4072 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4073 4074 4075 for (s = 0; s < supportSize; ++s) { 4076 PetscInt val; 4077 4078 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4079 if (val < 0) { 4080 /* Split old face: Replace negative side cell with cohesive cell */ 4081 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4082 } else { 4083 /* Split new face: Replace positive side cell with cohesive cell */ 4084 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4085 } 4086 } 4087 } else if (dep == 0) { 4088 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4089 4090 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4091 for (e = 0, q = 0; e < supportSize; ++e) { 4092 PetscInt val; 4093 4094 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4095 if ((val == 1) || (val == (shift + 1))) { 4096 supportNew[q++] = depthOffset[1] + support[e]; 4097 } 4098 } 4099 supportNew[q] = cedge; 4100 4101 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4102 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4103 for (e = 0, q = 0; e < supportSize; ++e) { 4104 PetscInt val, edge; 4105 4106 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4107 if (val == 1) { 4108 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4109 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4110 supportNew[q++] = pMaxNew[1] + edge; 4111 } else if (val == -(shift + 1)) { 4112 supportNew[q++] = depthOffset[1] + support[e]; 4113 } 4114 } 4115 supportNew[q] = cedge; 4116 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4117 /* Cohesive edge: Old and new split vertex, punting on support */ 4118 coneNew[0] = newp; 4119 coneNew[1] = splitp; 4120 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4121 } else if (dep == dim-2) { 4122 /* Split old edge: old vertices in cone so no change */ 4123 /* Split new edge: new vertices in cone */ 4124 for (q = 0; q < coneSize; ++q) { 4125 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4126 4127 coneNew[q] = pMaxNew[dim-3] + v; 4128 } 4129 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4130 /* Split old edge: Faces in positive side cells and old split faces */ 4131 for (e = 0, q = 0; e < supportSize; ++e) { 4132 PetscInt val; 4133 4134 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4135 if ((val == dim-1) || (val == (shift + dim-1))) { 4136 supportNew[q++] = depthOffset[dim-1] + support[e]; 4137 } 4138 } 4139 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4140 /* Split new edge: Faces in negative side cells and new split faces */ 4141 for(e = 0, q = 0; e < supportSize; ++e) { 4142 PetscInt val, face; 4143 4144 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4145 if (val == dim-1) { 4146 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4147 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4148 supportNew[q++] = pMaxNew[dim-1] + face; 4149 } else if (val == -(shift + dim-1)) { 4150 supportNew[q++] = depthOffset[dim-1] + support[e]; 4151 } 4152 } 4153 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4154 } 4155 } 4156 } 4157 /* Step 6b: Replace split points in negative side cones */ 4158 for (sp = 0; sp < numSP; ++sp) { 4159 PetscInt dep = values[sp]; 4160 IS pIS; 4161 PetscInt numPoints; 4162 const PetscInt *points; 4163 4164 if (dep >= 0) continue; 4165 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4166 if (!pIS) continue; 4167 dep = -dep - shift; 4168 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4169 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4170 for (p = 0; p < numPoints; ++p) { 4171 const PetscInt oldp = points[p]; 4172 const PetscInt newp = depthOffset[dep] + oldp; 4173 const PetscInt *cone; 4174 PetscInt coneSize, c; 4175 PetscBool replaced = PETSC_FALSE; 4176 4177 /* Negative edge: replace split vertex */ 4178 /* Negative cell: replace split face */ 4179 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4180 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4181 for (c = 0; c < coneSize; ++c) { 4182 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4183 PetscInt csplitp, cp, val; 4184 4185 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4186 if (val == dep-1) { 4187 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4188 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4189 csplitp = pMaxNew[dep-1] + cp; 4190 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4191 replaced = PETSC_TRUE; 4192 } 4193 } 4194 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4195 } 4196 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4197 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4198 } 4199 /* Step 7: Stratify */ 4200 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4201 /* Step 8: Coordinates */ 4202 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4203 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4204 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4205 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4206 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4207 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4208 const PetscInt splitp = pMaxNew[0] + v; 4209 PetscInt dof, off, soff, d; 4210 4211 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4212 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4213 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4214 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4215 } 4216 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4217 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4218 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4219 /* Step 10: Labels */ 4220 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4221 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4222 for (dep = 0; dep <= depth; ++dep) { 4223 for (p = 0; p < numSplitPoints[dep]; ++p) { 4224 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4225 const PetscInt splitp = pMaxNew[dep] + p; 4226 PetscInt l; 4227 4228 for (l = 0; l < numLabels; ++l) { 4229 DMLabel label; 4230 const char *lname; 4231 PetscInt val; 4232 4233 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4234 ierr = DMPlexGetLabel(sdm, lname, &label);CHKERRQ(ierr); 4235 ierr = DMLabelGetValue(label, newp, &val);CHKERRQ(ierr); 4236 if (val >= 0) { 4237 ierr = DMLabelSetValue(label, splitp, val);CHKERRQ(ierr); 4238 if (dep == 0) { 4239 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4240 ierr = DMLabelSetValue(label, cedge, val);CHKERRQ(ierr); 4241 } 4242 } 4243 } 4244 } 4245 } 4246 for (sp = 0; sp < numSP; ++sp) { 4247 const PetscInt dep = values[sp]; 4248 4249 if ((dep < 0) || (dep > depth)) continue; 4250 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4251 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4252 } 4253 if (label) { 4254 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4255 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4256 } 4257 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4258 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4259 PetscFunctionReturn(0); 4260 } 4261 4262 #undef __FUNCT__ 4263 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4264 /*@C 4265 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4266 4267 Collective on dm 4268 4269 Input Parameters: 4270 + dm - The original DM 4271 - labelName - The label specifying the boundary faces (this could be auto-generated) 4272 4273 Output Parameters: 4274 - dmSplit - The new DM 4275 4276 Level: developer 4277 4278 .seealso: DMCreate() 4279 */ 4280 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, const char labelName[], DM *dmSplit) 4281 { 4282 DM sdm; 4283 PetscInt dim; 4284 PetscErrorCode ierr; 4285 4286 PetscFunctionBegin; 4287 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4288 PetscValidPointer(dmSplit, 4); 4289 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4290 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4291 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4292 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4293 switch (dim) { 4294 case 2: 4295 case 3: 4296 ierr = DMPlexConstructCohesiveCells_Private(dm, labelName, sdm);CHKERRQ(ierr); 4297 break; 4298 default: 4299 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4300 } 4301 *dmSplit = sdm; 4302 PetscFunctionReturn(0); 4303 } 4304 4305 #undef __FUNCT__ 4306 #define __FUNCT__ "DMLabelCohesiveComplete" 4307 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4308 { 4309 IS dimIS; 4310 const PetscInt *points; 4311 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4312 PetscErrorCode ierr; 4313 4314 PetscFunctionBegin; 4315 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4316 /* Cell orientation for face gives the side of the fault */ 4317 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4318 if (!dimIS) PetscFunctionReturn(0); 4319 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4320 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4321 for (p = 0; p < numPoints; ++p) { 4322 const PetscInt *support; 4323 PetscInt supportSize, s; 4324 4325 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4326 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4327 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4328 for (s = 0; s < supportSize; ++s) { 4329 const PetscInt *cone, *ornt; 4330 PetscInt coneSize, c; 4331 PetscBool pos = PETSC_TRUE; 4332 4333 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4334 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4335 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4336 for(c = 0; c < coneSize; ++c) { 4337 if (cone[c] == points[p]) { 4338 if (ornt[c] >= 0) { 4339 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4340 } else { 4341 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4342 pos = PETSC_FALSE; 4343 } 4344 break; 4345 } 4346 } 4347 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]); 4348 /* Put faces touching the fault in the label */ 4349 for (c = 0; c < coneSize; ++c) { 4350 const PetscInt point = cone[c]; 4351 4352 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4353 if (val == -1) { 4354 PetscInt *closure = PETSC_NULL; 4355 PetscInt closureSize, cl; 4356 4357 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4358 for (cl = 0; cl < closureSize*2; cl += 2) { 4359 const PetscInt clp = closure[cl]; 4360 4361 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4362 if ((val >= 0) && (val < dim-1)) { 4363 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4364 break; 4365 } 4366 } 4367 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4368 } 4369 } 4370 } 4371 } 4372 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4373 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4374 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4375 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4376 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4377 if (!dimIS) PetscFunctionReturn(0); 4378 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4379 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4380 for (p = 0; p < numPoints; ++p) { 4381 PetscInt *star = PETSC_NULL; 4382 PetscInt starSize, s; 4383 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4384 4385 /* First mark cells connected to the fault */ 4386 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4387 while (again) { 4388 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4389 again = 0; 4390 for (s = 0; s < starSize*2; s += 2) { 4391 const PetscInt point = star[s]; 4392 const PetscInt *cone; 4393 PetscInt coneSize, c; 4394 4395 if ((point < cStart) || (point >= cEnd)) continue; 4396 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4397 if (val != -1) continue; 4398 again = 2; 4399 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4400 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4401 for (c = 0; c < coneSize; ++c) { 4402 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4403 if (val != -1) { 4404 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); 4405 if (val > 0) { 4406 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4407 } else { 4408 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4409 } 4410 again = 1; 4411 break; 4412 } 4413 } 4414 } 4415 } 4416 /* Classify the rest by cell membership */ 4417 for (s = 0; s < starSize*2; s += 2) { 4418 const PetscInt point = star[s]; 4419 4420 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4421 if (val == -1) { 4422 PetscInt *sstar = PETSC_NULL; 4423 PetscInt sstarSize, ss; 4424 PetscBool marked = PETSC_FALSE; 4425 4426 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4427 for (ss = 0; ss < sstarSize*2; ss += 2) { 4428 const PetscInt spoint = sstar[ss]; 4429 4430 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4431 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4432 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4433 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4434 if (val > 0) { 4435 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4436 } else { 4437 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4438 } 4439 marked = PETSC_TRUE; 4440 break; 4441 } 4442 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4443 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4444 } 4445 } 4446 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4447 } 4448 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4449 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4450 PetscFunctionReturn(0); 4451 } 4452 4453 #undef __FUNCT__ 4454 #define __FUNCT__ "DMPlexInterpolate_2D" 4455 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4456 { 4457 DM idm; 4458 DM_Plex *mesh; 4459 PetscHashIJ edgeTable; 4460 PetscInt *off; 4461 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4462 PetscInt numEdges, firstEdge, edge, e; 4463 PetscErrorCode ierr; 4464 4465 PetscFunctionBegin; 4466 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4467 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4468 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4469 numCells = cEnd - cStart; 4470 numVertices = vEnd - vStart; 4471 firstEdge = numCells + numVertices; 4472 numEdges = 0; 4473 /* Count edges using algorithm from CreateNeighborCSR */ 4474 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4475 if (off) { 4476 PetscInt numCorners = 0; 4477 4478 numEdges = off[numCells]/2; 4479 #if 0 4480 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4481 numEdges += 3*numCells - off[numCells]; 4482 #else 4483 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4484 for (c = cStart; c < cEnd; ++c) { 4485 PetscInt coneSize; 4486 4487 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4488 numCorners += coneSize; 4489 } 4490 numEdges += numCorners - off[numCells]; 4491 #endif 4492 } 4493 #if 0 4494 /* Check Euler characteristic V - E + F = 1 */ 4495 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4496 #endif 4497 /* Create interpolated mesh */ 4498 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4499 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4500 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4501 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4502 for (c = 0; c < numCells; ++c) { 4503 PetscInt numCorners; 4504 4505 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4506 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4507 } 4508 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4509 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4510 } 4511 ierr = DMSetUp(idm);CHKERRQ(ierr); 4512 /* Get edge cones from subsets of cell vertices */ 4513 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4514 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4515 4516 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4517 const PetscInt *cellFaces; 4518 PetscInt numCellFaces, faceSize, cf; 4519 4520 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4521 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4522 for (cf = 0; cf < numCellFaces; ++cf) { 4523 #if 1 4524 PetscHashIJKey key; 4525 4526 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4527 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4528 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4529 if (e < 0) { 4530 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4531 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4532 e = edge++; 4533 } 4534 #else 4535 PetscBool found = PETSC_FALSE; 4536 4537 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4538 for (e = firstEdge; e < edge; ++e) { 4539 const PetscInt *cone; 4540 4541 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4542 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4543 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4544 found = PETSC_TRUE; 4545 break; 4546 } 4547 } 4548 if (!found) { 4549 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4550 ++edge; 4551 } 4552 #endif 4553 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4554 } 4555 } 4556 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4557 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4558 ierr = PetscFree(off);CHKERRQ(ierr); 4559 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4560 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4561 mesh = (DM_Plex*) (idm)->data; 4562 /* Orient edges */ 4563 for (c = 0; c < numCells; ++c) { 4564 const PetscInt *cone = PETSC_NULL, *cellFaces; 4565 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4566 4567 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4568 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4569 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4570 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4571 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4572 for (cf = 0; cf < numCellFaces; ++cf) { 4573 const PetscInt *econe = PETSC_NULL; 4574 PetscInt esize; 4575 4576 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4577 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4578 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]); 4579 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4580 /* Correctly oriented */ 4581 mesh->coneOrientations[coff+cf] = 0; 4582 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4583 /* Start at index 1, and reverse orientation */ 4584 mesh->coneOrientations[coff+cf] = -(1+1); 4585 } 4586 } 4587 } 4588 *dmInt = idm; 4589 PetscFunctionReturn(0); 4590 } 4591 4592 #undef __FUNCT__ 4593 #define __FUNCT__ "DMPlexInterpolate_3D" 4594 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4595 { 4596 DM idm, fdm; 4597 DM_Plex *mesh; 4598 PetscInt *off; 4599 const PetscInt numCorners = 4; 4600 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4601 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4602 PetscErrorCode ierr; 4603 4604 PetscFunctionBegin; 4605 { 4606 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4607 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4608 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4609 } 4610 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4611 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4612 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4613 numCells = cEnd - cStart; 4614 numVertices = vEnd - vStart; 4615 firstFace = numCells + numVertices; 4616 numFaces = 0; 4617 /* Count faces using algorithm from CreateNeighborCSR */ 4618 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4619 if (off) { 4620 numFaces = off[numCells]/2; 4621 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4622 numFaces += 4*numCells - off[numCells]; 4623 } 4624 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4625 firstEdge = firstFace + numFaces; 4626 numEdges = numVertices + numFaces - numCells - 1; 4627 /* Create interpolated mesh */ 4628 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4629 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4630 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4631 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4632 for (c = 0; c < numCells; ++c) { 4633 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4634 } 4635 for (f = firstFace; f < firstFace+numFaces; ++f) { 4636 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4637 } 4638 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4639 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4640 } 4641 ierr = DMSetUp(idm);CHKERRQ(ierr); 4642 /* Get face cones from subsets of cell vertices */ 4643 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4644 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4645 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4646 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4647 for (f = firstFace; f < firstFace+numFaces; ++f) { 4648 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4649 } 4650 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4651 for (c = 0, face = firstFace; c < numCells; ++c) { 4652 const PetscInt *cellFaces; 4653 PetscInt numCellFaces, faceSize, cf; 4654 4655 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4656 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4657 for (cf = 0; cf < numCellFaces; ++cf) { 4658 PetscBool found = PETSC_FALSE; 4659 4660 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4661 for (f = firstFace; f < face; ++f) { 4662 const PetscInt *cone = PETSC_NULL; 4663 4664 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4665 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4666 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4667 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4668 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4669 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4670 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4671 found = PETSC_TRUE; 4672 break; 4673 } 4674 } 4675 if (!found) { 4676 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4677 /* Save the vertices for orientation calculation */ 4678 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4679 ++face; 4680 } 4681 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4682 } 4683 } 4684 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4685 /* Get edge cones from subsets of face vertices */ 4686 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4687 const PetscInt *cellFaces; 4688 PetscInt numCellFaces, faceSize, cf; 4689 4690 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4691 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4692 for (cf = 0; cf < numCellFaces; ++cf) { 4693 PetscBool found = PETSC_FALSE; 4694 4695 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4696 for (e = firstEdge; e < edge; ++e) { 4697 const PetscInt *cone = PETSC_NULL; 4698 4699 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4700 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4701 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4702 found = PETSC_TRUE; 4703 break; 4704 } 4705 } 4706 if (!found) { 4707 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4708 ++edge; 4709 } 4710 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4711 } 4712 } 4713 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4714 ierr = PetscFree(off);CHKERRQ(ierr); 4715 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4716 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4717 mesh = (DM_Plex*) (idm)->data; 4718 /* Orient edges */ 4719 for (f = firstFace; f < firstFace+numFaces; ++f) { 4720 const PetscInt *cone, *cellFaces; 4721 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4722 4723 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4724 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4725 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4726 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4727 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4728 for (cf = 0; cf < numCellFaces; ++cf) { 4729 const PetscInt *econe; 4730 PetscInt esize; 4731 4732 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4733 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4734 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]); 4735 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4736 /* Correctly oriented */ 4737 mesh->coneOrientations[coff+cf] = 0; 4738 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4739 /* Start at index 1, and reverse orientation */ 4740 mesh->coneOrientations[coff+cf] = -(1+1); 4741 } 4742 } 4743 } 4744 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4745 /* Orient faces */ 4746 for (c = 0; c < numCells; ++c) { 4747 const PetscInt *cone, *cellFaces; 4748 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4749 4750 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4751 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4752 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4753 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4754 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4755 for (cf = 0; cf < numCellFaces; ++cf) { 4756 PetscInt *origClosure = PETSC_NULL, *closure; 4757 PetscInt closureSize, i; 4758 4759 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4760 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4761 for (i = 4; i < 7; ++i) { 4762 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); 4763 } 4764 closure = &origClosure[4*2]; 4765 /* Remember that this is the orientation for edges, not vertices */ 4766 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4767 /* Correctly oriented */ 4768 mesh->coneOrientations[coff+cf] = 0; 4769 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4770 /* Shifted by 1 */ 4771 mesh->coneOrientations[coff+cf] = 1; 4772 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4773 /* Shifted by 2 */ 4774 mesh->coneOrientations[coff+cf] = 2; 4775 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4776 /* Start at edge 1, and reverse orientation */ 4777 mesh->coneOrientations[coff+cf] = -(1+1); 4778 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4779 /* Start at index 0, and reverse orientation */ 4780 mesh->coneOrientations[coff+cf] = -(0+1); 4781 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4782 /* Start at index 2, and reverse orientation */ 4783 mesh->coneOrientations[coff+cf] = -(2+1); 4784 } 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); 4785 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4786 } 4787 } 4788 { 4789 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4790 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4791 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4792 } 4793 *dmInt = idm; 4794 PetscFunctionReturn(0); 4795 } 4796 4797 #undef __FUNCT__ 4798 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4799 /* 4800 This takes as input the common mesh generator output, a list of the vertices for each cell 4801 */ 4802 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4803 { 4804 PetscInt *cone, c, p; 4805 PetscErrorCode ierr; 4806 4807 PetscFunctionBegin; 4808 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4809 for (c = 0; c < numCells; ++c) { 4810 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4811 } 4812 ierr = DMSetUp(dm);CHKERRQ(ierr); 4813 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4814 for (c = 0; c < numCells; ++c) { 4815 for (p = 0; p < numCorners; ++p) { 4816 cone[p] = cells[c*numCorners+p]+numCells; 4817 } 4818 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4819 } 4820 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4821 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4822 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4823 PetscFunctionReturn(0); 4824 } 4825 4826 #undef __FUNCT__ 4827 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4828 /* 4829 This takes as input the coordinates for each vertex 4830 */ 4831 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4832 { 4833 PetscSection coordSection; 4834 Vec coordinates; 4835 PetscScalar *coords; 4836 PetscInt coordSize, v, d; 4837 PetscErrorCode ierr; 4838 4839 PetscFunctionBegin; 4840 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4841 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4842 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4843 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4844 for (v = numCells; v < numCells+numVertices; ++v) { 4845 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4846 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4847 } 4848 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4849 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4850 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4851 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4852 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4853 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4854 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4855 for (v = 0; v < numVertices; ++v) { 4856 for (d = 0; d < spaceDim; ++d) { 4857 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4858 } 4859 } 4860 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4861 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4862 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4863 PetscFunctionReturn(0); 4864 } 4865 4866 #undef __FUNCT__ 4867 #define __FUNCT__ "DMPlexCreateFromCellList" 4868 /* 4869 This takes as input the common mesh generator output, a list of the vertices for each cell 4870 */ 4871 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4872 { 4873 PetscErrorCode ierr; 4874 4875 PetscFunctionBegin; 4876 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4877 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4878 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4879 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4880 if (interpolate) { 4881 DM idm; 4882 4883 switch (dim) { 4884 case 2: 4885 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4886 case 3: 4887 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4888 default: 4889 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4890 } 4891 ierr = DMDestroy(dm);CHKERRQ(ierr); 4892 *dm = idm; 4893 } 4894 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4895 PetscFunctionReturn(0); 4896 } 4897 4898 #if defined(PETSC_HAVE_TRIANGLE) 4899 #include <triangle.h> 4900 4901 #undef __FUNCT__ 4902 #define __FUNCT__ "InitInput_Triangle" 4903 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4904 { 4905 PetscFunctionBegin; 4906 inputCtx->numberofpoints = 0; 4907 inputCtx->numberofpointattributes = 0; 4908 inputCtx->pointlist = PETSC_NULL; 4909 inputCtx->pointattributelist = PETSC_NULL; 4910 inputCtx->pointmarkerlist = PETSC_NULL; 4911 inputCtx->numberofsegments = 0; 4912 inputCtx->segmentlist = PETSC_NULL; 4913 inputCtx->segmentmarkerlist = PETSC_NULL; 4914 inputCtx->numberoftriangleattributes = 0; 4915 inputCtx->trianglelist = PETSC_NULL; 4916 inputCtx->numberofholes = 0; 4917 inputCtx->holelist = PETSC_NULL; 4918 inputCtx->numberofregions = 0; 4919 inputCtx->regionlist = PETSC_NULL; 4920 PetscFunctionReturn(0); 4921 } 4922 4923 #undef __FUNCT__ 4924 #define __FUNCT__ "InitOutput_Triangle" 4925 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4926 { 4927 PetscFunctionBegin; 4928 outputCtx->numberofpoints = 0; 4929 outputCtx->pointlist = PETSC_NULL; 4930 outputCtx->pointattributelist = PETSC_NULL; 4931 outputCtx->pointmarkerlist = PETSC_NULL; 4932 outputCtx->numberoftriangles = 0; 4933 outputCtx->trianglelist = PETSC_NULL; 4934 outputCtx->triangleattributelist = PETSC_NULL; 4935 outputCtx->neighborlist = PETSC_NULL; 4936 outputCtx->segmentlist = PETSC_NULL; 4937 outputCtx->segmentmarkerlist = PETSC_NULL; 4938 outputCtx->numberofedges = 0; 4939 outputCtx->edgelist = PETSC_NULL; 4940 outputCtx->edgemarkerlist = PETSC_NULL; 4941 PetscFunctionReturn(0); 4942 } 4943 4944 #undef __FUNCT__ 4945 #define __FUNCT__ "FiniOutput_Triangle" 4946 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4947 { 4948 PetscFunctionBegin; 4949 free(outputCtx->pointmarkerlist); 4950 free(outputCtx->edgelist); 4951 free(outputCtx->edgemarkerlist); 4952 free(outputCtx->trianglelist); 4953 free(outputCtx->neighborlist); 4954 PetscFunctionReturn(0); 4955 } 4956 4957 #undef __FUNCT__ 4958 #define __FUNCT__ "DMPlexGenerate_Triangle" 4959 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4960 { 4961 MPI_Comm comm = ((PetscObject) boundary)->comm; 4962 PetscInt dim = 2; 4963 const PetscBool createConvexHull = PETSC_FALSE; 4964 const PetscBool constrained = PETSC_FALSE; 4965 struct triangulateio in; 4966 struct triangulateio out; 4967 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4968 PetscMPIInt rank; 4969 PetscErrorCode ierr; 4970 4971 PetscFunctionBegin; 4972 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4973 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4974 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4975 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4976 4977 in.numberofpoints = vEnd - vStart; 4978 if (in.numberofpoints > 0) { 4979 PetscSection coordSection; 4980 Vec coordinates; 4981 PetscScalar *array; 4982 4983 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4984 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4985 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4986 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4987 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4988 for (v = vStart; v < vEnd; ++v) { 4989 const PetscInt idx = v - vStart; 4990 PetscInt off, d; 4991 4992 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4993 for (d = 0; d < dim; ++d) { 4994 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4995 } 4996 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4997 } 4998 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4999 } 5000 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 5001 in.numberofsegments = eEnd - eStart; 5002 if (in.numberofsegments > 0) { 5003 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 5004 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 5005 for (e = eStart; e < eEnd; ++e) { 5006 const PetscInt idx = e - eStart; 5007 const PetscInt *cone; 5008 5009 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 5010 5011 in.segmentlist[idx*2+0] = cone[0] - vStart; 5012 in.segmentlist[idx*2+1] = cone[1] - vStart; 5013 5014 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5015 } 5016 } 5017 #if 0 /* Do not currently support holes */ 5018 PetscReal *holeCoords; 5019 PetscInt h, d; 5020 5021 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5022 if (in.numberofholes > 0) { 5023 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5024 for (h = 0; h < in.numberofholes; ++h) { 5025 for (d = 0; d < dim; ++d) { 5026 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5027 } 5028 } 5029 } 5030 #endif 5031 if (!rank) { 5032 char args[32]; 5033 5034 /* Take away 'Q' for verbose output */ 5035 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5036 if (createConvexHull) { 5037 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5038 } 5039 if (constrained) { 5040 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5041 } 5042 triangulate(args, &in, &out, PETSC_NULL); 5043 } 5044 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5045 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5046 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5047 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5048 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5049 5050 { 5051 const PetscInt numCorners = 3; 5052 const PetscInt numCells = out.numberoftriangles; 5053 const PetscInt numVertices = out.numberofpoints; 5054 const int *cells = out.trianglelist; 5055 const double *meshCoords = out.pointlist; 5056 5057 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5058 /* Set labels */ 5059 for (v = 0; v < numVertices; ++v) { 5060 if (out.pointmarkerlist[v]) { 5061 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5062 } 5063 } 5064 if (interpolate) { 5065 for (e = 0; e < out.numberofedges; e++) { 5066 if (out.edgemarkerlist[e]) { 5067 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5068 const PetscInt *edges; 5069 PetscInt numEdges; 5070 5071 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5072 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5073 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5074 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5075 } 5076 } 5077 } 5078 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5079 } 5080 #if 0 /* Do not currently support holes */ 5081 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5082 #endif 5083 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5084 PetscFunctionReturn(0); 5085 } 5086 5087 #undef __FUNCT__ 5088 #define __FUNCT__ "DMPlexRefine_Triangle" 5089 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5090 { 5091 MPI_Comm comm = ((PetscObject) dm)->comm; 5092 PetscInt dim = 2; 5093 struct triangulateio in; 5094 struct triangulateio out; 5095 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5096 PetscMPIInt rank; 5097 PetscErrorCode ierr; 5098 5099 PetscFunctionBegin; 5100 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5101 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5102 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5103 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5104 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5105 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5106 5107 in.numberofpoints = vEnd - vStart; 5108 if (in.numberofpoints > 0) { 5109 PetscSection coordSection; 5110 Vec coordinates; 5111 PetscScalar *array; 5112 5113 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5114 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5115 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5116 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5117 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5118 for (v = vStart; v < vEnd; ++v) { 5119 const PetscInt idx = v - vStart; 5120 PetscInt off, d; 5121 5122 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5123 for (d = 0; d < dim; ++d) { 5124 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5125 } 5126 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5127 } 5128 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5129 } 5130 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5131 5132 in.numberofcorners = 3; 5133 in.numberoftriangles = cEnd - cStart; 5134 5135 in.trianglearealist = (double*) maxVolumes; 5136 if (in.numberoftriangles > 0) { 5137 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5138 for (c = cStart; c < cEnd; ++c) { 5139 const PetscInt idx = c - cStart; 5140 PetscInt *closure = PETSC_NULL; 5141 PetscInt closureSize; 5142 5143 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5144 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5145 for (v = 0; v < 3; ++v) { 5146 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5147 } 5148 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5149 } 5150 } 5151 /* TODO: Segment markers are missing on input */ 5152 #if 0 /* Do not currently support holes */ 5153 PetscReal *holeCoords; 5154 PetscInt h, d; 5155 5156 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5157 if (in.numberofholes > 0) { 5158 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5159 for (h = 0; h < in.numberofholes; ++h) { 5160 for (d = 0; d < dim; ++d) { 5161 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5162 } 5163 } 5164 } 5165 #endif 5166 if (!rank) { 5167 char args[32]; 5168 5169 /* Take away 'Q' for verbose output */ 5170 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5171 triangulate(args, &in, &out, PETSC_NULL); 5172 } 5173 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5174 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5175 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5176 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5177 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5178 5179 { 5180 const PetscInt numCorners = 3; 5181 const PetscInt numCells = out.numberoftriangles; 5182 const PetscInt numVertices = out.numberofpoints; 5183 const int *cells = out.trianglelist; 5184 const double *meshCoords = out.pointlist; 5185 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5186 5187 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5188 /* Set labels */ 5189 for (v = 0; v < numVertices; ++v) { 5190 if (out.pointmarkerlist[v]) { 5191 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5192 } 5193 } 5194 if (interpolate) { 5195 PetscInt e; 5196 5197 for (e = 0; e < out.numberofedges; e++) { 5198 if (out.edgemarkerlist[e]) { 5199 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5200 const PetscInt *edges; 5201 PetscInt numEdges; 5202 5203 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5204 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5205 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5206 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5207 } 5208 } 5209 } 5210 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5211 } 5212 #if 0 /* Do not currently support holes */ 5213 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5214 #endif 5215 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5216 PetscFunctionReturn(0); 5217 } 5218 #endif 5219 5220 #if defined(PETSC_HAVE_TETGEN) 5221 #include <tetgen.h> 5222 #undef __FUNCT__ 5223 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5224 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5225 { 5226 MPI_Comm comm = ((PetscObject) boundary)->comm; 5227 const PetscInt dim = 3; 5228 ::tetgenio in; 5229 ::tetgenio out; 5230 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5231 PetscMPIInt rank; 5232 PetscErrorCode ierr; 5233 5234 PetscFunctionBegin; 5235 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5236 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5237 in.numberofpoints = vEnd - vStart; 5238 if (in.numberofpoints > 0) { 5239 PetscSection coordSection; 5240 Vec coordinates; 5241 PetscScalar *array; 5242 5243 in.pointlist = new double[in.numberofpoints*dim]; 5244 in.pointmarkerlist = new int[in.numberofpoints]; 5245 5246 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5247 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5248 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5249 for (v = vStart; v < vEnd; ++v) { 5250 const PetscInt idx = v - vStart; 5251 PetscInt off, d; 5252 5253 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5254 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5255 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5256 } 5257 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5258 } 5259 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5260 5261 in.numberoffacets = fEnd - fStart; 5262 if (in.numberoffacets > 0) { 5263 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5264 in.facetmarkerlist = new int[in.numberoffacets]; 5265 for (f = fStart; f < fEnd; ++f) { 5266 const PetscInt idx = f - fStart; 5267 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5268 5269 in.facetlist[idx].numberofpolygons = 1; 5270 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5271 in.facetlist[idx].numberofholes = 0; 5272 in.facetlist[idx].holelist = NULL; 5273 5274 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5275 for (p = 0; p < numPoints*2; p += 2) { 5276 const PetscInt point = points[p]; 5277 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5278 } 5279 5280 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5281 poly->numberofvertices = numVertices; 5282 poly->vertexlist = new int[poly->numberofvertices]; 5283 for (v = 0; v < numVertices; ++v) { 5284 const PetscInt vIdx = points[v] - vStart; 5285 poly->vertexlist[v] = vIdx; 5286 } 5287 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5288 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5289 } 5290 } 5291 if (!rank) { 5292 char args[32]; 5293 5294 /* Take away 'Q' for verbose output */ 5295 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5296 ::tetrahedralize(args, &in, &out); 5297 } 5298 { 5299 const PetscInt numCorners = 4; 5300 const PetscInt numCells = out.numberoftetrahedra; 5301 const PetscInt numVertices = out.numberofpoints; 5302 const int *cells = out.tetrahedronlist; 5303 const double *meshCoords = out.pointlist; 5304 5305 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5306 /* Set labels */ 5307 for (v = 0; v < numVertices; ++v) { 5308 if (out.pointmarkerlist[v]) { 5309 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5310 } 5311 } 5312 if (interpolate) { 5313 PetscInt e; 5314 5315 for (e = 0; e < out.numberofedges; e++) { 5316 if (out.edgemarkerlist[e]) { 5317 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5318 const PetscInt *edges; 5319 PetscInt numEdges; 5320 5321 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5322 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5323 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5324 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5325 } 5326 } 5327 for (f = 0; f < out.numberoftrifaces; f++) { 5328 if (out.trifacemarkerlist[f]) { 5329 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5330 const PetscInt *faces; 5331 PetscInt numFaces; 5332 5333 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5334 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5335 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5336 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5337 } 5338 } 5339 } 5340 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5341 } 5342 PetscFunctionReturn(0); 5343 } 5344 5345 #undef __FUNCT__ 5346 #define __FUNCT__ "DMPlexRefine_Tetgen" 5347 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5348 { 5349 MPI_Comm comm = ((PetscObject) dm)->comm; 5350 const PetscInt dim = 3; 5351 ::tetgenio in; 5352 ::tetgenio out; 5353 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5354 PetscMPIInt rank; 5355 PetscErrorCode ierr; 5356 5357 PetscFunctionBegin; 5358 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5359 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5360 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5361 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5362 5363 in.numberofpoints = vEnd - vStart; 5364 if (in.numberofpoints > 0) { 5365 PetscSection coordSection; 5366 Vec coordinates; 5367 PetscScalar *array; 5368 5369 in.pointlist = new double[in.numberofpoints*dim]; 5370 in.pointmarkerlist = new int[in.numberofpoints]; 5371 5372 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5373 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5374 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5375 for (v = vStart; v < vEnd; ++v) { 5376 const PetscInt idx = v - vStart; 5377 PetscInt off, d; 5378 5379 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5380 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5381 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5382 } 5383 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5384 } 5385 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5386 5387 in.numberofcorners = 4; 5388 in.numberoftetrahedra = cEnd - cStart; 5389 in.tetrahedronvolumelist = (double*) maxVolumes; 5390 if (in.numberoftetrahedra > 0) { 5391 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5392 for (c = cStart; c < cEnd; ++c) { 5393 const PetscInt idx = c - cStart; 5394 PetscInt *closure = PETSC_NULL; 5395 PetscInt closureSize; 5396 5397 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5398 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5399 for (v = 0; v < 4; ++v) { 5400 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5401 } 5402 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5403 } 5404 } 5405 /* TODO: Put in boundary faces with markers */ 5406 if (!rank) { 5407 char args[32]; 5408 5409 /* Take away 'Q' for verbose output */ 5410 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5411 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5412 ::tetrahedralize(args, &in, &out); 5413 } 5414 in.tetrahedronvolumelist = NULL; 5415 5416 { 5417 const PetscInt numCorners = 4; 5418 const PetscInt numCells = out.numberoftetrahedra; 5419 const PetscInt numVertices = out.numberofpoints; 5420 const int *cells = out.tetrahedronlist; 5421 const double *meshCoords = out.pointlist; 5422 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5423 5424 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5425 /* Set labels */ 5426 for (v = 0; v < numVertices; ++v) { 5427 if (out.pointmarkerlist[v]) { 5428 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5429 } 5430 } 5431 if (interpolate) { 5432 PetscInt e, f; 5433 5434 for (e = 0; e < out.numberofedges; e++) { 5435 if (out.edgemarkerlist[e]) { 5436 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5437 const PetscInt *edges; 5438 PetscInt numEdges; 5439 5440 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5441 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5442 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5443 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5444 } 5445 } 5446 for (f = 0; f < out.numberoftrifaces; f++) { 5447 if (out.trifacemarkerlist[f]) { 5448 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5449 const PetscInt *faces; 5450 PetscInt numFaces; 5451 5452 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5453 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5454 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5455 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5456 } 5457 } 5458 } 5459 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5460 } 5461 PetscFunctionReturn(0); 5462 } 5463 #endif 5464 5465 #if defined(PETSC_HAVE_CTETGEN) 5466 #include "ctetgen.h" 5467 5468 #undef __FUNCT__ 5469 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5470 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5471 { 5472 MPI_Comm comm = ((PetscObject) boundary)->comm; 5473 const PetscInt dim = 3; 5474 PLC *in, *out; 5475 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5476 PetscMPIInt rank; 5477 PetscErrorCode ierr; 5478 5479 PetscFunctionBegin; 5480 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5481 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5482 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5483 ierr = PLCCreate(&in);CHKERRQ(ierr); 5484 ierr = PLCCreate(&out);CHKERRQ(ierr); 5485 5486 in->numberofpoints = vEnd - vStart; 5487 if (in->numberofpoints > 0) { 5488 PetscSection coordSection; 5489 Vec coordinates; 5490 PetscScalar *array; 5491 5492 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5493 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5494 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5495 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5496 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5497 for (v = vStart; v < vEnd; ++v) { 5498 const PetscInt idx = v - vStart; 5499 PetscInt off, d, m; 5500 5501 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5502 for (d = 0; d < dim; ++d) { 5503 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5504 } 5505 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5506 5507 in->pointmarkerlist[idx] = (int) m; 5508 } 5509 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5510 } 5511 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5512 5513 in->numberoffacets = fEnd - fStart; 5514 if (in->numberoffacets > 0) { 5515 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5516 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5517 for (f = fStart; f < fEnd; ++f) { 5518 const PetscInt idx = f - fStart; 5519 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5520 polygon *poly; 5521 5522 in->facetlist[idx].numberofpolygons = 1; 5523 5524 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5525 5526 in->facetlist[idx].numberofholes = 0; 5527 in->facetlist[idx].holelist = PETSC_NULL; 5528 5529 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5530 for (p = 0; p < numPoints*2; p += 2) { 5531 const PetscInt point = points[p]; 5532 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5533 } 5534 5535 poly = in->facetlist[idx].polygonlist; 5536 poly->numberofvertices = numVertices; 5537 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5538 for (v = 0; v < numVertices; ++v) { 5539 const PetscInt vIdx = points[v] - vStart; 5540 poly->vertexlist[v] = vIdx; 5541 } 5542 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5543 in->facetmarkerlist[idx] = (int) m; 5544 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5545 } 5546 } 5547 if (!rank) { 5548 TetGenOpts t; 5549 5550 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5551 t.in = boundary; /* Should go away */ 5552 t.plc = 1; 5553 t.quality = 1; 5554 t.edgesout = 1; 5555 t.zeroindex = 1; 5556 t.quiet = 1; 5557 t.verbose = verbose; 5558 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5559 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5560 } 5561 { 5562 const PetscInt numCorners = 4; 5563 const PetscInt numCells = out->numberoftetrahedra; 5564 const PetscInt numVertices = out->numberofpoints; 5565 const int *cells = out->tetrahedronlist; 5566 const double *meshCoords = out->pointlist; 5567 5568 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5569 /* Set labels */ 5570 for (v = 0; v < numVertices; ++v) { 5571 if (out->pointmarkerlist[v]) { 5572 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5573 } 5574 } 5575 if (interpolate) { 5576 PetscInt e; 5577 5578 for (e = 0; e < out->numberofedges; e++) { 5579 if (out->edgemarkerlist[e]) { 5580 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5581 const PetscInt *edges; 5582 PetscInt numEdges; 5583 5584 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5585 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5586 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5587 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5588 } 5589 } 5590 for (f = 0; f < out->numberoftrifaces; f++) { 5591 if (out->trifacemarkerlist[f]) { 5592 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5593 const PetscInt *faces; 5594 PetscInt numFaces; 5595 5596 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5597 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5598 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5599 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5600 } 5601 } 5602 } 5603 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5604 } 5605 5606 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5607 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5608 PetscFunctionReturn(0); 5609 } 5610 5611 #undef __FUNCT__ 5612 #define __FUNCT__ "DMPlexRefine_CTetgen" 5613 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5614 { 5615 MPI_Comm comm = ((PetscObject) dm)->comm; 5616 const PetscInt dim = 3; 5617 PLC *in, *out; 5618 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5619 PetscMPIInt rank; 5620 PetscErrorCode ierr; 5621 5622 PetscFunctionBegin; 5623 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5624 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5625 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5626 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5627 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5628 ierr = PLCCreate(&in);CHKERRQ(ierr); 5629 ierr = PLCCreate(&out);CHKERRQ(ierr); 5630 5631 in->numberofpoints = vEnd - vStart; 5632 if (in->numberofpoints > 0) { 5633 PetscSection coordSection; 5634 Vec coordinates; 5635 PetscScalar *array; 5636 5637 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5638 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5639 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5640 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5641 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5642 for (v = vStart; v < vEnd; ++v) { 5643 const PetscInt idx = v - vStart; 5644 PetscInt off, d, m; 5645 5646 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5647 for (d = 0; d < dim; ++d) { 5648 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5649 } 5650 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5651 5652 in->pointmarkerlist[idx] = (int) m; 5653 } 5654 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5655 } 5656 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5657 5658 in->numberofcorners = 4; 5659 in->numberoftetrahedra = cEnd - cStart; 5660 in->tetrahedronvolumelist = maxVolumes; 5661 if (in->numberoftetrahedra > 0) { 5662 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5663 for (c = cStart; c < cEnd; ++c) { 5664 const PetscInt idx = c - cStart; 5665 PetscInt *closure = PETSC_NULL; 5666 PetscInt closureSize; 5667 5668 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5669 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5670 for (v = 0; v < 4; ++v) { 5671 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5672 } 5673 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5674 } 5675 } 5676 if (!rank) { 5677 TetGenOpts t; 5678 5679 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5680 5681 t.in = dm; /* Should go away */ 5682 t.refine = 1; 5683 t.varvolume = 1; 5684 t.quality = 1; 5685 t.edgesout = 1; 5686 t.zeroindex = 1; 5687 t.quiet = 1; 5688 t.verbose = verbose; /* Change this */ 5689 5690 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5691 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5692 } 5693 { 5694 const PetscInt numCorners = 4; 5695 const PetscInt numCells = out->numberoftetrahedra; 5696 const PetscInt numVertices = out->numberofpoints; 5697 const int *cells = out->tetrahedronlist; 5698 const double *meshCoords = out->pointlist; 5699 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5700 5701 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5702 /* Set labels */ 5703 for (v = 0; v < numVertices; ++v) { 5704 if (out->pointmarkerlist[v]) { 5705 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5706 } 5707 } 5708 if (interpolate) { 5709 PetscInt e, f; 5710 5711 for (e = 0; e < out->numberofedges; e++) { 5712 if (out->edgemarkerlist[e]) { 5713 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5714 const PetscInt *edges; 5715 PetscInt numEdges; 5716 5717 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5718 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5719 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5720 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5721 } 5722 } 5723 for (f = 0; f < out->numberoftrifaces; f++) { 5724 if (out->trifacemarkerlist[f]) { 5725 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5726 const PetscInt *faces; 5727 PetscInt numFaces; 5728 5729 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5730 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5731 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5732 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5733 } 5734 } 5735 } 5736 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5737 } 5738 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5739 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5740 PetscFunctionReturn(0); 5741 } 5742 #endif 5743 5744 #undef __FUNCT__ 5745 #define __FUNCT__ "DMPlexGenerate" 5746 /*@C 5747 DMPlexGenerate - Generates a mesh. 5748 5749 Not Collective 5750 5751 Input Parameters: 5752 + boundary - The DMPlex boundary object 5753 . name - The mesh generation package name 5754 - interpolate - Flag to create intermediate mesh elements 5755 5756 Output Parameter: 5757 . mesh - The DMPlex object 5758 5759 Level: intermediate 5760 5761 .keywords: mesh, elements 5762 .seealso: DMPlexCreate(), DMRefine() 5763 @*/ 5764 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5765 { 5766 PetscInt dim; 5767 char genname[1024]; 5768 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5769 PetscErrorCode ierr; 5770 5771 PetscFunctionBegin; 5772 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5773 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5774 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5775 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5776 if (flg) name = genname; 5777 if (name) { 5778 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5779 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5780 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5781 } 5782 switch (dim) { 5783 case 1: 5784 if (!name || isTriangle) { 5785 #if defined(PETSC_HAVE_TRIANGLE) 5786 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5787 #else 5788 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5789 #endif 5790 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5791 break; 5792 case 2: 5793 if (!name || isCTetgen) { 5794 #if defined(PETSC_HAVE_CTETGEN) 5795 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5796 #else 5797 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5798 #endif 5799 } else if (isTetgen) { 5800 #if defined(PETSC_HAVE_TETGEN) 5801 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5802 #else 5803 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5804 #endif 5805 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5806 break; 5807 default: 5808 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5809 } 5810 PetscFunctionReturn(0); 5811 } 5812 5813 typedef PetscInt CellRefiner; 5814 5815 #undef __FUNCT__ 5816 #define __FUNCT__ "GetDepthStart_Private" 5817 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5818 { 5819 PetscFunctionBegin; 5820 if (cStart) *cStart = 0; 5821 if (vStart) *vStart = depthSize[depth]; 5822 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5823 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5824 PetscFunctionReturn(0); 5825 } 5826 5827 #undef __FUNCT__ 5828 #define __FUNCT__ "GetDepthEnd_Private" 5829 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5830 { 5831 PetscFunctionBegin; 5832 if (cEnd) *cEnd = depthSize[depth]; 5833 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5834 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5835 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5836 PetscFunctionReturn(0); 5837 } 5838 5839 #undef __FUNCT__ 5840 #define __FUNCT__ "CellRefinerGetSizes" 5841 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5842 { 5843 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5844 PetscErrorCode ierr; 5845 5846 PetscFunctionBegin; 5847 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5848 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5849 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5850 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5851 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5852 switch (refiner) { 5853 case 1: 5854 /* Simplicial 2D */ 5855 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5856 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5857 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5858 break; 5859 case 3: 5860 /* Hybrid 2D */ 5861 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5862 cMax = PetscMin(cEnd, cMax); 5863 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5864 fMax = PetscMin(fEnd, fMax); 5865 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5866 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 */ 5867 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5868 break; 5869 case 2: 5870 /* Hex 2D */ 5871 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5872 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5873 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5874 break; 5875 default: 5876 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5877 } 5878 PetscFunctionReturn(0); 5879 } 5880 5881 #undef __FUNCT__ 5882 #define __FUNCT__ "CellRefinerSetConeSizes" 5883 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5884 { 5885 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5886 PetscErrorCode ierr; 5887 5888 PetscFunctionBegin; 5889 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5890 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5891 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5892 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5893 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5894 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5895 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5896 switch (refiner) { 5897 case 1: 5898 /* Simplicial 2D */ 5899 /* All cells have 3 faces */ 5900 for (c = cStart; c < cEnd; ++c) { 5901 for (r = 0; r < 4; ++r) { 5902 const PetscInt newp = (c - cStart)*4 + r; 5903 5904 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5905 } 5906 } 5907 /* Split faces have 2 vertices and the same cells as the parent */ 5908 for (f = fStart; f < fEnd; ++f) { 5909 for (r = 0; r < 2; ++r) { 5910 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5911 PetscInt size; 5912 5913 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5914 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5915 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5916 } 5917 } 5918 /* Interior faces have 2 vertices and 2 cells */ 5919 for (c = cStart; c < cEnd; ++c) { 5920 for (r = 0; r < 3; ++r) { 5921 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5922 5923 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5924 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5925 } 5926 } 5927 /* Old vertices have identical supports */ 5928 for (v = vStart; v < vEnd; ++v) { 5929 const PetscInt newp = vStartNew + (v - vStart); 5930 PetscInt size; 5931 5932 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5933 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5934 } 5935 /* Face vertices have 2 + cells*2 supports */ 5936 for (f = fStart; f < fEnd; ++f) { 5937 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5938 PetscInt size; 5939 5940 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5941 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5942 } 5943 break; 5944 case 2: 5945 /* Hex 2D */ 5946 /* All cells have 4 faces */ 5947 for (c = cStart; c < cEnd; ++c) { 5948 for (r = 0; r < 4; ++r) { 5949 const PetscInt newp = (c - cStart)*4 + r; 5950 5951 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5952 } 5953 } 5954 /* Split faces have 2 vertices and the same cells as the parent */ 5955 for (f = fStart; f < fEnd; ++f) { 5956 for (r = 0; r < 2; ++r) { 5957 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5958 PetscInt size; 5959 5960 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5961 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5962 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5963 } 5964 } 5965 /* Interior faces have 2 vertices and 2 cells */ 5966 for (c = cStart; c < cEnd; ++c) { 5967 for (r = 0; r < 4; ++r) { 5968 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5969 5970 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5971 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5972 } 5973 } 5974 /* Old vertices have identical supports */ 5975 for (v = vStart; v < vEnd; ++v) { 5976 const PetscInt newp = vStartNew + (v - vStart); 5977 PetscInt size; 5978 5979 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5980 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5981 } 5982 /* Face vertices have 2 + cells supports */ 5983 for (f = fStart; f < fEnd; ++f) { 5984 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5985 PetscInt size; 5986 5987 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5988 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5989 } 5990 /* Cell vertices have 4 supports */ 5991 for (c = cStart; c < cEnd; ++c) { 5992 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5993 5994 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5995 } 5996 break; 5997 case 3: 5998 /* Hybrid 2D */ 5999 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6000 cMax = PetscMin(cEnd, cMax); 6001 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6002 fMax = PetscMin(fEnd, fMax); 6003 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6004 /* Interior cells have 3 faces */ 6005 for (c = cStart; c < cMax; ++c) { 6006 for (r = 0; r < 4; ++r) { 6007 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 6008 6009 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 6010 } 6011 } 6012 /* Hybrid cells have 4 faces */ 6013 for (c = cMax; c < cEnd; ++c) { 6014 for (r = 0; r < 2; ++r) { 6015 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6016 6017 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6018 } 6019 } 6020 /* Interior split faces have 2 vertices and the same cells as the parent */ 6021 for (f = fStart; f < fMax; ++f) { 6022 for (r = 0; r < 2; ++r) { 6023 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6024 PetscInt size; 6025 6026 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6027 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6028 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6029 } 6030 } 6031 /* Interior cell faces have 2 vertices and 2 cells */ 6032 for (c = cStart; c < cMax; ++c) { 6033 for (r = 0; r < 3; ++r) { 6034 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6035 6036 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6037 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6038 } 6039 } 6040 /* Hybrid faces have 2 vertices and the same cells */ 6041 for (f = fMax; f < fEnd; ++f) { 6042 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6043 PetscInt size; 6044 6045 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6046 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6047 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6048 } 6049 /* Hybrid cell faces have 2 vertices and 2 cells */ 6050 for (c = cMax; c < cEnd; ++c) { 6051 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6052 6053 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6054 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6055 } 6056 /* Old vertices have identical supports */ 6057 for (v = vStart; v < vEnd; ++v) { 6058 const PetscInt newp = vStartNew + (v - vStart); 6059 PetscInt size; 6060 6061 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6062 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6063 } 6064 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6065 for (f = fStart; f < fMax; ++f) { 6066 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6067 const PetscInt *support; 6068 PetscInt size, newSize = 2, s; 6069 6070 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6071 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6072 for (s = 0; s < size; ++s) { 6073 if (support[s] >= cMax) newSize += 1; 6074 else newSize += 2; 6075 } 6076 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6077 } 6078 break; 6079 default: 6080 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6081 } 6082 PetscFunctionReturn(0); 6083 } 6084 6085 #undef __FUNCT__ 6086 #define __FUNCT__ "CellRefinerSetCones" 6087 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6088 { 6089 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; 6090 PetscInt maxSupportSize, *supportRef; 6091 PetscErrorCode ierr; 6092 6093 PetscFunctionBegin; 6094 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6095 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6096 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6097 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6098 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6099 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6100 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6101 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6102 switch (refiner) { 6103 case 1: 6104 /* Simplicial 2D */ 6105 /* 6106 2 6107 |\ 6108 | \ 6109 | \ 6110 | \ 6111 | C \ 6112 | \ 6113 | \ 6114 2---1---1 6115 |\ D / \ 6116 | 2 0 \ 6117 |A \ / B \ 6118 0---0-------1 6119 */ 6120 /* All cells have 3 faces */ 6121 for (c = cStart; c < cEnd; ++c) { 6122 const PetscInt newp = cStartNew + (c - cStart)*4; 6123 const PetscInt *cone, *ornt; 6124 PetscInt coneNew[3], orntNew[3]; 6125 6126 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6127 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6128 /* A triangle */ 6129 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6130 orntNew[0] = ornt[0]; 6131 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6132 orntNew[1] = -2; 6133 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6134 orntNew[2] = ornt[2]; 6135 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6136 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6137 #if 1 6138 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); 6139 for (p = 0; p < 3; ++p) { 6140 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); 6141 } 6142 #endif 6143 /* B triangle */ 6144 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6145 orntNew[0] = ornt[0]; 6146 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6147 orntNew[1] = ornt[1]; 6148 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6149 orntNew[2] = -2; 6150 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6151 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6152 #if 1 6153 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); 6154 for (p = 0; p < 3; ++p) { 6155 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); 6156 } 6157 #endif 6158 /* C triangle */ 6159 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6160 orntNew[0] = -2; 6161 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6162 orntNew[1] = ornt[1]; 6163 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6164 orntNew[2] = ornt[2]; 6165 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6166 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6167 #if 1 6168 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); 6169 for (p = 0; p < 3; ++p) { 6170 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); 6171 } 6172 #endif 6173 /* D triangle */ 6174 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6175 orntNew[0] = 0; 6176 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6177 orntNew[1] = 0; 6178 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6179 orntNew[2] = 0; 6180 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6181 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6182 #if 1 6183 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); 6184 for (p = 0; p < 3; ++p) { 6185 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); 6186 } 6187 #endif 6188 } 6189 /* Split faces have 2 vertices and the same cells as the parent */ 6190 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6191 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6192 for (f = fStart; f < fEnd; ++f) { 6193 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6194 6195 for (r = 0; r < 2; ++r) { 6196 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6197 const PetscInt *cone, *support; 6198 PetscInt coneNew[2], coneSize, c, supportSize, s; 6199 6200 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6201 coneNew[0] = vStartNew + (cone[0] - vStart); 6202 coneNew[1] = vStartNew + (cone[1] - vStart); 6203 coneNew[(r+1)%2] = newv; 6204 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6205 #if 1 6206 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6207 for (p = 0; p < 2; ++p) { 6208 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); 6209 } 6210 #endif 6211 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6212 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6213 for (s = 0; s < supportSize; ++s) { 6214 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6215 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6216 for (c = 0; c < coneSize; ++c) { 6217 if (cone[c] == f) break; 6218 } 6219 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6220 } 6221 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6222 #if 1 6223 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6224 for (p = 0; p < supportSize; ++p) { 6225 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); 6226 } 6227 #endif 6228 } 6229 } 6230 /* Interior faces have 2 vertices and 2 cells */ 6231 for (c = cStart; c < cEnd; ++c) { 6232 const PetscInt *cone; 6233 6234 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6235 for (r = 0; r < 3; ++r) { 6236 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6237 PetscInt coneNew[2]; 6238 PetscInt supportNew[2]; 6239 6240 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6241 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6242 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6243 #if 1 6244 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6245 for (p = 0; p < 2; ++p) { 6246 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); 6247 } 6248 #endif 6249 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6250 supportNew[1] = (c - cStart)*4 + 3; 6251 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6252 #if 1 6253 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6254 for (p = 0; p < 2; ++p) { 6255 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); 6256 } 6257 #endif 6258 } 6259 } 6260 /* Old vertices have identical supports */ 6261 for (v = vStart; v < vEnd; ++v) { 6262 const PetscInt newp = vStartNew + (v - vStart); 6263 const PetscInt *support, *cone; 6264 PetscInt size, s; 6265 6266 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6267 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6268 for (s = 0; s < size; ++s) { 6269 PetscInt r = 0; 6270 6271 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6272 if (cone[1] == v) r = 1; 6273 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6274 } 6275 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6276 #if 1 6277 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6278 for (p = 0; p < size; ++p) { 6279 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); 6280 } 6281 #endif 6282 } 6283 /* Face vertices have 2 + cells*2 supports */ 6284 for (f = fStart; f < fEnd; ++f) { 6285 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6286 const PetscInt *cone, *support; 6287 PetscInt size, s; 6288 6289 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6290 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6291 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6292 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6293 for (s = 0; s < size; ++s) { 6294 PetscInt r = 0; 6295 6296 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6297 if (cone[1] == f) r = 1; 6298 else if (cone[2] == f) r = 2; 6299 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6300 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6301 } 6302 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6303 #if 1 6304 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6305 for (p = 0; p < 2+size*2; ++p) { 6306 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); 6307 } 6308 #endif 6309 } 6310 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6311 break; 6312 case 2: 6313 /* Hex 2D */ 6314 /* 6315 3---------2---------2 6316 | | | 6317 | D 2 C | 6318 | | | 6319 3----3----0----1----1 6320 | | | 6321 | A 0 B | 6322 | | | 6323 0---------0---------1 6324 */ 6325 /* All cells have 4 faces */ 6326 for (c = cStart; c < cEnd; ++c) { 6327 const PetscInt newp = (c - cStart)*4; 6328 const PetscInt *cone, *ornt; 6329 PetscInt coneNew[4], orntNew[4]; 6330 6331 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6332 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6333 /* A quad */ 6334 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6335 orntNew[0] = ornt[0]; 6336 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6337 orntNew[1] = 0; 6338 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6339 orntNew[2] = -2; 6340 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6341 orntNew[3] = ornt[3]; 6342 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6343 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6344 #if 1 6345 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); 6346 for (p = 0; p < 4; ++p) { 6347 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); 6348 } 6349 #endif 6350 /* B quad */ 6351 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6352 orntNew[0] = ornt[0]; 6353 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6354 orntNew[1] = ornt[1]; 6355 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6356 orntNew[2] = 0; 6357 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6358 orntNew[3] = -2; 6359 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6360 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6361 #if 1 6362 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); 6363 for (p = 0; p < 4; ++p) { 6364 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); 6365 } 6366 #endif 6367 /* C quad */ 6368 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6369 orntNew[0] = -2; 6370 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6371 orntNew[1] = ornt[1]; 6372 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6373 orntNew[2] = ornt[2]; 6374 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6375 orntNew[3] = 0; 6376 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6377 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6378 #if 1 6379 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); 6380 for (p = 0; p < 4; ++p) { 6381 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); 6382 } 6383 #endif 6384 /* D quad */ 6385 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6386 orntNew[0] = 0; 6387 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6388 orntNew[1] = -2; 6389 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6390 orntNew[2] = ornt[2]; 6391 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6392 orntNew[3] = ornt[3]; 6393 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6394 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6395 #if 1 6396 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); 6397 for (p = 0; p < 4; ++p) { 6398 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); 6399 } 6400 #endif 6401 } 6402 /* Split faces have 2 vertices and the same cells as the parent */ 6403 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6404 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6405 for (f = fStart; f < fEnd; ++f) { 6406 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6407 6408 for (r = 0; r < 2; ++r) { 6409 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6410 const PetscInt *cone, *support; 6411 PetscInt coneNew[2], coneSize, c, supportSize, s; 6412 6413 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6414 coneNew[0] = vStartNew + (cone[0] - vStart); 6415 coneNew[1] = vStartNew + (cone[1] - vStart); 6416 coneNew[(r+1)%2] = newv; 6417 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6418 #if 1 6419 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6420 for (p = 0; p < 2; ++p) { 6421 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); 6422 } 6423 #endif 6424 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6425 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6426 for (s = 0; s < supportSize; ++s) { 6427 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6428 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6429 for (c = 0; c < coneSize; ++c) { 6430 if (cone[c] == f) break; 6431 } 6432 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6433 } 6434 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6435 #if 1 6436 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6437 for (p = 0; p < supportSize; ++p) { 6438 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); 6439 } 6440 #endif 6441 } 6442 } 6443 /* Interior faces have 2 vertices and 2 cells */ 6444 for (c = cStart; c < cEnd; ++c) { 6445 const PetscInt *cone; 6446 PetscInt coneNew[2], supportNew[2]; 6447 6448 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6449 for (r = 0; r < 4; ++r) { 6450 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6451 6452 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6453 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6454 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6455 #if 1 6456 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6457 for (p = 0; p < 2; ++p) { 6458 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6459 } 6460 #endif 6461 supportNew[0] = (c - cStart)*4 + r; 6462 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6463 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6464 #if 1 6465 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6466 for (p = 0; p < 2; ++p) { 6467 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6468 } 6469 #endif 6470 } 6471 } 6472 /* Old vertices have identical supports */ 6473 for (v = vStart; v < vEnd; ++v) { 6474 const PetscInt newp = vStartNew + (v - vStart); 6475 const PetscInt *support, *cone; 6476 PetscInt size, s; 6477 6478 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6479 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6480 for (s = 0; s < size; ++s) { 6481 PetscInt r = 0; 6482 6483 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6484 if (cone[1] == v) r = 1; 6485 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6486 } 6487 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6488 #if 1 6489 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6490 for (p = 0; p < size; ++p) { 6491 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); 6492 } 6493 #endif 6494 } 6495 /* Face vertices have 2 + cells supports */ 6496 for (f = fStart; f < fEnd; ++f) { 6497 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6498 const PetscInt *cone, *support; 6499 PetscInt size, s; 6500 6501 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6502 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6503 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6504 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6505 for (s = 0; s < size; ++s) { 6506 PetscInt r = 0; 6507 6508 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6509 if (cone[1] == f) r = 1; 6510 else if (cone[2] == f) r = 2; 6511 else if (cone[3] == f) r = 3; 6512 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6513 } 6514 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6515 #if 1 6516 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6517 for (p = 0; p < 2+size; ++p) { 6518 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); 6519 } 6520 #endif 6521 } 6522 /* Cell vertices have 4 supports */ 6523 for (c = cStart; c < cEnd; ++c) { 6524 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6525 PetscInt supportNew[4]; 6526 6527 for (r = 0; r < 4; ++r) { 6528 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6529 } 6530 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6531 } 6532 break; 6533 case 3: 6534 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6535 cMax = PetscMin(cEnd, cMax); 6536 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6537 fMax = PetscMin(fEnd, fMax); 6538 /* Interior cells have 3 faces */ 6539 for (c = cStart; c < cMax; ++c) { 6540 const PetscInt newp = cStartNew + (c - cStart)*4; 6541 const PetscInt *cone, *ornt; 6542 PetscInt coneNew[3], orntNew[3]; 6543 6544 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6545 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6546 /* A triangle */ 6547 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6548 orntNew[0] = ornt[0]; 6549 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6550 orntNew[1] = -2; 6551 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6552 orntNew[2] = ornt[2]; 6553 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6554 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6555 #if 1 6556 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); 6557 for (p = 0; p < 3; ++p) { 6558 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); 6559 } 6560 #endif 6561 /* B triangle */ 6562 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6563 orntNew[0] = ornt[0]; 6564 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6565 orntNew[1] = ornt[1]; 6566 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6567 orntNew[2] = -2; 6568 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6569 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6570 #if 1 6571 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); 6572 for (p = 0; p < 3; ++p) { 6573 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); 6574 } 6575 #endif 6576 /* C triangle */ 6577 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6578 orntNew[0] = -2; 6579 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6580 orntNew[1] = ornt[1]; 6581 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6582 orntNew[2] = ornt[2]; 6583 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6584 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6585 #if 1 6586 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); 6587 for (p = 0; p < 3; ++p) { 6588 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); 6589 } 6590 #endif 6591 /* D triangle */ 6592 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6593 orntNew[0] = 0; 6594 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6595 orntNew[1] = 0; 6596 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6597 orntNew[2] = 0; 6598 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6599 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6600 #if 1 6601 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); 6602 for (p = 0; p < 3; ++p) { 6603 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); 6604 } 6605 #endif 6606 } 6607 /* 6608 2----3----3 6609 | | 6610 | B | 6611 | | 6612 0----4--- 1 6613 | | 6614 | A | 6615 | | 6616 0----2----1 6617 */ 6618 /* Hybrid cells have 4 faces */ 6619 for (c = cMax; c < cEnd; ++c) { 6620 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6621 const PetscInt *cone, *ornt; 6622 PetscInt coneNew[4], orntNew[4]; 6623 6624 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6625 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6626 /* A quad */ 6627 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6628 orntNew[0] = ornt[0]; 6629 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6630 orntNew[1] = ornt[1]; 6631 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6632 orntNew[2] = 0; 6633 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6634 orntNew[3] = 0; 6635 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6636 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6637 #if 1 6638 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); 6639 for (p = 0; p < 4; ++p) { 6640 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); 6641 } 6642 #endif 6643 /* B quad */ 6644 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6645 orntNew[0] = ornt[0]; 6646 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6647 orntNew[1] = ornt[1]; 6648 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6649 orntNew[2] = 0; 6650 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6651 orntNew[3] = 0; 6652 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6653 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6654 #if 1 6655 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); 6656 for (p = 0; p < 4; ++p) { 6657 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); 6658 } 6659 #endif 6660 } 6661 /* Interior split faces have 2 vertices and the same cells as the parent */ 6662 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6663 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6664 for (f = fStart; f < fMax; ++f) { 6665 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6666 6667 for (r = 0; r < 2; ++r) { 6668 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6669 const PetscInt *cone, *support; 6670 PetscInt coneNew[2], coneSize, c, supportSize, s; 6671 6672 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6673 coneNew[0] = vStartNew + (cone[0] - vStart); 6674 coneNew[1] = vStartNew + (cone[1] - vStart); 6675 coneNew[(r+1)%2] = newv; 6676 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6677 #if 1 6678 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6679 for (p = 0; p < 2; ++p) { 6680 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); 6681 } 6682 #endif 6683 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6684 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6685 for (s = 0; s < supportSize; ++s) { 6686 if (support[s] >= cMax) { 6687 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6688 } else { 6689 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6690 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6691 for (c = 0; c < coneSize; ++c) { 6692 if (cone[c] == f) break; 6693 } 6694 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6695 } 6696 } 6697 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6698 #if 1 6699 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6700 for (p = 0; p < supportSize; ++p) { 6701 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); 6702 } 6703 #endif 6704 } 6705 } 6706 /* Interior cell faces have 2 vertices and 2 cells */ 6707 for (c = cStart; c < cMax; ++c) { 6708 const PetscInt *cone; 6709 6710 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6711 for (r = 0; r < 3; ++r) { 6712 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6713 PetscInt coneNew[2]; 6714 PetscInt supportNew[2]; 6715 6716 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6717 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6718 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6719 #if 1 6720 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6721 for (p = 0; p < 2; ++p) { 6722 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); 6723 } 6724 #endif 6725 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6726 supportNew[1] = (c - cStart)*4 + 3; 6727 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6728 #if 1 6729 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6730 for (p = 0; p < 2; ++p) { 6731 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); 6732 } 6733 #endif 6734 } 6735 } 6736 /* Interior hybrid faces have 2 vertices and the same cells */ 6737 for (f = fMax; f < fEnd; ++f) { 6738 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6739 const PetscInt *cone; 6740 const PetscInt *support; 6741 PetscInt coneNew[2]; 6742 PetscInt supportNew[2]; 6743 PetscInt size, s, r; 6744 6745 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6746 coneNew[0] = vStartNew + (cone[0] - vStart); 6747 coneNew[1] = vStartNew + (cone[1] - vStart); 6748 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6749 #if 1 6750 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6751 for (p = 0; p < 2; ++p) { 6752 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); 6753 } 6754 #endif 6755 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6756 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6757 for (s = 0; s < size; ++s) { 6758 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6759 for (r = 0; r < 2; ++r) { 6760 if (cone[r+2] == f) break; 6761 } 6762 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6763 } 6764 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6765 #if 1 6766 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6767 for (p = 0; p < size; ++p) { 6768 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); 6769 } 6770 #endif 6771 } 6772 /* Cell hybrid faces have 2 vertices and 2 cells */ 6773 for (c = cMax; c < cEnd; ++c) { 6774 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6775 const PetscInt *cone; 6776 PetscInt coneNew[2]; 6777 PetscInt supportNew[2]; 6778 6779 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6780 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6781 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6782 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6783 #if 1 6784 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6785 for (p = 0; p < 2; ++p) { 6786 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); 6787 } 6788 #endif 6789 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6790 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6791 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6792 #if 1 6793 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6794 for (p = 0; p < 2; ++p) { 6795 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); 6796 } 6797 #endif 6798 } 6799 /* Old vertices have identical supports */ 6800 for (v = vStart; v < vEnd; ++v) { 6801 const PetscInt newp = vStartNew + (v - vStart); 6802 const PetscInt *support, *cone; 6803 PetscInt size, s; 6804 6805 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6806 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6807 for (s = 0; s < size; ++s) { 6808 if (support[s] >= fMax) { 6809 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6810 } else { 6811 PetscInt r = 0; 6812 6813 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6814 if (cone[1] == v) r = 1; 6815 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6816 } 6817 } 6818 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6819 #if 1 6820 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6821 for (p = 0; p < size; ++p) { 6822 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); 6823 } 6824 #endif 6825 } 6826 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6827 for (f = fStart; f < fMax; ++f) { 6828 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6829 const PetscInt *cone, *support; 6830 PetscInt size, newSize = 2, s; 6831 6832 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6833 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6834 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6835 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6836 for (s = 0; s < size; ++s) { 6837 PetscInt r = 0; 6838 6839 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6840 if (support[s] >= cMax) { 6841 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6842 6843 newSize += 1; 6844 } else { 6845 if (cone[1] == f) r = 1; 6846 else if (cone[2] == f) r = 2; 6847 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6848 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6849 6850 newSize += 2; 6851 } 6852 } 6853 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6854 #if 1 6855 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6856 for (p = 0; p < newSize; ++p) { 6857 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); 6858 } 6859 #endif 6860 } 6861 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6862 break; 6863 default: 6864 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6865 } 6866 PetscFunctionReturn(0); 6867 } 6868 6869 #undef __FUNCT__ 6870 #define __FUNCT__ "CellRefinerSetCoordinates" 6871 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6872 { 6873 PetscSection coordSection, coordSectionNew; 6874 Vec coordinates, coordinatesNew; 6875 PetscScalar *coords, *coordsNew; 6876 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6877 PetscErrorCode ierr; 6878 6879 PetscFunctionBegin; 6880 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6881 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6882 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6883 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6884 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6885 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6886 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6887 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6888 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6889 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6890 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6891 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6892 if (fMax < 0) fMax = fEnd; 6893 switch (refiner) { 6894 case 1: 6895 case 2: 6896 case 3: 6897 /* Simplicial and Hex 2D */ 6898 /* All vertices have the dim coordinates */ 6899 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6900 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6901 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6902 } 6903 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6904 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6905 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6906 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6907 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6908 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6909 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6910 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6911 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6912 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6913 /* Old vertices have the same coordinates */ 6914 for (v = vStart; v < vEnd; ++v) { 6915 const PetscInt newv = vStartNew + (v - vStart); 6916 PetscInt off, offnew, d; 6917 6918 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6919 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6920 for (d = 0; d < dim; ++d) { 6921 coordsNew[offnew+d] = coords[off+d]; 6922 } 6923 } 6924 /* Face vertices have the average of endpoint coordinates */ 6925 for (f = fStart; f < fMax; ++f) { 6926 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6927 const PetscInt *cone; 6928 PetscInt coneSize, offA, offB, offnew, d; 6929 6930 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6931 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6932 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6933 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6934 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6935 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6936 for (d = 0; d < dim; ++d) { 6937 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6938 } 6939 } 6940 /* Just Hex 2D */ 6941 if (refiner == 2) { 6942 /* Cell vertices have the average of corner coordinates */ 6943 for (c = cStart; c < cEnd; ++c) { 6944 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6945 PetscInt *cone = PETSC_NULL; 6946 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6947 6948 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6949 for (p = 0; p < closureSize*2; p += 2) { 6950 const PetscInt point = cone[p]; 6951 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6952 } 6953 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6954 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6955 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6956 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6957 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6958 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6959 for (d = 0; d < dim; ++d) { 6960 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6961 } 6962 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6963 } 6964 } 6965 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6966 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6967 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6968 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6969 break; 6970 default: 6971 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6972 } 6973 PetscFunctionReturn(0); 6974 } 6975 6976 #undef __FUNCT__ 6977 #define __FUNCT__ "DMPlexCreateProcessSF" 6978 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6979 { 6980 PetscInt numRoots, numLeaves, l; 6981 const PetscInt *localPoints; 6982 const PetscSFNode *remotePoints; 6983 PetscInt *localPointsNew; 6984 PetscSFNode *remotePointsNew; 6985 PetscInt *ranks, *ranksNew; 6986 PetscErrorCode ierr; 6987 6988 PetscFunctionBegin; 6989 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6990 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6991 for (l = 0; l < numLeaves; ++l) { 6992 ranks[l] = remotePoints[l].rank; 6993 } 6994 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6995 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6996 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6997 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6998 for (l = 0; l < numLeaves; ++l) { 6999 ranksNew[l] = ranks[l]; 7000 localPointsNew[l] = l; 7001 remotePointsNew[l].index = 0; 7002 remotePointsNew[l].rank = ranksNew[l]; 7003 } 7004 ierr = PetscFree(ranks);CHKERRQ(ierr); 7005 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 7006 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 7007 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 7008 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7009 PetscFunctionReturn(0); 7010 } 7011 7012 #undef __FUNCT__ 7013 #define __FUNCT__ "CellRefinerCreateSF" 7014 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7015 { 7016 PetscSF sf, sfNew, sfProcess; 7017 IS processRanks; 7018 MPI_Datatype depthType; 7019 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7020 const PetscInt *localPoints, *neighbors; 7021 const PetscSFNode *remotePoints; 7022 PetscInt *localPointsNew; 7023 PetscSFNode *remotePointsNew; 7024 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7025 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7026 PetscErrorCode ierr; 7027 7028 PetscFunctionBegin; 7029 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7030 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7031 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7032 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7033 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7034 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7035 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7036 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7037 switch (refiner) { 7038 case 3: 7039 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7040 cMax = PetscMin(cEnd, cMax); 7041 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7042 fMax = PetscMin(fEnd, fMax); 7043 } 7044 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7045 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7046 /* Caculate size of new SF */ 7047 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7048 if (numRoots < 0) PetscFunctionReturn(0); 7049 for (l = 0; l < numLeaves; ++l) { 7050 const PetscInt p = localPoints[l]; 7051 7052 switch (refiner) { 7053 case 1: 7054 /* Simplicial 2D */ 7055 if ((p >= vStart) && (p < vEnd)) { 7056 /* Old vertices stay the same */ 7057 ++numLeavesNew; 7058 } else if ((p >= fStart) && (p < fEnd)) { 7059 /* Old faces add new faces and vertex */ 7060 numLeavesNew += 1 + 2; 7061 } else if ((p >= cStart) && (p < cEnd)) { 7062 /* Old cells add new cells and interior faces */ 7063 numLeavesNew += 4 + 3; 7064 } 7065 break; 7066 case 2: 7067 /* Hex 2D */ 7068 if ((p >= vStart) && (p < vEnd)) { 7069 /* Old vertices stay the same */ 7070 ++numLeavesNew; 7071 } else if ((p >= fStart) && (p < fEnd)) { 7072 /* Old faces add new faces and vertex */ 7073 numLeavesNew += 1 + 2; 7074 } else if ((p >= cStart) && (p < cEnd)) { 7075 /* Old cells add new cells and interior faces */ 7076 numLeavesNew += 4 + 4; 7077 } 7078 break; 7079 default: 7080 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7081 } 7082 } 7083 /* Communicate depthSizes for each remote rank */ 7084 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7085 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7086 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7087 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); 7088 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7089 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7090 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7091 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7092 for (n = 0; n < numNeighbors; ++n) { 7093 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7094 } 7095 depthSizeOld[depth] = cMax; 7096 depthSizeOld[0] = vMax; 7097 depthSizeOld[depth-1] = fMax; 7098 depthSizeOld[1] = eMax; 7099 7100 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7101 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7102 7103 depthSizeOld[depth] = cEnd - cStart; 7104 depthSizeOld[0] = vEnd - vStart; 7105 depthSizeOld[depth-1] = fEnd - fStart; 7106 depthSizeOld[1] = eEnd - eStart; 7107 7108 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7109 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7110 for (n = 0; n < numNeighbors; ++n) { 7111 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7112 } 7113 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7114 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7115 /* Calculate new point SF */ 7116 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7117 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7118 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7119 for (l = 0, m = 0; l < numLeaves; ++l) { 7120 PetscInt p = localPoints[l]; 7121 PetscInt rp = remotePoints[l].index, n; 7122 PetscMPIInt rrank = remotePoints[l].rank; 7123 7124 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7125 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7126 switch (refiner) { 7127 case 1: 7128 /* Simplicial 2D */ 7129 if ((p >= vStart) && (p < vEnd)) { 7130 /* Old vertices stay the same */ 7131 localPointsNew[m] = vStartNew + (p - vStart); 7132 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7133 remotePointsNew[m].rank = rrank; 7134 ++m; 7135 } else if ((p >= fStart) && (p < fEnd)) { 7136 /* Old faces add new faces and vertex */ 7137 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7138 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7139 remotePointsNew[m].rank = rrank; 7140 ++m; 7141 for (r = 0; r < 2; ++r, ++m) { 7142 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7143 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7144 remotePointsNew[m].rank = rrank; 7145 } 7146 } else if ((p >= cStart) && (p < cEnd)) { 7147 /* Old cells add new cells and interior faces */ 7148 for (r = 0; r < 4; ++r, ++m) { 7149 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7150 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7151 remotePointsNew[m].rank = rrank; 7152 } 7153 for (r = 0; r < 3; ++r, ++m) { 7154 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7155 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7156 remotePointsNew[m].rank = rrank; 7157 } 7158 } 7159 break; 7160 case 2: 7161 /* Hex 2D */ 7162 if ((p >= vStart) && (p < vEnd)) { 7163 /* Old vertices stay the same */ 7164 localPointsNew[m] = vStartNew + (p - vStart); 7165 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7166 remotePointsNew[m].rank = rrank; 7167 ++m; 7168 } else if ((p >= fStart) && (p < fEnd)) { 7169 /* Old faces add new faces and vertex */ 7170 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7171 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7172 remotePointsNew[m].rank = rrank; 7173 ++m; 7174 for (r = 0; r < 2; ++r, ++m) { 7175 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7176 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7177 remotePointsNew[m].rank = rrank; 7178 } 7179 } else if ((p >= cStart) && (p < cEnd)) { 7180 /* Old cells add new cells and interior faces */ 7181 for (r = 0; r < 4; ++r, ++m) { 7182 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7183 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7184 remotePointsNew[m].rank = rrank; 7185 } 7186 for (r = 0; r < 4; ++r, ++m) { 7187 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7188 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7189 remotePointsNew[m].rank = rrank; 7190 } 7191 } 7192 break; 7193 case 3: 7194 /* Hybrid simplicial 2D */ 7195 if ((p >= vStart) && (p < vEnd)) { 7196 /* Old vertices stay the same */ 7197 localPointsNew[m] = vStartNew + (p - vStart); 7198 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7199 remotePointsNew[m].rank = rrank; 7200 ++m; 7201 } else if ((p >= fStart) && (p < fMax)) { 7202 /* Old interior faces add new faces and vertex */ 7203 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7204 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7205 remotePointsNew[m].rank = rrank; 7206 ++m; 7207 for (r = 0; r < 2; ++r, ++m) { 7208 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7209 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7210 remotePointsNew[m].rank = rrank; 7211 } 7212 } else if ((p >= fMax) && (p < fEnd)) { 7213 /* Old hybrid faces stay the same */ 7214 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7215 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7216 remotePointsNew[m].rank = rrank; 7217 ++m; 7218 } else if ((p >= cStart) && (p < cMax)) { 7219 /* Old interior cells add new cells and interior faces */ 7220 for (r = 0; r < 4; ++r, ++m) { 7221 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7222 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7223 remotePointsNew[m].rank = rrank; 7224 } 7225 for (r = 0; r < 3; ++r, ++m) { 7226 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7227 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7228 remotePointsNew[m].rank = rrank; 7229 } 7230 } else if ((p >= cStart) && (p < cMax)) { 7231 /* Old hybrid cells add new cells and hybrid face */ 7232 for (r = 0; r < 2; ++r, ++m) { 7233 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7234 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7235 remotePointsNew[m].rank = rrank; 7236 } 7237 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7238 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]); 7239 remotePointsNew[m].rank = rrank; 7240 ++m; 7241 } 7242 break; 7243 default: 7244 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7245 } 7246 } 7247 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7248 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7249 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7250 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7251 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7252 PetscFunctionReturn(0); 7253 } 7254 7255 #undef __FUNCT__ 7256 #define __FUNCT__ "CellRefinerCreateLabels" 7257 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7258 { 7259 PetscInt numLabels, l; 7260 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7261 PetscErrorCode ierr; 7262 7263 PetscFunctionBegin; 7264 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7265 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7266 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7267 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7268 7269 cStartNew = 0; 7270 vStartNew = depthSize[2]; 7271 fStartNew = depthSize[2] + depthSize[0]; 7272 7273 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7274 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7275 switch (refiner) { 7276 case 3: 7277 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7278 cMax = PetscMin(cEnd, cMax); 7279 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7280 fMax = PetscMin(fEnd, fMax); 7281 } 7282 for (l = 0; l < numLabels; ++l) { 7283 DMLabel label, labelNew; 7284 const char *lname; 7285 PetscBool isDepth; 7286 IS valueIS; 7287 const PetscInt *values; 7288 PetscInt numValues, val; 7289 7290 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7291 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7292 if (isDepth) continue; 7293 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7294 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7295 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7296 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7297 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7298 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7299 for (val = 0; val < numValues; ++val) { 7300 IS pointIS; 7301 const PetscInt *points; 7302 PetscInt numPoints, n; 7303 7304 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7305 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7306 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7307 for (n = 0; n < numPoints; ++n) { 7308 const PetscInt p = points[n]; 7309 switch (refiner) { 7310 case 1: 7311 /* Simplicial 2D */ 7312 if ((p >= vStart) && (p < vEnd)) { 7313 /* Old vertices stay the same */ 7314 newp = vStartNew + (p - vStart); 7315 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7316 } else if ((p >= fStart) && (p < fEnd)) { 7317 /* Old faces add new faces and vertex */ 7318 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7319 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7320 for (r = 0; r < 2; ++r) { 7321 newp = fStartNew + (p - fStart)*2 + r; 7322 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7323 } 7324 } else if ((p >= cStart) && (p < cEnd)) { 7325 /* Old cells add new cells and interior faces */ 7326 for (r = 0; r < 4; ++r) { 7327 newp = cStartNew + (p - cStart)*4 + r; 7328 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7329 } 7330 for (r = 0; r < 3; ++r) { 7331 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7332 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7333 } 7334 } 7335 break; 7336 case 2: 7337 /* Hex 2D */ 7338 if ((p >= vStart) && (p < vEnd)) { 7339 /* Old vertices stay the same */ 7340 newp = vStartNew + (p - vStart); 7341 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7342 } else if ((p >= fStart) && (p < fEnd)) { 7343 /* Old faces add new faces and vertex */ 7344 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7345 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7346 for (r = 0; r < 2; ++r) { 7347 newp = fStartNew + (p - fStart)*2 + r; 7348 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7349 } 7350 } else if ((p >= cStart) && (p < cEnd)) { 7351 /* Old cells add new cells and interior faces and vertex */ 7352 for (r = 0; r < 4; ++r) { 7353 newp = cStartNew + (p - cStart)*4 + r; 7354 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7355 } 7356 for (r = 0; r < 4; ++r) { 7357 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7358 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7359 } 7360 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7361 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7362 } 7363 break; 7364 case 3: 7365 /* Hybrid simplicial 2D */ 7366 if ((p >= vStart) && (p < vEnd)) { 7367 /* Old vertices stay the same */ 7368 newp = vStartNew + (p - vStart); 7369 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7370 } else if ((p >= fStart) && (p < fMax)) { 7371 /* Old interior faces add new faces and vertex */ 7372 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7373 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7374 for (r = 0; r < 2; ++r) { 7375 newp = fStartNew + (p - fStart)*2 + r; 7376 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7377 } 7378 } else if ((p >= fMax) && (p < fEnd)) { 7379 /* Old hybrid faces stay the same */ 7380 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7381 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7382 } else if ((p >= cStart) && (p < cMax)) { 7383 /* Old interior cells add new cells and interior faces */ 7384 for (r = 0; r < 4; ++r) { 7385 newp = cStartNew + (p - cStart)*4 + r; 7386 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7387 } 7388 for (r = 0; r < 3; ++r) { 7389 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7390 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7391 } 7392 } else if ((p >= cMax) && (p < cEnd)) { 7393 /* Old hybrid cells add new cells and hybrid face */ 7394 for (r = 0; r < 2; ++r) { 7395 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7396 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7397 } 7398 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7399 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7400 } 7401 break; 7402 default: 7403 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7404 } 7405 } 7406 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7407 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7408 } 7409 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7410 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7411 if (0) { 7412 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7413 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7414 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7415 } 7416 } 7417 PetscFunctionReturn(0); 7418 } 7419 7420 #undef __FUNCT__ 7421 #define __FUNCT__ "DMPlexRefine_Uniform" 7422 /* This will only work for interpolated meshes */ 7423 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7424 { 7425 DM rdm; 7426 PetscInt *depthSize; 7427 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7428 PetscErrorCode ierr; 7429 7430 PetscFunctionBegin; 7431 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7432 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7433 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7434 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7435 /* Calculate number of new points of each depth */ 7436 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7437 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7438 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7439 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7440 /* Step 1: Set chart */ 7441 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7442 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7443 /* Step 2: Set cone/support sizes */ 7444 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7445 /* Step 3: Setup refined DM */ 7446 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7447 /* Step 4: Set cones and supports */ 7448 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7449 /* Step 5: Stratify */ 7450 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7451 /* Step 6: Set coordinates for vertices */ 7452 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7453 /* Step 7: Create pointSF */ 7454 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7455 /* Step 8: Create labels */ 7456 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7457 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7458 7459 *dmRefined = rdm; 7460 PetscFunctionReturn(0); 7461 } 7462 7463 #undef __FUNCT__ 7464 #define __FUNCT__ "DMPlexSetRefinementUniform" 7465 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7466 { 7467 DM_Plex *mesh = (DM_Plex*) dm->data; 7468 7469 PetscFunctionBegin; 7470 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7471 mesh->refinementUniform = refinementUniform; 7472 PetscFunctionReturn(0); 7473 } 7474 7475 #undef __FUNCT__ 7476 #define __FUNCT__ "DMPlexGetRefinementUniform" 7477 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7478 { 7479 DM_Plex *mesh = (DM_Plex*) dm->data; 7480 7481 PetscFunctionBegin; 7482 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7483 PetscValidPointer(refinementUniform, 2); 7484 *refinementUniform = mesh->refinementUniform; 7485 PetscFunctionReturn(0); 7486 } 7487 7488 #undef __FUNCT__ 7489 #define __FUNCT__ "DMPlexSetRefinementLimit" 7490 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7491 { 7492 DM_Plex *mesh = (DM_Plex*) dm->data; 7493 7494 PetscFunctionBegin; 7495 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7496 mesh->refinementLimit = refinementLimit; 7497 PetscFunctionReturn(0); 7498 } 7499 7500 #undef __FUNCT__ 7501 #define __FUNCT__ "DMPlexGetRefinementLimit" 7502 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7503 { 7504 DM_Plex *mesh = (DM_Plex*) dm->data; 7505 7506 PetscFunctionBegin; 7507 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7508 PetscValidPointer(refinementLimit, 2); 7509 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7510 *refinementLimit = mesh->refinementLimit; 7511 PetscFunctionReturn(0); 7512 } 7513 7514 #undef __FUNCT__ 7515 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7516 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7517 { 7518 PetscInt dim, cStart, coneSize, cMax; 7519 PetscErrorCode ierr; 7520 7521 PetscFunctionBegin; 7522 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7523 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7524 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7525 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7526 switch (dim) { 7527 case 2: 7528 switch (coneSize) { 7529 case 3: 7530 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7531 else *cellRefiner = 1; /* Triangular */ 7532 break; 7533 case 4: 7534 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7535 else *cellRefiner = 2; /* Quadrilateral */ 7536 break; 7537 default: 7538 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7539 } 7540 break; 7541 default: 7542 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7543 } 7544 PetscFunctionReturn(0); 7545 } 7546 7547 #undef __FUNCT__ 7548 #define __FUNCT__ "DMRefine_Plex" 7549 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7550 { 7551 PetscReal refinementLimit; 7552 PetscInt dim, cStart, cEnd; 7553 char genname[1024], *name = PETSC_NULL; 7554 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7555 PetscErrorCode ierr; 7556 7557 PetscFunctionBegin; 7558 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7559 if (isUniform) { 7560 CellRefiner cellRefiner; 7561 7562 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7563 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7564 PetscFunctionReturn(0); 7565 } 7566 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7567 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7568 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7569 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7570 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7571 if (flg) name = genname; 7572 if (name) { 7573 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7574 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7575 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7576 } 7577 switch (dim) { 7578 case 2: 7579 if (!name || isTriangle) { 7580 #if defined(PETSC_HAVE_TRIANGLE) 7581 double *maxVolumes; 7582 PetscInt c; 7583 7584 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7585 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7586 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7587 #else 7588 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7589 #endif 7590 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7591 break; 7592 case 3: 7593 if (!name || isCTetgen) { 7594 #if defined(PETSC_HAVE_CTETGEN) 7595 PetscReal *maxVolumes; 7596 PetscInt c; 7597 7598 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7599 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7600 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7601 #else 7602 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7603 #endif 7604 } else if (isTetgen) { 7605 #if defined(PETSC_HAVE_TETGEN) 7606 double *maxVolumes; 7607 PetscInt c; 7608 7609 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7610 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7611 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7612 #else 7613 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7614 #endif 7615 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7616 break; 7617 default: 7618 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7619 } 7620 PetscFunctionReturn(0); 7621 } 7622 7623 #undef __FUNCT__ 7624 #define __FUNCT__ "DMPlexGetDepth" 7625 /*@ 7626 DMPlexGetDepth - get the number of strata 7627 7628 Not Collective 7629 7630 Input Parameters: 7631 . dm - The DMPlex object 7632 7633 Output Parameters: 7634 . depth - number of strata 7635 7636 Level: developer 7637 7638 Notes: 7639 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7640 7641 .keywords: mesh, points 7642 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7643 @*/ 7644 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7645 { 7646 PetscInt d; 7647 PetscErrorCode ierr; 7648 7649 PetscFunctionBegin; 7650 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7651 PetscValidPointer(depth, 2); 7652 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7653 *depth = d-1; 7654 PetscFunctionReturn(0); 7655 } 7656 7657 #undef __FUNCT__ 7658 #define __FUNCT__ "DMPlexGetDepthStratum" 7659 /*@ 7660 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7661 7662 Not Collective 7663 7664 Input Parameters: 7665 + dm - The DMPlex object 7666 - stratumValue - The requested depth 7667 7668 Output Parameters: 7669 + start - The first point at this depth 7670 - end - One beyond the last point at this depth 7671 7672 Level: developer 7673 7674 .keywords: mesh, points 7675 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7676 @*/ 7677 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7678 { 7679 DM_Plex *mesh = (DM_Plex*) dm->data; 7680 DMLabel next = mesh->labels; 7681 PetscBool flg = PETSC_FALSE; 7682 PetscInt depth; 7683 PetscErrorCode ierr; 7684 7685 PetscFunctionBegin; 7686 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7687 if (stratumValue < 0) { 7688 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7689 PetscFunctionReturn(0); 7690 } else { 7691 PetscInt pStart, pEnd; 7692 7693 if (start) *start = 0; 7694 if (end) *end = 0; 7695 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7696 if (pStart == pEnd) PetscFunctionReturn(0); 7697 } 7698 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7699 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7700 /* We should have a generic GetLabel() and a Label class */ 7701 while (next) { 7702 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7703 if (flg) break; 7704 next = next->next; 7705 } 7706 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7707 depth = stratumValue; 7708 if ((depth < 0) || (depth >= next->numStrata)) { 7709 if (start) *start = 0; 7710 if (end) *end = 0; 7711 } else { 7712 if (start) *start = next->points[next->stratumOffsets[depth]]; 7713 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7714 } 7715 PetscFunctionReturn(0); 7716 } 7717 7718 #undef __FUNCT__ 7719 #define __FUNCT__ "DMPlexGetHeightStratum" 7720 /*@ 7721 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7722 7723 Not Collective 7724 7725 Input Parameters: 7726 + dm - The DMPlex object 7727 - stratumValue - The requested height 7728 7729 Output Parameters: 7730 + start - The first point at this height 7731 - end - One beyond the last point at this height 7732 7733 Level: developer 7734 7735 .keywords: mesh, points 7736 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7737 @*/ 7738 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7739 { 7740 DM_Plex *mesh = (DM_Plex*) dm->data; 7741 DMLabel next = mesh->labels; 7742 PetscBool flg = PETSC_FALSE; 7743 PetscInt depth; 7744 PetscErrorCode ierr; 7745 7746 PetscFunctionBegin; 7747 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7748 if (stratumValue < 0) { 7749 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7750 } else { 7751 PetscInt pStart, pEnd; 7752 7753 if (start) *start = 0; 7754 if (end) *end = 0; 7755 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7756 if (pStart == pEnd) PetscFunctionReturn(0); 7757 } 7758 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7759 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7760 /* We should have a generic GetLabel() and a Label class */ 7761 while (next) { 7762 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7763 if (flg) break; 7764 next = next->next; 7765 } 7766 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7767 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7768 if ((depth < 0) || (depth >= next->numStrata)) { 7769 if (start) *start = 0; 7770 if (end) *end = 0; 7771 } else { 7772 if (start) *start = next->points[next->stratumOffsets[depth]]; 7773 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7774 } 7775 PetscFunctionReturn(0); 7776 } 7777 7778 #undef __FUNCT__ 7779 #define __FUNCT__ "DMPlexCreateSectionInitial" 7780 /* Set the number of dof on each point and separate by fields */ 7781 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7782 { 7783 PetscInt *numDofTot; 7784 PetscInt pStart = 0, pEnd = 0; 7785 PetscInt p, d, f; 7786 PetscErrorCode ierr; 7787 7788 PetscFunctionBegin; 7789 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7790 for (d = 0; d <= dim; ++d) { 7791 numDofTot[d] = 0; 7792 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7793 } 7794 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7795 if (numFields > 0) { 7796 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7797 if (numComp) { 7798 for (f = 0; f < numFields; ++f) { 7799 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7800 } 7801 } 7802 } 7803 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7804 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7805 for (d = 0; d <= dim; ++d) { 7806 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7807 for (p = pStart; p < pEnd; ++p) { 7808 for (f = 0; f < numFields; ++f) { 7809 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7810 } 7811 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7812 } 7813 } 7814 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7815 PetscFunctionReturn(0); 7816 } 7817 7818 #undef __FUNCT__ 7819 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7820 /* Set the number of dof on each point and separate by fields 7821 If constDof is PETSC_DETERMINE, constrain every dof on the point 7822 */ 7823 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7824 { 7825 PetscInt numFields; 7826 PetscInt bc; 7827 PetscErrorCode ierr; 7828 7829 PetscFunctionBegin; 7830 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7831 for (bc = 0; bc < numBC; ++bc) { 7832 PetscInt field = 0; 7833 const PetscInt *idx; 7834 PetscInt n, i; 7835 7836 if (numFields) field = bcField[bc]; 7837 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7838 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7839 for (i = 0; i < n; ++i) { 7840 const PetscInt p = idx[i]; 7841 PetscInt numConst = constDof; 7842 7843 /* Constrain every dof on the point */ 7844 if (numConst < 0) { 7845 if (numFields) { 7846 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7847 } else { 7848 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7849 } 7850 } 7851 if (numFields) { 7852 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7853 } 7854 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7855 } 7856 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7857 } 7858 PetscFunctionReturn(0); 7859 } 7860 7861 #undef __FUNCT__ 7862 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7863 /* Set the constrained indices on each point and separate by fields */ 7864 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7865 { 7866 PetscInt *maxConstraints; 7867 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7868 PetscErrorCode ierr; 7869 7870 PetscFunctionBegin; 7871 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7872 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7873 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7874 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7875 for (p = pStart; p < pEnd; ++p) { 7876 PetscInt cdof; 7877 7878 if (numFields) { 7879 for (f = 0; f < numFields; ++f) { 7880 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7881 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7882 } 7883 } else { 7884 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7885 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7886 } 7887 } 7888 for (f = 0; f < numFields; ++f) { 7889 maxConstraints[numFields] += maxConstraints[f]; 7890 } 7891 if (maxConstraints[numFields]) { 7892 PetscInt *indices; 7893 7894 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7895 for (p = pStart; p < pEnd; ++p) { 7896 PetscInt cdof, d; 7897 7898 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7899 if (cdof) { 7900 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7901 if (numFields) { 7902 PetscInt numConst = 0, foff = 0; 7903 7904 for (f = 0; f < numFields; ++f) { 7905 PetscInt cfdof, fdof; 7906 7907 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7908 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7909 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7910 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7911 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7912 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7913 numConst += cfdof; 7914 foff += fdof; 7915 } 7916 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7917 } else { 7918 for (d = 0; d < cdof; ++d) indices[d] = d; 7919 } 7920 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7921 } 7922 } 7923 ierr = PetscFree(indices);CHKERRQ(ierr); 7924 } 7925 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7926 PetscFunctionReturn(0); 7927 } 7928 7929 #undef __FUNCT__ 7930 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7931 /* Set the constrained field indices on each point */ 7932 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7933 { 7934 const PetscInt *points, *indices; 7935 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7936 PetscErrorCode ierr; 7937 7938 PetscFunctionBegin; 7939 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7940 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7941 7942 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7943 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7944 if (!constraintIndices) { 7945 PetscInt *idx, i; 7946 7947 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7948 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7949 for (i = 0; i < maxDof; ++i) idx[i] = i; 7950 for (p = 0; p < numPoints; ++p) { 7951 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7952 } 7953 ierr = PetscFree(idx);CHKERRQ(ierr); 7954 } else { 7955 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7956 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7957 for (p = 0; p < numPoints; ++p) { 7958 PetscInt fcdof; 7959 7960 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7961 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); 7962 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7963 } 7964 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7965 } 7966 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7967 PetscFunctionReturn(0); 7968 } 7969 7970 #undef __FUNCT__ 7971 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7972 /* Set the constrained indices on each point and separate by fields */ 7973 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7974 { 7975 PetscInt *indices; 7976 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7977 PetscErrorCode ierr; 7978 7979 PetscFunctionBegin; 7980 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7981 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7982 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7983 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7984 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7985 for (p = pStart; p < pEnd; ++p) { 7986 PetscInt cdof, d; 7987 7988 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7989 if (cdof) { 7990 PetscInt numConst = 0, foff = 0; 7991 7992 for (f = 0; f < numFields; ++f) { 7993 const PetscInt *fcind; 7994 PetscInt fdof, fcdof; 7995 7996 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7997 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7998 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7999 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8000 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 8001 foff += fdof; 8002 numConst += fcdof; 8003 } 8004 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8005 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8006 } 8007 } 8008 ierr = PetscFree(indices);CHKERRQ(ierr); 8009 PetscFunctionReturn(0); 8010 } 8011 8012 #undef __FUNCT__ 8013 #define __FUNCT__ "DMPlexCreateSection" 8014 /*@C 8015 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8016 8017 Not Collective 8018 8019 Input Parameters: 8020 + dm - The DMPlex object 8021 . dim - The spatial dimension of the problem 8022 . numFields - The number of fields in the problem 8023 . numComp - An array of size numFields that holds the number of components for each field 8024 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8025 . numBC - The number of boundary conditions 8026 . bcField - An array of size numBC giving the field number for each boundry condition 8027 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8028 8029 Output Parameter: 8030 . section - The PetscSection object 8031 8032 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 8033 nubmer of dof for field 0 on each edge. 8034 8035 Level: developer 8036 8037 .keywords: mesh, elements 8038 .seealso: DMPlexCreate(), PetscSectionCreate() 8039 @*/ 8040 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8041 { 8042 PetscErrorCode ierr; 8043 8044 PetscFunctionBegin; 8045 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8046 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8047 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8048 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8049 { 8050 PetscBool view = PETSC_FALSE; 8051 8052 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8053 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8054 } 8055 PetscFunctionReturn(0); 8056 } 8057 8058 #undef __FUNCT__ 8059 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8060 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8061 { 8062 PetscSection section; 8063 PetscErrorCode ierr; 8064 8065 PetscFunctionBegin; 8066 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8067 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8068 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8069 PetscFunctionReturn(0); 8070 } 8071 8072 #undef __FUNCT__ 8073 #define __FUNCT__ "DMPlexGetCoordinateSection" 8074 /*@ 8075 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8076 8077 Not Collective 8078 8079 Input Parameter: 8080 . dm - The DMPlex object 8081 8082 Output Parameter: 8083 . section - The PetscSection object 8084 8085 Level: intermediate 8086 8087 .keywords: mesh, coordinates 8088 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8089 @*/ 8090 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8091 { 8092 DM cdm; 8093 PetscErrorCode ierr; 8094 8095 PetscFunctionBegin; 8096 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8097 PetscValidPointer(section, 2); 8098 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8099 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8100 PetscFunctionReturn(0); 8101 } 8102 8103 #undef __FUNCT__ 8104 #define __FUNCT__ "DMPlexSetCoordinateSection" 8105 /*@ 8106 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8107 8108 Not Collective 8109 8110 Input Parameters: 8111 + dm - The DMPlex object 8112 - section - The PetscSection object 8113 8114 Level: intermediate 8115 8116 .keywords: mesh, coordinates 8117 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8118 @*/ 8119 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8120 { 8121 DM cdm; 8122 PetscErrorCode ierr; 8123 8124 PetscFunctionBegin; 8125 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8126 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8127 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8128 PetscFunctionReturn(0); 8129 } 8130 8131 #undef __FUNCT__ 8132 #define __FUNCT__ "DMPlexGetConeSection" 8133 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8134 { 8135 DM_Plex *mesh = (DM_Plex*) dm->data; 8136 8137 PetscFunctionBegin; 8138 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8139 if (section) *section = mesh->coneSection; 8140 PetscFunctionReturn(0); 8141 } 8142 8143 #undef __FUNCT__ 8144 #define __FUNCT__ "DMPlexGetCones" 8145 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8146 { 8147 DM_Plex *mesh = (DM_Plex*) dm->data; 8148 8149 PetscFunctionBegin; 8150 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8151 if (cones) *cones = mesh->cones; 8152 PetscFunctionReturn(0); 8153 } 8154 8155 #undef __FUNCT__ 8156 #define __FUNCT__ "DMPlexGetConeOrientations" 8157 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8158 { 8159 DM_Plex *mesh = (DM_Plex*) dm->data; 8160 8161 PetscFunctionBegin; 8162 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8163 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8164 PetscFunctionReturn(0); 8165 } 8166 8167 #undef __FUNCT__ 8168 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8169 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8170 { 8171 const PetscInt embedDim = 2; 8172 PetscReal x = PetscRealPart(point[0]); 8173 PetscReal y = PetscRealPart(point[1]); 8174 PetscReal v0[2], J[4], invJ[4], detJ; 8175 PetscReal xi, eta; 8176 PetscErrorCode ierr; 8177 8178 PetscFunctionBegin; 8179 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8180 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8181 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8182 8183 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8184 else *cell = -1; 8185 PetscFunctionReturn(0); 8186 } 8187 8188 #undef __FUNCT__ 8189 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8190 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8191 { 8192 PetscSection coordSection; 8193 Vec coordsLocal; 8194 const PetscScalar *coords; 8195 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8196 PetscReal x = PetscRealPart(point[0]); 8197 PetscReal y = PetscRealPart(point[1]); 8198 PetscInt crossings = 0, f; 8199 PetscErrorCode ierr; 8200 8201 PetscFunctionBegin; 8202 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8203 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8204 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8205 for (f = 0; f < 4; ++f) { 8206 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8207 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8208 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8209 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8210 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8211 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8212 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8213 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8214 if ((cond1 || cond2) && above) ++crossings; 8215 } 8216 if (crossings % 2) *cell = c; 8217 else *cell = -1; 8218 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8219 PetscFunctionReturn(0); 8220 } 8221 8222 #undef __FUNCT__ 8223 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8224 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8225 { 8226 const PetscInt embedDim = 3; 8227 PetscReal v0[3], J[9], invJ[9], detJ; 8228 PetscReal x = PetscRealPart(point[0]); 8229 PetscReal y = PetscRealPart(point[1]); 8230 PetscReal z = PetscRealPart(point[2]); 8231 PetscReal xi, eta, zeta; 8232 PetscErrorCode ierr; 8233 8234 PetscFunctionBegin; 8235 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8236 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8237 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8238 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8239 8240 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8241 else *cell = -1; 8242 PetscFunctionReturn(0); 8243 } 8244 8245 #undef __FUNCT__ 8246 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8247 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8248 { 8249 PetscSection coordSection; 8250 Vec coordsLocal; 8251 const PetscScalar *coords; 8252 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8253 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8254 PetscBool found = PETSC_TRUE; 8255 PetscInt f; 8256 PetscErrorCode ierr; 8257 8258 PetscFunctionBegin; 8259 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8260 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8261 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8262 for (f = 0; f < 6; ++f) { 8263 /* Check the point is under plane */ 8264 /* Get face normal */ 8265 PetscReal v_i[3]; 8266 PetscReal v_j[3]; 8267 PetscReal normal[3]; 8268 PetscReal pp[3]; 8269 PetscReal dot; 8270 8271 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8272 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8273 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8274 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8275 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8276 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8277 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8278 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8279 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8280 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8281 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8282 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8283 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8284 8285 /* Check that projected point is in face (2D location problem) */ 8286 if (dot < 0.0) { 8287 found = PETSC_FALSE; 8288 break; 8289 } 8290 } 8291 if (found) *cell = c; 8292 else *cell = -1; 8293 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8294 PetscFunctionReturn(0); 8295 } 8296 8297 #undef __FUNCT__ 8298 #define __FUNCT__ "DMLocatePoints_Plex" 8299 /* 8300 Need to implement using the guess 8301 */ 8302 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8303 { 8304 PetscInt cell = -1 /*, guess = -1*/; 8305 PetscInt bs, numPoints, p; 8306 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8307 PetscInt *cells; 8308 PetscScalar *a; 8309 PetscErrorCode ierr; 8310 8311 PetscFunctionBegin; 8312 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8313 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8314 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8315 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8316 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8317 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8318 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8319 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); 8320 numPoints /= bs; 8321 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8322 for (p = 0; p < numPoints; ++p) { 8323 const PetscScalar *point = &a[p*bs]; 8324 8325 switch (dim) { 8326 case 2: 8327 for (c = cStart; c < cEnd; ++c) { 8328 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8329 switch (coneSize) { 8330 case 3: 8331 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8332 break; 8333 case 4: 8334 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8335 break; 8336 default: 8337 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8338 } 8339 if (cell >= 0) break; 8340 } 8341 break; 8342 case 3: 8343 for (c = cStart; c < cEnd; ++c) { 8344 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8345 switch (coneSize) { 8346 case 4: 8347 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8348 break; 8349 case 8: 8350 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8351 break; 8352 default: 8353 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8354 } 8355 if (cell >= 0) break; 8356 } 8357 break; 8358 default: 8359 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8360 } 8361 cells[p] = cell; 8362 } 8363 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8364 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8365 PetscFunctionReturn(0); 8366 } 8367 8368 /******************************** FEM Support **********************************/ 8369 8370 #undef __FUNCT__ 8371 #define __FUNCT__ "DMPlexVecGetClosure" 8372 /*@C 8373 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8374 8375 Not collective 8376 8377 Input Parameters: 8378 + dm - The DM 8379 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8380 . v - The local vector 8381 - point - The sieve point in the DM 8382 8383 Output Parameters: 8384 + csize - The number of values in the closure, or PETSC_NULL 8385 - values - The array of values, which is a borrowed array and should not be freed 8386 8387 Level: intermediate 8388 8389 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8390 @*/ 8391 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8392 { 8393 PetscScalar *array, *vArray; 8394 PetscInt *points = PETSC_NULL; 8395 PetscInt offsets[32]; 8396 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8397 PetscErrorCode ierr; 8398 8399 PetscFunctionBegin; 8400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8401 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8402 if (!section) { 8403 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8404 } 8405 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8406 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8407 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8408 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8409 /* Compress out points not in the section */ 8410 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8411 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8412 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8413 points[q*2] = points[p]; 8414 points[q*2+1] = points[p+1]; 8415 ++q; 8416 } 8417 } 8418 numPoints = q; 8419 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8420 PetscInt dof, fdof; 8421 8422 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8423 for (f = 0; f < numFields; ++f) { 8424 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8425 offsets[f+1] += fdof; 8426 } 8427 size += dof; 8428 } 8429 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8430 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8431 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8432 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8433 for (p = 0; p < numPoints*2; p += 2) { 8434 PetscInt o = points[p+1]; 8435 PetscInt dof, off, d; 8436 PetscScalar *varr; 8437 8438 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8439 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8440 varr = &vArray[off]; 8441 if (numFields) { 8442 PetscInt fdof, foff, fcomp, f, c; 8443 8444 for (f = 0, foff = 0; f < numFields; ++f) { 8445 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8446 if (o >= 0) { 8447 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8448 array[offsets[f]] = varr[foff+d]; 8449 } 8450 } else { 8451 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8452 for (d = fdof/fcomp-1; d >= 0; --d) { 8453 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8454 array[offsets[f]] = varr[foff+d*fcomp+c]; 8455 } 8456 } 8457 } 8458 foff += fdof; 8459 } 8460 } else { 8461 if (o >= 0) { 8462 for (d = 0; d < dof; ++d, ++offsets[0]) { 8463 array[offsets[0]] = varr[d]; 8464 } 8465 } else { 8466 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8467 array[offsets[0]] = varr[d]; 8468 } 8469 } 8470 } 8471 } 8472 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8473 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8474 if (csize) *csize = size; 8475 *values = array; 8476 PetscFunctionReturn(0); 8477 } 8478 8479 #undef __FUNCT__ 8480 #define __FUNCT__ "DMPlexVecRestoreClosure" 8481 /*@C 8482 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8483 8484 Not collective 8485 8486 Input Parameters: 8487 + dm - The DM 8488 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8489 . v - The local vector 8490 . point - The sieve point in the DM 8491 . csize - The number of values in the closure, or PETSC_NULL 8492 - values - The array of values, which is a borrowed array and should not be freed 8493 8494 Level: intermediate 8495 8496 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8497 @*/ 8498 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8499 { 8500 PetscInt size = 0; 8501 PetscErrorCode ierr; 8502 8503 PetscFunctionBegin; 8504 /* Should work without recalculating size */ 8505 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8506 PetscFunctionReturn(0); 8507 } 8508 8509 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8510 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8511 8512 #undef __FUNCT__ 8513 #define __FUNCT__ "updatePoint_private" 8514 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8515 { 8516 PetscInt cdof; /* The number of constraints on this point */ 8517 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8518 PetscScalar *a; 8519 PetscInt off, cind = 0, k; 8520 PetscErrorCode ierr; 8521 8522 PetscFunctionBegin; 8523 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8524 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8525 a = &array[off]; 8526 if (!cdof || setBC) { 8527 if (orientation >= 0) { 8528 for (k = 0; k < dof; ++k) { 8529 fuse(&a[k], values[k]); 8530 } 8531 } else { 8532 for (k = 0; k < dof; ++k) { 8533 fuse(&a[k], values[dof-k-1]); 8534 } 8535 } 8536 } else { 8537 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8538 if (orientation >= 0) { 8539 for (k = 0; k < dof; ++k) { 8540 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8541 fuse(&a[k], values[k]); 8542 } 8543 } else { 8544 for (k = 0; k < dof; ++k) { 8545 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8546 fuse(&a[k], values[dof-k-1]); 8547 } 8548 } 8549 } 8550 PetscFunctionReturn(0); 8551 } 8552 8553 #undef __FUNCT__ 8554 #define __FUNCT__ "updatePointFields_private" 8555 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8556 { 8557 PetscScalar *a; 8558 PetscInt numFields, off, foff, f; 8559 PetscErrorCode ierr; 8560 8561 PetscFunctionBegin; 8562 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8563 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8564 a = &array[off]; 8565 for (f = 0, foff = 0; f < numFields; ++f) { 8566 PetscInt fdof, fcomp, fcdof; 8567 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8568 PetscInt cind = 0, k, c; 8569 8570 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8571 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8572 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8573 if (!fcdof || setBC) { 8574 if (orientation >= 0) { 8575 for (k = 0; k < fdof; ++k) { 8576 fuse(&a[foff+k], values[foffs[f]+k]); 8577 } 8578 } else { 8579 for (k = fdof/fcomp-1; k >= 0; --k) { 8580 for (c = 0; c < fcomp; ++c) { 8581 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8582 } 8583 } 8584 } 8585 } else { 8586 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8587 if (orientation >= 0) { 8588 for (k = 0; k < fdof; ++k) { 8589 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8590 fuse(&a[foff+k], values[foffs[f]+k]); 8591 } 8592 } else { 8593 for (k = fdof/fcomp-1; k >= 0; --k) { 8594 for (c = 0; c < fcomp; ++c) { 8595 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8596 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8597 } 8598 } 8599 } 8600 } 8601 foff += fdof; 8602 foffs[f] += fdof; 8603 } 8604 PetscFunctionReturn(0); 8605 } 8606 8607 #undef __FUNCT__ 8608 #define __FUNCT__ "DMPlexVecSetClosure" 8609 /*@C 8610 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8611 8612 Not collective 8613 8614 Input Parameters: 8615 + dm - The DM 8616 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8617 . v - The local vector 8618 . point - The sieve point in the DM 8619 . values - The array of values, which is a borrowed array and should not be freed 8620 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8621 8622 Level: intermediate 8623 8624 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8625 @*/ 8626 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8627 { 8628 PetscScalar *array; 8629 PetscInt *points = PETSC_NULL; 8630 PetscInt offsets[32]; 8631 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8632 PetscErrorCode ierr; 8633 8634 PetscFunctionBegin; 8635 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8636 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8637 if (!section) { 8638 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8639 } 8640 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8641 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8642 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8643 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8644 /* Compress out points not in the section */ 8645 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8646 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8647 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8648 points[q*2] = points[p]; 8649 points[q*2+1] = points[p+1]; 8650 ++q; 8651 } 8652 } 8653 numPoints = q; 8654 for (p = 0; p < numPoints*2; p += 2) { 8655 PetscInt fdof; 8656 8657 for (f = 0; f < numFields; ++f) { 8658 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8659 offsets[f+1] += fdof; 8660 } 8661 } 8662 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8663 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8664 if (numFields) { 8665 switch (mode) { 8666 case INSERT_VALUES: 8667 for (p = 0; p < numPoints*2; p += 2) { 8668 PetscInt o = points[p+1]; 8669 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8670 } break; 8671 case INSERT_ALL_VALUES: 8672 for (p = 0; p < numPoints*2; p += 2) { 8673 PetscInt o = points[p+1]; 8674 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8675 } break; 8676 case ADD_VALUES: 8677 for (p = 0; p < numPoints*2; p += 2) { 8678 PetscInt o = points[p+1]; 8679 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8680 } break; 8681 case ADD_ALL_VALUES: 8682 for (p = 0; p < numPoints*2; p += 2) { 8683 PetscInt o = points[p+1]; 8684 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8685 } break; 8686 default: 8687 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8688 } 8689 } else { 8690 switch (mode) { 8691 case INSERT_VALUES: 8692 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8693 PetscInt o = points[p+1]; 8694 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8695 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8696 } break; 8697 case INSERT_ALL_VALUES: 8698 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8699 PetscInt o = points[p+1]; 8700 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8701 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8702 } break; 8703 case ADD_VALUES: 8704 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8705 PetscInt o = points[p+1]; 8706 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8707 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8708 } break; 8709 case ADD_ALL_VALUES: 8710 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8711 PetscInt o = points[p+1]; 8712 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8713 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8714 } break; 8715 default: 8716 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8717 } 8718 } 8719 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8720 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8721 PetscFunctionReturn(0); 8722 } 8723 8724 #undef __FUNCT__ 8725 #define __FUNCT__ "DMPlexPrintMatSetValues" 8726 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8727 { 8728 PetscMPIInt rank; 8729 PetscInt i, j; 8730 PetscErrorCode ierr; 8731 8732 PetscFunctionBegin; 8733 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8734 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8735 for (i = 0; i < numIndices; i++) { 8736 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8737 } 8738 for (i = 0; i < numIndices; i++) { 8739 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8740 for (j = 0; j < numIndices; j++) { 8741 #if defined(PETSC_USE_COMPLEX) 8742 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8743 #else 8744 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8745 #endif 8746 } 8747 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8748 } 8749 PetscFunctionReturn(0); 8750 } 8751 8752 #undef __FUNCT__ 8753 #define __FUNCT__ "indicesPoint_private" 8754 /* . off - The global offset of this point */ 8755 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8756 { 8757 PetscInt cdof; /* The number of constraints on this point */ 8758 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8759 PetscInt cind = 0, k; 8760 PetscErrorCode ierr; 8761 8762 PetscFunctionBegin; 8763 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8764 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8765 if (!cdof || setBC) { 8766 if (orientation >= 0) { 8767 for (k = 0; k < dof; ++k) indices[k] = off+k; 8768 } else { 8769 for (k = 0; k < dof; ++k) indices[dof-k-1] = off+k; 8770 } 8771 } else { 8772 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8773 if (orientation >= 0) { 8774 for (k = 0; k < dof; ++k) { 8775 if ((cind < cdof) && (k == cdofs[cind])) { 8776 /* Insert check for returning constrained indices */ 8777 indices[k] = -(off+k+1); 8778 ++cind; 8779 } else { 8780 indices[k] = off+k-cind; 8781 } 8782 } 8783 } else { 8784 for (k = 0; k < dof; ++k) { 8785 if ((cind < cdof) && (k == cdofs[cind])) { 8786 /* Insert check for returning constrained indices */ 8787 indices[dof-k-1] = -(off+k+1); 8788 ++cind; 8789 } else { 8790 indices[dof-k-1] = off+k-cind; 8791 } 8792 } 8793 } 8794 } 8795 PetscFunctionReturn(0); 8796 } 8797 8798 #undef __FUNCT__ 8799 #define __FUNCT__ "indicesPointFields_private" 8800 /* . off - The global offset of this point */ 8801 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8802 { 8803 PetscInt numFields, foff, f; 8804 PetscErrorCode ierr; 8805 8806 PetscFunctionBegin; 8807 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8808 for (f = 0, foff = 0; f < numFields; ++f) { 8809 PetscInt fdof, fcomp, cfdof; 8810 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8811 PetscInt cind = 0, k, c; 8812 8813 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8814 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8815 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8816 if (!cfdof || setBC) { 8817 if (orientation >= 0) { 8818 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8819 } else { 8820 for (k = fdof/fcomp-1; k >= 0; --k) { 8821 for (c = 0; c < fcomp; ++c) { 8822 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8823 } 8824 } 8825 } 8826 } else { 8827 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8828 if (orientation >= 0) { 8829 for (k = 0; k < fdof; ++k) { 8830 if ((cind < cfdof) && (k == fcdofs[cind])) { 8831 indices[foffs[f]+k] = -(off+foff+k+1); 8832 ++cind; 8833 } else { 8834 indices[foffs[f]+k] = off+foff+k-cind; 8835 } 8836 } 8837 } else { 8838 for (k = fdof/fcomp-1; k >= 0; --k) { 8839 for (c = 0; c < fcomp; ++c) { 8840 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8841 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8842 ++cind; 8843 } else { 8844 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8845 } 8846 } 8847 } 8848 } 8849 } 8850 foff += fdof - cfdof; 8851 foffs[f] += fdof; 8852 } 8853 PetscFunctionReturn(0); 8854 } 8855 8856 #undef __FUNCT__ 8857 #define __FUNCT__ "DMPlexMatSetClosure" 8858 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8859 { 8860 DM_Plex *mesh = (DM_Plex*) dm->data; 8861 PetscInt *points = PETSC_NULL; 8862 PetscInt *indices; 8863 PetscInt offsets[32]; 8864 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8865 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8866 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8867 PetscErrorCode ierr; 8868 8869 PetscFunctionBegin; 8870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8871 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8872 if (useDefault) { 8873 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8874 } 8875 if (useGlobalDefault) { 8876 if (useDefault) { 8877 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8878 } else { 8879 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8880 } 8881 } 8882 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8883 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8884 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8885 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8886 /* Compress out points not in the section */ 8887 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8888 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8889 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8890 points[q*2] = points[p]; 8891 points[q*2+1] = points[p+1]; 8892 ++q; 8893 } 8894 } 8895 numPoints = q; 8896 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8897 PetscInt fdof; 8898 8899 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8900 for (f = 0; f < numFields; ++f) { 8901 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8902 offsets[f+1] += fdof; 8903 } 8904 numIndices += dof; 8905 } 8906 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8907 8908 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8909 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8910 if (numFields) { 8911 for (p = 0; p < numPoints*2; p += 2) { 8912 PetscInt o = points[p+1]; 8913 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8914 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8915 } 8916 } else { 8917 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8918 PetscInt o = points[p+1]; 8919 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8920 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8921 } 8922 } 8923 if (useGlobalDefault && !useDefault) { 8924 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8925 } 8926 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8927 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8928 if (ierr) { 8929 PetscMPIInt rank; 8930 PetscErrorCode ierr2; 8931 8932 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8933 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8934 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8935 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8936 CHKERRQ(ierr); 8937 } 8938 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8939 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8940 PetscFunctionReturn(0); 8941 } 8942 8943 #undef __FUNCT__ 8944 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8945 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8946 { 8947 PetscSection coordSection; 8948 Vec coordinates; 8949 const PetscScalar *coords; 8950 const PetscInt dim = 2; 8951 PetscInt d, f; 8952 PetscErrorCode ierr; 8953 8954 PetscFunctionBegin; 8955 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8956 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8957 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8958 if (v0) { 8959 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8960 } 8961 if (J) { 8962 for (d = 0; d < dim; d++) { 8963 for (f = 0; f < dim; f++) { 8964 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8965 } 8966 } 8967 *detJ = J[0]*J[3] - J[1]*J[2]; 8968 #if 0 8969 if (detJ < 0.0) { 8970 const PetscReal xLength = mesh->periodicity[0]; 8971 8972 if (xLength != 0.0) { 8973 PetscReal v0x = coords[0*dim+0]; 8974 8975 if (v0x == 0.0) v0x = v0[0] = xLength; 8976 for (f = 0; f < dim; f++) { 8977 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8978 8979 J[0*dim+f] = 0.5*(px - v0x); 8980 } 8981 } 8982 detJ = J[0]*J[3] - J[1]*J[2]; 8983 } 8984 #endif 8985 PetscLogFlops(8.0 + 3.0); 8986 } 8987 if (invJ) { 8988 const PetscReal invDet = 1.0/(*detJ); 8989 8990 invJ[0] = invDet*J[3]; 8991 invJ[1] = -invDet*J[1]; 8992 invJ[2] = -invDet*J[2]; 8993 invJ[3] = invDet*J[0]; 8994 PetscLogFlops(5.0); 8995 } 8996 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8997 PetscFunctionReturn(0); 8998 } 8999 9000 #undef __FUNCT__ 9001 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9002 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9003 { 9004 PetscSection coordSection; 9005 Vec coordinates; 9006 const PetscScalar *coords; 9007 const PetscInt dim = 2; 9008 PetscInt d, f; 9009 PetscErrorCode ierr; 9010 9011 PetscFunctionBegin; 9012 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9013 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9014 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9015 if (v0) { 9016 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9017 } 9018 if (J) { 9019 for (d = 0; d < dim; d++) { 9020 for (f = 0; f < dim; f++) { 9021 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9022 } 9023 } 9024 *detJ = J[0]*J[3] - J[1]*J[2]; 9025 PetscLogFlops(8.0 + 3.0); 9026 } 9027 if (invJ) { 9028 const PetscReal invDet = 1.0/(*detJ); 9029 9030 invJ[0] = invDet*J[3]; 9031 invJ[1] = -invDet*J[1]; 9032 invJ[2] = -invDet*J[2]; 9033 invJ[3] = invDet*J[0]; 9034 PetscLogFlops(5.0); 9035 } 9036 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9037 PetscFunctionReturn(0); 9038 } 9039 9040 #undef __FUNCT__ 9041 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9042 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9043 { 9044 PetscSection coordSection; 9045 Vec coordinates; 9046 const PetscScalar *coords; 9047 const PetscInt dim = 3; 9048 PetscInt d, f; 9049 PetscErrorCode ierr; 9050 9051 PetscFunctionBegin; 9052 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9053 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9054 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9055 if (v0) { 9056 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9057 } 9058 if (J) { 9059 for (d = 0; d < dim; d++) { 9060 for (f = 0; f < dim; f++) { 9061 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9062 } 9063 } 9064 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9065 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9066 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9067 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9068 PetscLogFlops(18.0 + 12.0); 9069 } 9070 if (invJ) { 9071 const PetscReal invDet = 1.0/(*detJ); 9072 9073 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9074 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9075 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9076 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9077 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9078 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9079 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9080 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9081 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9082 PetscLogFlops(37.0); 9083 } 9084 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9085 PetscFunctionReturn(0); 9086 } 9087 9088 #undef __FUNCT__ 9089 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9090 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9091 { 9092 PetscSection coordSection; 9093 Vec coordinates; 9094 const PetscScalar *coords; 9095 const PetscInt dim = 3; 9096 PetscInt d; 9097 PetscErrorCode ierr; 9098 9099 PetscFunctionBegin; 9100 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9101 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9102 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9103 if (v0) { 9104 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9105 } 9106 if (J) { 9107 for (d = 0; d < dim; d++) { 9108 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9109 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9110 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9111 } 9112 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9113 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9114 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9115 PetscLogFlops(18.0 + 12.0); 9116 } 9117 if (invJ) { 9118 const PetscReal invDet = -1.0/(*detJ); 9119 9120 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9121 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9122 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9123 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9124 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9125 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9126 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9127 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9128 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9129 PetscLogFlops(37.0); 9130 } 9131 *detJ *= 8.0; 9132 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9133 PetscFunctionReturn(0); 9134 } 9135 9136 #undef __FUNCT__ 9137 #define __FUNCT__ "DMPlexComputeCellGeometry" 9138 /*@C 9139 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9140 9141 Collective on DM 9142 9143 Input Arguments: 9144 + dm - the DM 9145 - cell - the cell 9146 9147 Output Arguments: 9148 + v0 - the translation part of this affine transform 9149 . J - the Jacobian of the transform to the reference element 9150 . invJ - the inverse of the Jacobian 9151 - detJ - the Jacobian determinant 9152 9153 Level: advanced 9154 9155 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9156 @*/ 9157 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9158 { 9159 PetscInt dim, coneSize; 9160 PetscErrorCode ierr; 9161 9162 PetscFunctionBegin; 9163 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9164 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9165 switch (dim) { 9166 case 2: 9167 switch (coneSize) { 9168 case 3: 9169 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9170 break; 9171 case 4: 9172 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9173 break; 9174 default: 9175 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9176 } 9177 break; 9178 case 3: 9179 switch (coneSize) { 9180 case 4: 9181 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9182 break; 9183 case 8: 9184 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9185 break; 9186 default: 9187 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9188 } 9189 break; 9190 default: 9191 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9192 } 9193 PetscFunctionReturn(0); 9194 } 9195 9196 #undef __FUNCT__ 9197 #define __FUNCT__ "DMPlexGetFaceOrientation" 9198 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9199 { 9200 MPI_Comm comm = ((PetscObject) dm)->comm; 9201 PetscBool posOrient = PETSC_FALSE; 9202 const PetscInt debug = 0; 9203 PetscInt cellDim, faceSize, f; 9204 PetscErrorCode ierr; 9205 9206 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9207 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9208 9209 if (cellDim == numCorners-1) { 9210 /* Simplices */ 9211 faceSize = numCorners-1; 9212 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9213 } else if (cellDim == 1 && numCorners == 3) { 9214 /* Quadratic line */ 9215 faceSize = 1; 9216 posOrient = PETSC_TRUE; 9217 } else if (cellDim == 2 && numCorners == 4) { 9218 /* Quads */ 9219 faceSize = 2; 9220 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9221 posOrient = PETSC_TRUE; 9222 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9223 posOrient = PETSC_TRUE; 9224 } else { 9225 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9226 posOrient = PETSC_FALSE; 9227 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9228 } 9229 } else if (cellDim == 2 && numCorners == 6) { 9230 /* Quadratic triangle (I hate this) */ 9231 /* Edges are determined by the first 2 vertices (corners of edges) */ 9232 const PetscInt faceSizeTri = 3; 9233 PetscInt sortedIndices[3], i, iFace; 9234 PetscBool found = PETSC_FALSE; 9235 PetscInt faceVerticesTriSorted[9] = { 9236 0, 3, 4, /* bottom */ 9237 1, 4, 5, /* right */ 9238 2, 3, 5, /* left */ 9239 }; 9240 PetscInt faceVerticesTri[9] = { 9241 0, 3, 4, /* bottom */ 9242 1, 4, 5, /* right */ 9243 2, 5, 3, /* left */ 9244 }; 9245 9246 faceSize = faceSizeTri; 9247 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9248 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9249 for (iFace = 0; iFace < 3; ++iFace) { 9250 const PetscInt ii = iFace*faceSizeTri; 9251 PetscInt fVertex, cVertex; 9252 9253 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9254 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9255 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9256 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9257 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9258 faceVertices[fVertex] = origVertices[cVertex]; 9259 break; 9260 } 9261 } 9262 } 9263 found = PETSC_TRUE; 9264 break; 9265 } 9266 } 9267 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9268 if (posOriented) *posOriented = PETSC_TRUE; 9269 PetscFunctionReturn(0); 9270 } else if (cellDim == 2 && numCorners == 9) { 9271 /* Quadratic quad (I hate this) */ 9272 /* Edges are determined by the first 2 vertices (corners of edges) */ 9273 const PetscInt faceSizeQuad = 3; 9274 PetscInt sortedIndices[3], i, iFace; 9275 PetscBool found = PETSC_FALSE; 9276 PetscInt faceVerticesQuadSorted[12] = { 9277 0, 1, 4, /* bottom */ 9278 1, 2, 5, /* right */ 9279 2, 3, 6, /* top */ 9280 0, 3, 7, /* left */ 9281 }; 9282 PetscInt faceVerticesQuad[12] = { 9283 0, 1, 4, /* bottom */ 9284 1, 2, 5, /* right */ 9285 2, 3, 6, /* top */ 9286 3, 0, 7, /* left */ 9287 }; 9288 9289 faceSize = faceSizeQuad; 9290 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9291 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9292 for (iFace = 0; iFace < 4; ++iFace) { 9293 const PetscInt ii = iFace*faceSizeQuad; 9294 PetscInt fVertex, cVertex; 9295 9296 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9297 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9298 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9299 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9300 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9301 faceVertices[fVertex] = origVertices[cVertex]; 9302 break; 9303 } 9304 } 9305 } 9306 found = PETSC_TRUE; 9307 break; 9308 } 9309 } 9310 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9311 if (posOriented) *posOriented = PETSC_TRUE; 9312 PetscFunctionReturn(0); 9313 } else if (cellDim == 3 && numCorners == 8) { 9314 /* Hexes 9315 A hex is two oriented quads with the normal of the first 9316 pointing up at the second. 9317 9318 7---6 9319 /| /| 9320 4---5 | 9321 | 3-|-2 9322 |/ |/ 9323 0---1 9324 9325 Faces are determined by the first 4 vertices (corners of faces) */ 9326 const PetscInt faceSizeHex = 4; 9327 PetscInt sortedIndices[4], i, iFace; 9328 PetscBool found = PETSC_FALSE; 9329 PetscInt faceVerticesHexSorted[24] = { 9330 0, 1, 2, 3, /* bottom */ 9331 4, 5, 6, 7, /* top */ 9332 0, 1, 4, 5, /* front */ 9333 1, 2, 5, 6, /* right */ 9334 2, 3, 6, 7, /* back */ 9335 0, 3, 4, 7, /* left */ 9336 }; 9337 PetscInt faceVerticesHex[24] = { 9338 3, 2, 1, 0, /* bottom */ 9339 4, 5, 6, 7, /* top */ 9340 0, 1, 5, 4, /* front */ 9341 1, 2, 6, 5, /* right */ 9342 2, 3, 7, 6, /* back */ 9343 3, 0, 4, 7, /* left */ 9344 }; 9345 9346 faceSize = faceSizeHex; 9347 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9348 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9349 for (iFace = 0; iFace < 6; ++iFace) { 9350 const PetscInt ii = iFace*faceSizeHex; 9351 PetscInt fVertex, cVertex; 9352 9353 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9354 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9355 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9356 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9357 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9358 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9359 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9360 faceVertices[fVertex] = origVertices[cVertex]; 9361 break; 9362 } 9363 } 9364 } 9365 found = PETSC_TRUE; 9366 break; 9367 } 9368 } 9369 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9370 if (posOriented) *posOriented = PETSC_TRUE; 9371 PetscFunctionReturn(0); 9372 } else if (cellDim == 3 && numCorners == 10) { 9373 /* Quadratic tet */ 9374 /* Faces are determined by the first 3 vertices (corners of faces) */ 9375 const PetscInt faceSizeTet = 6; 9376 PetscInt sortedIndices[6], i, iFace; 9377 PetscBool found = PETSC_FALSE; 9378 PetscInt faceVerticesTetSorted[24] = { 9379 0, 1, 2, 6, 7, 8, /* bottom */ 9380 0, 3, 4, 6, 7, 9, /* front */ 9381 1, 4, 5, 7, 8, 9, /* right */ 9382 2, 3, 5, 6, 8, 9, /* left */ 9383 }; 9384 PetscInt faceVerticesTet[24] = { 9385 0, 1, 2, 6, 7, 8, /* bottom */ 9386 0, 4, 3, 6, 7, 9, /* front */ 9387 1, 5, 4, 7, 8, 9, /* right */ 9388 2, 3, 5, 8, 6, 9, /* left */ 9389 }; 9390 9391 faceSize = faceSizeTet; 9392 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9393 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9394 for (iFace=0; iFace < 4; ++iFace) { 9395 const PetscInt ii = iFace*faceSizeTet; 9396 PetscInt fVertex, cVertex; 9397 9398 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9399 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9400 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9401 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9402 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9403 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9404 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9405 faceVertices[fVertex] = origVertices[cVertex]; 9406 break; 9407 } 9408 } 9409 } 9410 found = PETSC_TRUE; 9411 break; 9412 } 9413 } 9414 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9415 if (posOriented) *posOriented = PETSC_TRUE; 9416 PetscFunctionReturn(0); 9417 } else if (cellDim == 3 && numCorners == 27) { 9418 /* Quadratic hexes (I hate this) 9419 A hex is two oriented quads with the normal of the first 9420 pointing up at the second. 9421 9422 7---6 9423 /| /| 9424 4---5 | 9425 | 3-|-2 9426 |/ |/ 9427 0---1 9428 9429 Faces are determined by the first 4 vertices (corners of faces) */ 9430 const PetscInt faceSizeQuadHex = 9; 9431 PetscInt sortedIndices[9], i, iFace; 9432 PetscBool found = PETSC_FALSE; 9433 PetscInt faceVerticesQuadHexSorted[54] = { 9434 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9435 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9436 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9437 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9438 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9439 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9440 }; 9441 PetscInt faceVerticesQuadHex[54] = { 9442 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9443 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9444 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9445 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9446 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9447 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9448 }; 9449 9450 faceSize = faceSizeQuadHex; 9451 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9452 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9453 for (iFace = 0; iFace < 6; ++iFace) { 9454 const PetscInt ii = iFace*faceSizeQuadHex; 9455 PetscInt fVertex, cVertex; 9456 9457 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9458 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9459 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9460 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9461 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9462 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9463 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9464 faceVertices[fVertex] = origVertices[cVertex]; 9465 break; 9466 } 9467 } 9468 } 9469 found = PETSC_TRUE; 9470 break; 9471 } 9472 } 9473 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9474 if (posOriented) *posOriented = PETSC_TRUE; 9475 PetscFunctionReturn(0); 9476 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9477 if (!posOrient) { 9478 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9479 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize-1 - f]; 9480 } else { 9481 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9482 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f]; 9483 } 9484 if (posOriented) *posOriented = posOrient; 9485 PetscFunctionReturn(0); 9486 } 9487 9488 #undef __FUNCT__ 9489 #define __FUNCT__ "DMPlexGetOrientedFace" 9490 /* 9491 Given a cell and a face, as a set of vertices, 9492 return the oriented face, as a set of vertices, in faceVertices 9493 The orientation is such that the face normal points out of the cell 9494 */ 9495 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9496 { 9497 const PetscInt *cone = PETSC_NULL; 9498 PetscInt coneSize, v, f, v2; 9499 PetscInt oppositeVertex = -1; 9500 PetscErrorCode ierr; 9501 9502 PetscFunctionBegin; 9503 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9504 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9505 for (v = 0, v2 = 0; v < coneSize; ++v) { 9506 PetscBool found = PETSC_FALSE; 9507 9508 for (f = 0; f < faceSize; ++f) { 9509 if (face[f] == cone[v]) { 9510 found = PETSC_TRUE; break; 9511 } 9512 } 9513 if (found) { 9514 indices[v2] = v; 9515 origVertices[v2] = cone[v]; 9516 ++v2; 9517 } else { 9518 oppositeVertex = v; 9519 } 9520 } 9521 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9522 PetscFunctionReturn(0); 9523 } 9524 9525 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9526 { 9527 switch (i) { 9528 case 0: 9529 switch (j) { 9530 case 0: return 0; 9531 case 1: 9532 switch (k) { 9533 case 0: return 0; 9534 case 1: return 0; 9535 case 2: return 1; 9536 } 9537 case 2: 9538 switch (k) { 9539 case 0: return 0; 9540 case 1: return -1; 9541 case 2: return 0; 9542 } 9543 } 9544 case 1: 9545 switch (j) { 9546 case 0: 9547 switch (k) { 9548 case 0: return 0; 9549 case 1: return 0; 9550 case 2: return -1; 9551 } 9552 case 1: return 0; 9553 case 2: 9554 switch (k) { 9555 case 0: return 1; 9556 case 1: return 0; 9557 case 2: return 0; 9558 } 9559 } 9560 case 2: 9561 switch (j) { 9562 case 0: 9563 switch (k) { 9564 case 0: return 0; 9565 case 1: return 1; 9566 case 2: return 0; 9567 } 9568 case 1: 9569 switch (k) { 9570 case 0: return -1; 9571 case 1: return 0; 9572 case 2: return 0; 9573 } 9574 case 2: return 0; 9575 } 9576 } 9577 return 0; 9578 } 9579 9580 #undef __FUNCT__ 9581 #define __FUNCT__ "DMPlexCreateRigidBody" 9582 /*@C 9583 DMPlexCreateRigidBody - create rigid body modes from coordinates 9584 9585 Collective on DM 9586 9587 Input Arguments: 9588 + dm - the DM 9589 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9590 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9591 9592 Output Argument: 9593 . sp - the null space 9594 9595 Note: This is necessary to take account of Dirichlet conditions on the displacements 9596 9597 Level: advanced 9598 9599 .seealso: MatNullSpaceCreate() 9600 @*/ 9601 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9602 { 9603 MPI_Comm comm = ((PetscObject) dm)->comm; 9604 Vec coordinates, localMode, mode[6]; 9605 PetscSection coordSection; 9606 PetscScalar *coords; 9607 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9608 PetscErrorCode ierr; 9609 9610 PetscFunctionBegin; 9611 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9612 if (dim == 1) { 9613 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9614 PetscFunctionReturn(0); 9615 } 9616 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9617 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9618 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9619 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9620 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9621 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9622 m = (dim*(dim+1))/2; 9623 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9624 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9625 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9626 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9627 /* Assume P1 */ 9628 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9629 for (d = 0; d < dim; ++d) { 9630 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9631 9632 values[d] = 1.0; 9633 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9634 for (v = vStart; v < vEnd; ++v) { 9635 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9636 } 9637 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9638 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9639 } 9640 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9641 for (d = dim; d < dim*(dim+1)/2; ++d) { 9642 PetscInt i, j, k = dim > 2 ? d - dim : d; 9643 9644 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9645 for (v = vStart; v < vEnd; ++v) { 9646 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9647 PetscInt off; 9648 9649 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9650 for (i = 0; i < dim; ++i) { 9651 for (j = 0; j < dim; ++j) { 9652 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9653 } 9654 } 9655 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9656 } 9657 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9658 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9659 } 9660 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9661 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9662 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9663 /* Orthonormalize system */ 9664 for (i = dim; i < m; ++i) { 9665 PetscScalar dots[6]; 9666 9667 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9668 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9669 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9670 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9671 } 9672 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9673 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9674 PetscFunctionReturn(0); 9675 } 9676 9677 #undef __FUNCT__ 9678 #define __FUNCT__ "DMPlexGetHybridBounds" 9679 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9680 { 9681 DM_Plex *mesh = (DM_Plex*) dm->data; 9682 PetscInt dim; 9683 PetscErrorCode ierr; 9684 9685 PetscFunctionBegin; 9686 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9687 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9688 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9689 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9690 if (eMax) *eMax = mesh->hybridPointMax[1]; 9691 if (vMax) *vMax = mesh->hybridPointMax[0]; 9692 PetscFunctionReturn(0); 9693 } 9694 9695 #undef __FUNCT__ 9696 #define __FUNCT__ "DMPlexSetHybridBounds" 9697 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9698 { 9699 DM_Plex *mesh = (DM_Plex*) dm->data; 9700 PetscInt dim; 9701 PetscErrorCode ierr; 9702 9703 PetscFunctionBegin; 9704 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9705 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9706 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9707 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9708 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9709 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9710 PetscFunctionReturn(0); 9711 } 9712 9713 #undef __FUNCT__ 9714 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9715 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9716 { 9717 DM_Plex *mesh = (DM_Plex*) dm->data; 9718 9719 PetscFunctionBegin; 9720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9721 PetscValidPointer(cellHeight, 2); 9722 *cellHeight = mesh->vtkCellHeight; 9723 PetscFunctionReturn(0); 9724 } 9725 9726 #undef __FUNCT__ 9727 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9728 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9729 { 9730 DM_Plex *mesh = (DM_Plex*) dm->data; 9731 9732 PetscFunctionBegin; 9733 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9734 mesh->vtkCellHeight = cellHeight; 9735 PetscFunctionReturn(0); 9736 } 9737 9738 #undef __FUNCT__ 9739 #define __FUNCT__ "DMPlexInsertFace_Private" 9740 /* 9741 DMPlexInsertFace_Private - Puts a face into the mesh 9742 9743 Not collective 9744 9745 Input Parameters: 9746 + dm - The DMPlex 9747 . numFaceVertex - The number of vertices in the face 9748 . faceVertices - The vertices in the face for dm 9749 . subfaceVertices - The vertices in the face for subdm 9750 . numCorners - The number of vertices in the cell 9751 . cell - A cell in dm containing the face 9752 . subcell - A cell in subdm containing the face 9753 . firstFace - First face in the mesh 9754 - newFacePoint - Next face in the mesh 9755 9756 Output Parameters: 9757 . newFacePoint - Contains next face point number on input, updated on output 9758 9759 Level: developer 9760 */ 9761 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) 9762 { 9763 MPI_Comm comm = ((PetscObject) dm)->comm; 9764 DM_Plex *submesh = (DM_Plex*) subdm->data; 9765 const PetscInt *faces; 9766 PetscInt numFaces, coneSize; 9767 PetscErrorCode ierr; 9768 9769 PetscFunctionBegin; 9770 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9771 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9772 #if 0 9773 /* Cannot use this because support() has not been constructed yet */ 9774 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9775 #else 9776 { 9777 PetscInt f; 9778 9779 numFaces = 0; 9780 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void**) &faces);CHKERRQ(ierr); 9781 for (f = firstFace; f < *newFacePoint; ++f) { 9782 PetscInt dof, off, d; 9783 9784 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9785 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9786 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9787 for (d = 0; d < dof; ++d) { 9788 const PetscInt p = submesh->cones[off+d]; 9789 PetscInt v; 9790 9791 for (v = 0; v < numFaceVertices; ++v) { 9792 if (subfaceVertices[v] == p) break; 9793 } 9794 if (v == numFaceVertices) break; 9795 } 9796 if (d == dof) { 9797 numFaces = 1; 9798 ((PetscInt*) faces)[0] = f; 9799 } 9800 } 9801 } 9802 #endif 9803 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 9804 else if (numFaces == 1) { 9805 /* Add the other cell neighbor for this face */ 9806 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 9807 } else { 9808 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 9809 PetscBool posOriented; 9810 9811 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9812 origVertices = &orientedVertices[numFaceVertices]; 9813 indices = &orientedVertices[numFaceVertices*2]; 9814 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 9815 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 9816 /* TODO: I know that routine should return a permutation, not the indices */ 9817 for (v = 0; v < numFaceVertices; ++v) { 9818 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 9819 for (ov = 0; ov < numFaceVertices; ++ov) { 9820 if (orientedVertices[ov] == vertex) { 9821 orientedSubVertices[ov] = subvertex; 9822 break; 9823 } 9824 } 9825 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 9826 } 9827 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 9828 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 9829 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9830 ++(*newFacePoint); 9831 } 9832 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9833 PetscFunctionReturn(0); 9834 } 9835 9836 #undef __FUNCT__ 9837 #define __FUNCT__ "DMPlexCreateSubmesh_Uninterpolated" 9838 static PetscErrorCode DMPlexCreateSubmesh_Uninterpolated(DM dm, const char label[], const char surfaceLabel[], DM subdm) 9839 { 9840 MPI_Comm comm = ((PetscObject) dm)->comm; 9841 PetscBool boundaryFaces = PETSC_FALSE; 9842 PetscSection coordSection, subCoordSection; 9843 Vec coordinates, subCoordinates; 9844 PetscScalar *coords, *subCoords; 9845 IS labelIS, subpointMap; 9846 const PetscInt *subVertices; 9847 PetscInt *subVerticesActive, *tmpPoints; 9848 PetscInt *subCells = PETSC_NULL; 9849 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 9850 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 9851 PetscInt dim; /* Right now, do not specify dimension */ 9852 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 9853 PetscErrorCode ierr; 9854 9855 PetscFunctionBegin; 9856 if (surfaceLabel) SETERRQ(comm, PETSC_ERR_SUP, "Yell at me to do this"); 9857 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9858 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9859 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9860 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 9861 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9862 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9863 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9864 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9865 subface = &face[maxConeSize]; 9866 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 9867 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 9868 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 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 = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 10040 for (c = 0; c < numSubCells; ++c) tmpPoints[c] = subCells[c]; 10041 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) tmpPoints[v] = subVerticesActive[v-numSubCells]; 10042 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &subpointMap);CHKERRQ(ierr); 10043 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 10044 ierr = ISDestroy(&subpointMap);CHKERRQ(ierr); 10045 10046 ierr = PetscFree(subCells);CHKERRQ(ierr); 10047 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10048 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10049 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10050 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10051 PetscFunctionReturn(0); 10052 } 10053 10054 #undef __FUNCT__ 10055 #define __FUNCT__ "DMPlexCreateSubmesh_Interpolated" 10056 static PetscErrorCode DMPlexCreateSubmesh_Interpolated(DM dm, const char vertexLabel[], const char surfaceLabel[], DM subdm) 10057 { 10058 MPI_Comm comm = ((PetscObject) dm)->comm; 10059 const char *name = surfaceLabel ? surfaceLabel : "submesh_label"; 10060 DMLabel slabel; 10061 IS subvertexIS, subedgeIS, subfaceIS, subcellIS, subpointMap; 10062 const PetscInt *subVertices, *subEdges, *subFaces, *subCells; 10063 PetscInt *numSubPoints, *coneNew; 10064 PetscInt dim, numSubVerticesInitial, numSubVertices, firstSubVertex, v, numSubEdges = 0, firstSubEdge, e, numSubFaces = 0, firstSubFace, f, numSubCells; 10065 PetscInt vStart, vEnd, fStart, fEnd; 10066 PetscErrorCode ierr; 10067 10068 PetscFunctionBegin; 10069 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10070 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10071 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 10072 ierr = DMPlexCreateLabel(subdm, name);CHKERRQ(ierr); 10073 ierr = DMPlexGetLabel(subdm, name, &slabel);CHKERRQ(ierr); 10074 ierr = DMPlexGetStratumIS(dm, vertexLabel, 1, &subvertexIS);CHKERRQ(ierr); 10075 ierr = ISGetSize(subvertexIS, &numSubVerticesInitial);CHKERRQ(ierr); 10076 ierr = ISGetIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10077 for (v = 0; v < numSubVerticesInitial; ++v) { 10078 const PetscInt vertex = subVertices[v]; 10079 PetscInt *star = PETSC_NULL; 10080 PetscInt starSize, s, numFaces = 0, f; 10081 10082 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10083 for (s = 0; s < starSize*2; s += 2) { 10084 const PetscInt point = star[s]; 10085 if ((point >= fStart) && (point < fEnd)) { 10086 star[numFaces++] = point; 10087 } 10088 } 10089 for (f = 0; f < numFaces; ++f) { 10090 const PetscInt face = star[f]; 10091 PetscInt *closure = PETSC_NULL; 10092 PetscInt closureSize, c, numCorners = 0; 10093 PetscInt faceLoc, corner; 10094 10095 ierr = DMLabelGetValue(slabel, face, &faceLoc);CHKERRQ(ierr); 10096 if (faceLoc == dim-1) continue; 10097 if (faceLoc >= 0) SETERRQ2(comm, PETSC_ERR_PLIB, "Face %d has dimension %d in the surface label", face, faceLoc); 10098 ierr = DMPlexGetTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10099 for (c = 0; c < closureSize*2; c += 2) { 10100 const PetscInt point = closure[c]; 10101 if ((point >= vStart) && (point < vEnd)) { 10102 closure[numCorners++] = point; 10103 } 10104 } 10105 for (corner = 0; corner < numCorners; ++corner) { 10106 const PetscInt cellVertex = closure[corner]; 10107 PetscInt vertexLoc; 10108 10109 ierr = DMLabelGetValue(slabel, cellVertex, &vertexLoc);CHKERRQ(ierr); 10110 if (vertexLoc < 0) break; 10111 } 10112 ierr = DMPlexRestoreTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10113 if (corner == numCorners) { 10114 const PetscInt *support; 10115 PetscInt supportSize; 10116 10117 for (corner = 0; corner < numCorners; ++corner) {ierr = DMLabelSetValue(slabel, closure[corner], 0);CHKERRQ(ierr);} 10118 ierr = DMLabelSetValue(slabel, face, dim-1);CHKERRQ(ierr); 10119 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10120 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10121 for(s = 0; s < supportSize; ++s) { 10122 ierr = DMLabelSetValue(slabel, support[s], dim);CHKERRQ(ierr); 10123 } 10124 if (dim > 2) { 10125 const PetscInt *cone; 10126 PetscInt coneSize; 10127 10128 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10129 ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 10130 for(c = 0; c < coneSize; ++c) { 10131 ierr = DMLabelSetValue(slabel, cone[c], dim-2);CHKERRQ(ierr); 10132 } 10133 } 10134 } 10135 } 10136 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10137 } 10138 ierr = ISRestoreIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10139 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 10140 ierr = DMLabelGetStratumSize(slabel, dim, &numSubCells);CHKERRQ(ierr); 10141 ierr = DMLabelGetStratumSize(slabel, 0, &numSubVertices);CHKERRQ(ierr); 10142 if (dim > 1) {ierr = DMLabelGetStratumSize(slabel, dim-1, &numSubFaces);CHKERRQ(ierr);} 10143 if (dim > 2) {ierr = DMLabelGetStratumSize(slabel, 1, &numSubEdges);CHKERRQ(ierr);} 10144 ierr = DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubEdges+numSubVertices);CHKERRQ(ierr); 10145 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 10146 /* Set cone sizes */ 10147 firstSubVertex = numSubCells; 10148 firstSubFace = firstSubVertex + numSubVertices; 10149 firstSubEdge = firstSubFace + numSubFaces; 10150 ierr = DMLabelGetStratumIS(slabel, dim, &subcellIS);CHKERRQ(ierr); 10151 ierr = ISGetIndices(subcellIS, &subCells);CHKERRQ(ierr); 10152 ierr = DMLabelGetStratumIS(slabel, 0, &subvertexIS);CHKERRQ(ierr); 10153 ierr = ISGetIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10154 if (dim > 1) { 10155 ierr = DMLabelGetStratumIS(slabel, dim-1, &subfaceIS);CHKERRQ(ierr); 10156 ierr = ISGetIndices(subfaceIS, &subFaces);CHKERRQ(ierr); 10157 } 10158 if (dim > 2) { 10159 ierr = DMLabelGetStratumIS(slabel, 1, &subedgeIS);CHKERRQ(ierr); 10160 ierr = ISGetIndices(subedgeIS, &subEdges);CHKERRQ(ierr); 10161 } 10162 for (e = firstSubEdge; e < firstSubEdge+numSubEdges; ++e) { 10163 ierr = DMPlexSetConeSize(subdm, e, 2);CHKERRQ(ierr); 10164 } 10165 for (f = 0; f < numSubFaces; ++f) { 10166 const PetscInt face = subFaces[f]; 10167 const PetscInt subface = firstSubFace + f; 10168 const PetscInt *support; 10169 PetscInt coneSize, supportSize, subcell, s; 10170 10171 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10172 ierr = DMPlexSetConeSize(subdm, subface, coneSize);CHKERRQ(ierr); 10173 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10174 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10175 for(s = 0; s < supportSize; ++s) { 10176 ierr = PetscFindInt(support[s], numSubCells, subCells, &subcell);CHKERRQ(ierr); 10177 if (subcell < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Subcell %d not found in surface label", support[s]); 10178 /* ierr = DMPlexAddConeSize(subdm, subcell, 1);CHKERRQ(ierr); */ 10179 } 10180 } 10181 ierr = DMSetUp(subdm);CHKERRQ(ierr); 10182 /* Set cones */ 10183 for (e = 0; e < numSubEdges; ++e) { 10184 const PetscInt edge = subEdges[e]; 10185 const PetscInt subedge = firstSubEdge + e; 10186 const PetscInt *cone; 10187 PetscInt coneSize, c, coneNew[2], subv; 10188 10189 ierr = DMPlexGetConeSize(subdm, e, &coneSize);CHKERRQ(ierr); 10190 if (coneSize != 2) SETERRQ3(comm, PETSC_ERR_ARG_OUTOFRANGE, "Edge %d matching subedge %d had cone size %d != 2", edge, subedge, coneSize); 10191 ierr = DMPlexGetCone(subdm, e, &cone);CHKERRQ(ierr); 10192 for(c = 0; c < coneSize; ++c) { 10193 ierr = PetscFindInt(cone[c], numSubVertices, subVertices, &subv);CHKERRQ(ierr); 10194 if (subv < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Vertex %d has no matching subvertex", cone[v]); 10195 coneNew[c] = firstSubVertex + subv; 10196 } 10197 ierr = DMPlexSetCone(subdm, e, coneNew);CHKERRQ(ierr); 10198 } 10199 for (f = 0; f < numSubFaces; ++f) { 10200 const PetscInt face = subFaces[f]; 10201 const PetscInt subface = firstSubFace + f; 10202 const PetscInt *cone, *support; 10203 PetscInt coneSize, supportSize, subvertex, subcell, c, s; 10204 10205 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10206 ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 10207 for(c = 0; c < coneSize; ++c) { 10208 ierr = PetscFindInt(cone[c], numSubVertices, subVertices, &subvertex);CHKERRQ(ierr); 10209 if (subvertex < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Vertex %d has no matching subvertex", cone[v]); 10210 coneNew[c] = firstSubVertex + subvertex; 10211 } 10212 ierr = DMPlexSetCone(subdm, subface, coneNew);CHKERRQ(ierr); 10213 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10214 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10215 for(s = 0; s < supportSize; ++s) { 10216 ierr = PetscFindInt(support[s], numSubCells, subCells, &subcell);CHKERRQ(ierr); 10217 if (subcell < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Subcell %d not found in surface label", support[s]); 10218 /* ierr = DMPlexAddCone(subdm, subcell, 1);CHKERRQ(ierr); */ 10219 } 10220 } 10221 ierr = ISRestoreIndices(subcellIS, &subCells);CHKERRQ(ierr); 10222 ierr = ISDestroy(&subcellIS);CHKERRQ(ierr); 10223 ierr = ISRestoreIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10224 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 10225 if (dim > 1) { 10226 ierr = ISRestoreIndices(subfaceIS, &subFaces);CHKERRQ(ierr); 10227 ierr = ISDestroy(&subfaceIS);CHKERRQ(ierr); 10228 } 10229 if (dim > 2) { 10230 ierr = ISRestoreIndices(subedgeIS, &subEdges);CHKERRQ(ierr); 10231 ierr = ISDestroy(&subedgeIS);CHKERRQ(ierr); 10232 } 10233 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 10234 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 10235 /* Build coordinates */ 10236 { 10237 PetscSection coordSection, subCoordSection; 10238 Vec coordinates, subCoordinates; 10239 PetscScalar *coords, *subCoords; 10240 PetscInt coordSize; 10241 10242 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10243 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10244 ierr = DMPlexGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 10245 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVertices);CHKERRQ(ierr); 10246 for (v = 0; v < numSubVertices; ++v) { 10247 const PetscInt vertex = subVertices[v]; 10248 const PetscInt subVertex = firstSubVertex+v; 10249 PetscInt dof; 10250 10251 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10252 ierr = PetscSectionSetDof(subCoordSection, subVertex, dof);CHKERRQ(ierr); 10253 } 10254 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10255 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10256 ierr = VecCreate(comm, &subCoordinates);CHKERRQ(ierr); 10257 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10258 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10259 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10260 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10261 for (v = 0; v < numSubVertices; ++v) { 10262 const PetscInt vertex = subVertices[v]; 10263 const PetscInt subVertex = firstSubVertex+v; 10264 PetscInt dof, off, sdof, soff, d; 10265 10266 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10267 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10268 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10269 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10270 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10271 for (d = 0; d < dof; ++d) { 10272 subCoords[soff+d] = coords[off+d]; 10273 } 10274 } 10275 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10276 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10277 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 10278 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10279 } 10280 /* TODO: Create map from submesh points to original mesh points */ 10281 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 10282 PetscFunctionReturn(0); 10283 } 10284 10285 #undef __FUNCT__ 10286 #define __FUNCT__ "DMPlexCreateSubmesh" 10287 /* 10288 DMPlexCreateSubmesh - Extract a hypersurface from the mesh using vertices defined by a label 10289 10290 Input Parameters: 10291 + dm - The original mesh 10292 . vertexLabel - The DMLabel marking vertices contained in the surface 10293 - surfaceLabel - If not PETSC_NULL, create a new label with all the surface points labeled by dimension 10294 10295 Output Parameter: 10296 . subdm - The surface mesh 10297 10298 Level: developer 10299 10300 .seealso: DMPlexGetLabel(), DMLabelSetValue() 10301 */ 10302 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char vertexLabel[], const char surfaceLabel[], DM *subdm) 10303 { 10304 PetscInt dim, depth; 10305 PetscErrorCode ierr; 10306 10307 PetscFunctionBegin; 10308 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10309 PetscValidCharPointer(vertexLabel, 2); 10310 PetscValidPointer(subdm, 4); 10311 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10312 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 10313 ierr = DMCreate(((PetscObject) dm)->comm, subdm);CHKERRQ(ierr); 10314 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 10315 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 10316 /* TODO Remove the dim guard */ 10317 if ((dim > 1) && (depth == dim)) { 10318 ierr = DMPlexCreateSubmesh_Interpolated(dm, vertexLabel, surfaceLabel, *subdm);CHKERRQ(ierr); 10319 } else { 10320 ierr = DMPlexCreateSubmesh_Uninterpolated(dm, vertexLabel, surfaceLabel, *subdm);CHKERRQ(ierr); 10321 } 10322 PetscFunctionReturn(0); 10323 } 10324 10325 #undef __FUNCT__ 10326 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10327 /* We can easily have a form that takes an IS instead */ 10328 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10329 { 10330 PetscSection section, globalSection; 10331 PetscInt *numbers, p; 10332 PetscErrorCode ierr; 10333 10334 PetscFunctionBegin; 10335 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10336 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10337 for (p = pStart; p < pEnd; ++p) { 10338 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10339 } 10340 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10341 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10342 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10343 for (p = pStart; p < pEnd; ++p) { 10344 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10345 } 10346 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10347 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10348 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10349 PetscFunctionReturn(0); 10350 } 10351 10352 #undef __FUNCT__ 10353 #define __FUNCT__ "DMPlexGetCellNumbering" 10354 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10355 { 10356 DM_Plex *mesh = (DM_Plex*) dm->data; 10357 PetscInt cellHeight, cStart, cEnd, cMax; 10358 PetscErrorCode ierr; 10359 10360 PetscFunctionBegin; 10361 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10362 if (!mesh->globalCellNumbers) { 10363 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10364 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10365 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10366 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 10367 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10368 } 10369 *globalCellNumbers = mesh->globalCellNumbers; 10370 PetscFunctionReturn(0); 10371 } 10372 10373 #undef __FUNCT__ 10374 #define __FUNCT__ "DMPlexGetVertexNumbering" 10375 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10376 { 10377 DM_Plex *mesh = (DM_Plex*) dm->data; 10378 PetscInt vStart, vEnd, vMax; 10379 PetscErrorCode ierr; 10380 10381 PetscFunctionBegin; 10382 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10383 if (!mesh->globalVertexNumbers) { 10384 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10385 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10386 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 10387 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10388 } 10389 *globalVertexNumbers = mesh->globalVertexNumbers; 10390 PetscFunctionReturn(0); 10391 } 10392 10393 #undef __FUNCT__ 10394 #define __FUNCT__ "DMPlexGetSubpointMap" 10395 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 10396 { 10397 DM_Plex *mesh = (DM_Plex*) dm->data; 10398 10399 PetscFunctionBegin; 10400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10401 PetscValidPointer(subpointMap, 2); 10402 *subpointMap = mesh->subpointMap; 10403 PetscFunctionReturn(0); 10404 } 10405 10406 #undef __FUNCT__ 10407 #define __FUNCT__ "DMPlexSetSubpointMap" 10408 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10409 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 10410 { 10411 DM_Plex *mesh = (DM_Plex *) dm->data; 10412 PetscErrorCode ierr; 10413 10414 PetscFunctionBegin; 10415 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10416 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 10417 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 10418 mesh->subpointMap = subpointMap; 10419 ierr = PetscObjectReference((PetscObject) mesh->subpointMap);CHKERRQ(ierr); 10420 PetscFunctionReturn(0); 10421 } 10422 10423 #undef __FUNCT__ 10424 #define __FUNCT__ "DMPlexGetScale" 10425 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10426 { 10427 DM_Plex *mesh = (DM_Plex*) dm->data; 10428 10429 PetscFunctionBegin; 10430 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10431 PetscValidPointer(scale, 3); 10432 *scale = mesh->scale[unit]; 10433 PetscFunctionReturn(0); 10434 } 10435 10436 #undef __FUNCT__ 10437 #define __FUNCT__ "DMPlexSetScale" 10438 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10439 { 10440 DM_Plex *mesh = (DM_Plex*) dm->data; 10441 10442 PetscFunctionBegin; 10443 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10444 mesh->scale[unit] = scale; 10445 PetscFunctionReturn(0); 10446 } 10447 10448 10449 /******************************************************************************* 10450 This should be in a separate Discretization object, but I am not sure how to lay 10451 it out yet, so I am stuffing things here while I experiment. 10452 *******************************************************************************/ 10453 #undef __FUNCT__ 10454 #define __FUNCT__ "DMPlexSetFEMIntegration" 10455 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10456 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10457 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10458 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10459 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10460 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10461 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10462 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10463 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10464 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10465 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10466 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10467 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10468 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10469 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10470 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10471 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 10472 { 10473 DM_Plex *mesh = (DM_Plex*) dm->data; 10474 10475 PetscFunctionBegin; 10476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10477 mesh->integrateResidualFEM = integrateResidualFEM; 10478 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10479 mesh->integrateJacobianFEM = integrateJacobianFEM; 10480 PetscFunctionReturn(0); 10481 } 10482 10483 #undef __FUNCT__ 10484 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10485 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10486 { 10487 Vec coordinates; 10488 PetscSection section, cSection; 10489 PetscInt dim, vStart, vEnd, v, c, d; 10490 PetscScalar *values, *cArray; 10491 PetscReal *coords; 10492 PetscErrorCode ierr; 10493 10494 PetscFunctionBegin; 10495 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10496 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10497 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10498 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10499 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10500 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10501 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10502 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10503 for (v = vStart; v < vEnd; ++v) { 10504 PetscInt dof, off; 10505 10506 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10507 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10508 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10509 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 10510 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10511 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10512 } 10513 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10514 /* Temporary, must be replaced by a projection on the finite element basis */ 10515 { 10516 PetscInt eStart = 0, eEnd = 0, e, depth; 10517 10518 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10519 --depth; 10520 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10521 for (e = eStart; e < eEnd; ++e) { 10522 const PetscInt *cone = PETSC_NULL; 10523 PetscInt coneSize, d; 10524 PetscScalar *coordsA, *coordsB; 10525 10526 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10527 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10528 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10529 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10530 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10531 for (d = 0; d < dim; ++d) { 10532 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10533 } 10534 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10535 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10536 } 10537 } 10538 10539 ierr = PetscFree(coords);CHKERRQ(ierr); 10540 ierr = PetscFree(values);CHKERRQ(ierr); 10541 #if 0 10542 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10543 PetscReal detJ; 10544 10545 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10546 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10547 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10548 10549 for (PetscInt c = cStart; c < cEnd; ++c) { 10550 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10551 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10552 const int oSize = pV.getSize(); 10553 int v = 0; 10554 10555 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10556 for (PetscInt cl = 0; cl < oSize; ++cl) { 10557 const PetscInt fDim; 10558 10559 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10560 if (pointDim) { 10561 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10562 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10563 } 10564 } 10565 } 10566 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10567 pV.clear(); 10568 } 10569 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10570 ierr = PetscFree(values);CHKERRQ(ierr); 10571 #endif 10572 PetscFunctionReturn(0); 10573 } 10574 10575 #undef __FUNCT__ 10576 #define __FUNCT__ "DMPlexProjectFunction" 10577 /*@C 10578 DMPlexProjectFunction - This projects the given function into the function space provided. 10579 10580 Input Parameters: 10581 + dm - The DM 10582 . numComp - The number of components (functions) 10583 . funcs - The coordinate functions to evaluate 10584 - mode - The insertion mode for values 10585 10586 Output Parameter: 10587 . X - vector 10588 10589 Level: developer 10590 10591 Note: 10592 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10593 We will eventually fix it. 10594 10595 ,seealso: DMPlexComputeL2Diff() 10596 */ 10597 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10598 { 10599 Vec localX; 10600 PetscErrorCode ierr; 10601 10602 PetscFunctionBegin; 10603 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10604 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10605 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10606 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10607 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10608 PetscFunctionReturn(0); 10609 } 10610 10611 #undef __FUNCT__ 10612 #define __FUNCT__ "DMPlexComputeL2Diff" 10613 /*@C 10614 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10615 10616 Input Parameters: 10617 + dm - The DM 10618 . quad - The PetscQuadrature object for each field 10619 . funcs - The functions to evaluate for each field component 10620 - X - The coefficient vector u_h 10621 10622 Output Parameter: 10623 . diff - The diff ||u - u_h||_2 10624 10625 Level: developer 10626 10627 .seealso: DMPlexProjectFunction() 10628 */ 10629 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10630 { 10631 const PetscInt debug = 0; 10632 PetscSection section; 10633 Vec localX; 10634 PetscReal *coords, *v0, *J, *invJ, detJ; 10635 PetscReal localDiff = 0.0; 10636 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10637 PetscErrorCode ierr; 10638 10639 PetscFunctionBegin; 10640 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10641 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10642 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10643 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10644 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10645 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10646 for (field = 0; field < numFields; ++field) { 10647 numComponents += quad[field].numComponents; 10648 } 10649 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10650 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10651 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10652 for (c = cStart; c < cEnd; ++c) { 10653 const PetscScalar *x; 10654 PetscReal elemDiff = 0.0; 10655 10656 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10657 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10658 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10659 10660 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10661 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10662 const PetscReal *quadPoints = quad[field].quadPoints; 10663 const PetscReal *quadWeights = quad[field].quadWeights; 10664 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10665 const PetscInt numBasisComps = quad[field].numComponents; 10666 const PetscReal *basis = quad[field].basis; 10667 PetscInt q, d, e, fc, f; 10668 10669 if (debug) { 10670 char title[1024]; 10671 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10672 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10673 } 10674 for (q = 0; q < numQuadPoints; ++q) { 10675 for (d = 0; d < dim; d++) { 10676 coords[d] = v0[d]; 10677 for (e = 0; e < dim; e++) { 10678 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10679 } 10680 } 10681 for (fc = 0; fc < numBasisComps; ++fc) { 10682 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10683 PetscReal interpolant = 0.0; 10684 for (f = 0; f < numBasisFuncs; ++f) { 10685 const PetscInt fidx = f*numBasisComps+fc; 10686 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10687 } 10688 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10689 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10690 } 10691 } 10692 comp += numBasisComps; 10693 fieldOffset += numBasisFuncs*numBasisComps; 10694 } 10695 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10696 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10697 localDiff += elemDiff; 10698 } 10699 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10700 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10701 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10702 *diff = PetscSqrtReal(*diff); 10703 PetscFunctionReturn(0); 10704 } 10705 10706 #undef __FUNCT__ 10707 #define __FUNCT__ "DMPlexComputeResidualFEM" 10708 /*@ 10709 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10710 10711 Input Parameters: 10712 + dm - The mesh 10713 . X - Local input vector 10714 - user - The user context 10715 10716 Output Parameter: 10717 . F - Local output vector 10718 10719 Note: 10720 The second member of the user context must be an FEMContext. 10721 10722 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10723 like a GPU, or vectorize on a multicore machine. 10724 10725 .seealso: DMPlexComputeJacobianActionFEM() 10726 */ 10727 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10728 { 10729 DM_Plex *mesh = (DM_Plex*) dm->data; 10730 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10731 PetscQuadrature *quad = fem->quad; 10732 PetscSection section; 10733 PetscReal *v0, *J, *invJ, *detJ; 10734 PetscScalar *elemVec, *u; 10735 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10736 PetscInt cellDof = 0, numComponents = 0; 10737 PetscErrorCode ierr; 10738 10739 PetscFunctionBegin; 10740 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10741 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10742 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10743 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10744 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10745 numCells = cEnd - cStart; 10746 for (field = 0; field < numFields; ++field) { 10747 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10748 numComponents += quad[field].numComponents; 10749 } 10750 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10751 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10752 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); 10753 for (c = cStart; c < cEnd; ++c) { 10754 const PetscScalar *x; 10755 PetscInt i; 10756 10757 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10758 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10759 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10760 10761 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10762 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10763 } 10764 for (field = 0; field < numFields; ++field) { 10765 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10766 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10767 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10768 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10769 /* Conforming batches */ 10770 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10771 PetscInt numBlocks = 1; 10772 PetscInt batchSize = numBlocks * blockSize; 10773 PetscInt numBatches = numBatchesTmp; 10774 PetscInt numChunks = numCells / (numBatches*batchSize); 10775 /* Remainder */ 10776 PetscInt numRemainder = numCells % (numBatches * batchSize); 10777 PetscInt offset = numCells - numRemainder; 10778 10779 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10780 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10781 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10782 } 10783 for (c = cStart; c < cEnd; ++c) { 10784 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10785 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10786 } 10787 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10788 if (mesh->printFEM) { 10789 PetscMPIInt rank, numProcs; 10790 PetscInt p; 10791 10792 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10793 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10794 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10795 for (p = 0; p < numProcs; ++p) { 10796 if (p == rank) { 10797 Vec f; 10798 10799 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10800 ierr = VecCopy(F, f);CHKERRQ(ierr); 10801 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10802 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10803 ierr = VecDestroy(&f);CHKERRQ(ierr); 10804 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10805 } 10806 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10807 } 10808 } 10809 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10810 PetscFunctionReturn(0); 10811 } 10812 10813 #undef __FUNCT__ 10814 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10815 /*@C 10816 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10817 10818 Input Parameters: 10819 + dm - The mesh 10820 . J - The Jacobian shell matrix 10821 . X - Local input vector 10822 - user - The user context 10823 10824 Output Parameter: 10825 . F - Local output vector 10826 10827 Note: 10828 The second member of the user context must be an FEMContext. 10829 10830 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10831 like a GPU, or vectorize on a multicore machine. 10832 10833 .seealso: DMPlexComputeResidualFEM() 10834 */ 10835 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10836 { 10837 DM_Plex *mesh = (DM_Plex*) dm->data; 10838 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10839 PetscQuadrature *quad = fem->quad; 10840 PetscSection section; 10841 JacActionCtx *jctx; 10842 PetscReal *v0, *J, *invJ, *detJ; 10843 PetscScalar *elemVec, *u, *a; 10844 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10845 PetscInt cellDof = 0; 10846 PetscErrorCode ierr; 10847 10848 PetscFunctionBegin; 10849 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10850 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10851 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10852 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10853 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10854 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10855 numCells = cEnd - cStart; 10856 for (field = 0; field < numFields; ++field) { 10857 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10858 } 10859 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10860 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); 10861 for (c = cStart; c < cEnd; ++c) { 10862 const PetscScalar *x; 10863 PetscInt i; 10864 10865 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10866 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10867 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10868 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10869 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10870 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10871 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 10872 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10873 } 10874 for (field = 0; field < numFields; ++field) { 10875 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10876 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10877 /* Conforming batches */ 10878 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10879 PetscInt numBlocks = 1; 10880 PetscInt batchSize = numBlocks * blockSize; 10881 PetscInt numBatches = numBatchesTmp; 10882 PetscInt numChunks = numCells / (numBatches*batchSize); 10883 /* Remainder */ 10884 PetscInt numRemainder = numCells % (numBatches * batchSize); 10885 PetscInt offset = numCells - numRemainder; 10886 10887 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); 10888 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], 10889 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10890 } 10891 for (c = cStart; c < cEnd; ++c) { 10892 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10893 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10894 } 10895 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10896 if (mesh->printFEM) { 10897 PetscMPIInt rank, numProcs; 10898 PetscInt p; 10899 10900 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10901 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10902 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10903 for (p = 0; p < numProcs; ++p) { 10904 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10905 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10906 } 10907 } 10908 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10909 PetscFunctionReturn(0); 10910 } 10911 10912 #undef __FUNCT__ 10913 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10914 /*@ 10915 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10916 10917 Input Parameters: 10918 + dm - The mesh 10919 . X - Local input vector 10920 - user - The user context 10921 10922 Output Parameter: 10923 . Jac - Jacobian matrix 10924 10925 Note: 10926 The second member of the user context must be an FEMContext. 10927 10928 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10929 like a GPU, or vectorize on a multicore machine. 10930 10931 .seealso: FormFunctionLocal() 10932 */ 10933 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10934 { 10935 DM_Plex *mesh = (DM_Plex*) dm->data; 10936 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10937 PetscQuadrature *quad = fem->quad; 10938 PetscSection section; 10939 PetscReal *v0, *J, *invJ, *detJ; 10940 PetscScalar *elemMat, *u; 10941 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10942 PetscInt cellDof = 0, numComponents = 0; 10943 PetscBool isShell; 10944 PetscErrorCode ierr; 10945 10946 PetscFunctionBegin; 10947 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10948 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10949 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10950 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10951 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10952 numCells = cEnd - cStart; 10953 for (field = 0; field < numFields; ++field) { 10954 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10955 numComponents += quad[field].numComponents; 10956 } 10957 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10958 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10959 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); 10960 for (c = cStart; c < cEnd; ++c) { 10961 const PetscScalar *x; 10962 PetscInt i; 10963 10964 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10965 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10966 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10967 10968 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10969 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10970 } 10971 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10972 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10973 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10974 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10975 PetscInt fieldJ; 10976 10977 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10978 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10979 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10980 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10981 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10982 /* Conforming batches */ 10983 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10984 PetscInt numBlocks = 1; 10985 PetscInt batchSize = numBlocks * blockSize; 10986 PetscInt numBatches = numBatchesTmp; 10987 PetscInt numChunks = numCells / (numBatches*batchSize); 10988 /* Remainder */ 10989 PetscInt numRemainder = numCells % (numBatches * batchSize); 10990 PetscInt offset = numCells - numRemainder; 10991 10992 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10993 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10994 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10995 } 10996 } 10997 for (c = cStart; c < cEnd; ++c) { 10998 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10999 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 11000 } 11001 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 11002 11003 /* Assemble matrix, using the 2-step process: 11004 MatAssemblyBegin(), MatAssemblyEnd(). */ 11005 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11006 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11007 11008 if (mesh->printFEM) { 11009 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 11010 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 11011 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 11012 } 11013 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11014 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 11015 if (isShell) { 11016 JacActionCtx *jctx; 11017 11018 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 11019 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 11020 } 11021 *str = SAME_NONZERO_PATTERN; 11022 PetscFunctionReturn(0); 11023 } 11024 11025 11026 #undef __FUNCT__ 11027 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 11028 /*@C 11029 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 11030 the local section and an SF describing the section point overlap. 11031 11032 Input Parameters: 11033 + s - The PetscSection for the local field layout 11034 . sf - The SF describing parallel layout of the section points 11035 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 11036 . label - The label specifying the points 11037 - labelValue - The label stratum specifying the points 11038 11039 Output Parameter: 11040 . gsection - The PetscSection for the global field layout 11041 11042 Note: This gives negative sizes and offsets to points not owned by this process 11043 11044 Level: developer 11045 11046 .seealso: PetscSectionCreate() 11047 @*/ 11048 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 11049 { 11050 PetscInt *neg; 11051 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 11052 PetscErrorCode ierr; 11053 11054 PetscFunctionBegin; 11055 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 11056 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 11057 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 11058 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 11059 /* Mark ghost points with negative dof */ 11060 for (p = pStart; p < pEnd; ++p) { 11061 PetscInt value; 11062 11063 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 11064 if (value != labelValue) continue; 11065 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 11066 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 11067 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 11068 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 11069 neg[p-pStart] = -(dof+1); 11070 } 11071 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 11072 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 11073 if (nroots >= 0) { 11074 if (nroots > pEnd - pStart) { 11075 PetscInt *tmpDof; 11076 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11077 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 11078 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11079 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11080 for (p = pStart; p < pEnd; ++p) { 11081 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 11082 } 11083 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 11084 } else { 11085 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11086 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11087 } 11088 } 11089 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 11090 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11091 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 11092 11093 (*gsection)->atlasOff[p] = off; 11094 11095 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 11096 } 11097 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 11098 globalOff -= off; 11099 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11100 (*gsection)->atlasOff[p] += globalOff; 11101 11102 neg[p] = -((*gsection)->atlasOff[p]+1); 11103 } 11104 /* Put in negative offsets for ghost points */ 11105 if (nroots >= 0) { 11106 if (nroots > pEnd - pStart) { 11107 PetscInt *tmpOff; 11108 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11109 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 11110 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11111 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11112 for (p = pStart; p < pEnd; ++p) { 11113 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 11114 } 11115 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 11116 } else { 11117 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11118 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11119 } 11120 } 11121 ierr = PetscFree(neg);CHKERRQ(ierr); 11122 PetscFunctionReturn(0); 11123 } 11124