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