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 if (markers) { 167 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 168 } 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for (c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = PETSC_NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm = ((PetscObject) dm)->comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 284 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 285 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 286 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 287 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 288 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 289 if (depth == 1) { 290 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 291 pEnd = pEnd - pStart; 292 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 293 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 294 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 295 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 296 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 297 pEnd = pEnd - pStart; 298 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 299 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 300 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 301 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 302 } else { 303 for (d = 0; d <= dim; d++) { 304 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 305 pEnd = pEnd - pStart; 306 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 307 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 308 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 309 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 310 } 311 } 312 ierr = PetscFree(sizes);CHKERRQ(ierr); 313 } 314 PetscFunctionReturn(0); 315 } 316 317 #undef __FUNCT__ 318 #define __FUNCT__ "DMView_Plex" 319 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 320 { 321 PetscBool iascii, isbinary; 322 PetscErrorCode ierr; 323 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 326 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 327 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 329 if (iascii) { 330 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 331 #if 0 332 } else if (isbinary) { 333 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 334 #endif 335 } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name); 336 PetscFunctionReturn(0); 337 } 338 339 #undef __FUNCT__ 340 #define __FUNCT__ "DMDestroy_Plex" 341 PetscErrorCode DMDestroy_Plex(DM dm) 342 { 343 DM_Plex *mesh = (DM_Plex *) dm->data; 344 DMLabel next = mesh->labels; 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 if (--mesh->refct > 0) {PetscFunctionReturn(0);} 349 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 350 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 352 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 353 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 355 while (next) { 356 DMLabel tmp = next->next; 357 358 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 359 next = tmp; 360 } 361 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 362 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 364 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 365 ierr = PetscFree(mesh);CHKERRQ(ierr); 366 PetscFunctionReturn(0); 367 } 368 369 #undef __FUNCT__ 370 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 371 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 372 { 373 const PetscInt *support = PETSC_NULL; 374 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 if (useClosure) { 379 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 380 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 381 for (s = 0; s < supportSize; ++s) { 382 const PetscInt *cone = PETSC_NULL; 383 PetscInt coneSize, c, q; 384 385 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 386 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 387 for (c = 0; c < coneSize; ++c) { 388 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 389 if (cone[c] == adj[q]) break; 390 } 391 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 392 } 393 } 394 } else { 395 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 396 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 397 for (s = 0; s < supportSize; ++s) { 398 const PetscInt *cone = PETSC_NULL; 399 PetscInt coneSize, c, q; 400 401 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 402 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 403 for (c = 0; c < coneSize; ++c) { 404 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 405 if (cone[c] == adj[q]) break; 406 } 407 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 408 } 409 } 410 } 411 *adjSize = numAdj; 412 PetscFunctionReturn(0); 413 } 414 415 #undef __FUNCT__ 416 #define __FUNCT__ "DMPlexGetAdjacency_Private" 417 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 418 { 419 const PetscInt *star = tmpClosure; 420 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 421 PetscErrorCode ierr; 422 423 PetscFunctionBegin; 424 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 425 for (s = 2; s < starSize*2; s += 2) { 426 const PetscInt *closure = PETSC_NULL; 427 PetscInt closureSize, c, q; 428 429 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 430 for (c = 0; c < closureSize*2; c += 2) { 431 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 432 if (closure[c] == adj[q]) break; 433 } 434 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 435 } 436 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 437 } 438 *adjSize = numAdj; 439 PetscFunctionReturn(0); 440 } 441 442 #undef __FUNCT__ 443 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 444 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 445 { 446 DM_Plex *mesh = (DM_Plex *) dm->data; 447 448 PetscFunctionBegin; 449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 450 mesh->preallocCenterDim = preallocCenterDim; 451 PetscFunctionReturn(0); 452 } 453 454 #undef __FUNCT__ 455 #define __FUNCT__ "DMPlexPreallocateOperator" 456 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 457 { 458 DM_Plex *mesh = (DM_Plex *) dm->data; 459 MPI_Comm comm = ((PetscObject) dm)->comm; 460 PetscSF sf, sfDof, sfAdj; 461 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 462 PetscInt nleaves, l, p; 463 const PetscInt *leaves; 464 const PetscSFNode *remotes; 465 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 466 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 467 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 468 PetscLayout rLayout; 469 PetscInt locRows, rStart, rEnd, r; 470 PetscMPIInt size; 471 PetscBool useClosure, debug = PETSC_FALSE; 472 PetscErrorCode ierr; 473 474 PetscFunctionBegin; 475 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 476 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 477 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 478 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 479 /* Create dof SF based on point SF */ 480 if (debug) { 481 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 487 } 488 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 489 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 490 if (debug) { 491 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 492 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 493 } 494 /* Create section for dof adjacency (dof ==> # adj dof) */ 495 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 496 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 497 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 498 if (mesh->preallocCenterDim == dim) { 499 useClosure = PETSC_FALSE; 500 } else if (mesh->preallocCenterDim == 0) { 501 useClosure = PETSC_TRUE; 502 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 503 504 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 505 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 510 /* Fill in the ghost dofs on the interface */ 511 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 512 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 513 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 514 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 515 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 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) { 639 rootAdj[r] = -1; 640 } 641 if (size > 1) { 642 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 643 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 644 } 645 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 646 ierr = PetscFree(adj);CHKERRQ(ierr); 647 /* Debugging */ 648 if (debug) { 649 IS tmp; 650 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 651 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 652 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 653 } 654 /* Add in local adjacency indices for owned dofs on interface (roots) */ 655 for (p = pStart; p < pEnd; ++p) { 656 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 657 658 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 659 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 660 if (!dof) continue; 661 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 662 if (adof <= 0) continue; 663 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 664 for (d = off; d < off+dof; ++d) { 665 PetscInt adof, aoff, i; 666 667 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 668 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 669 i = adof-1; 670 for (q = 0; q < numAdj; ++q) { 671 PetscInt ndof, ncdof, ngoff, nd; 672 673 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 674 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 675 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 676 for (nd = 0; nd < ndof-ncdof; ++nd) { 677 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 678 --i; 679 } 680 } 681 } 682 } 683 /* Debugging */ 684 if (debug) { 685 IS tmp; 686 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 687 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 688 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 689 } 690 /* Compress indices */ 691 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 692 for (p = pStart; p < pEnd; ++p) { 693 PetscInt dof, cdof, off, d; 694 PetscInt adof, aoff; 695 696 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 697 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 698 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 699 if (!dof) continue; 700 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 701 if (adof <= 0) continue; 702 for (d = off; d < off+dof-cdof; ++d) { 703 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 704 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 705 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 706 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 707 } 708 } 709 /* Debugging */ 710 if (debug) { 711 IS tmp; 712 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 713 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 714 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 715 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 716 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 717 } 718 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 719 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 720 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 721 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 722 for (p = pStart; p < pEnd; ++p) { 723 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 724 PetscBool found = PETSC_TRUE; 725 726 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 727 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 728 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 729 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 730 for (d = 0; d < dof-cdof; ++d) { 731 PetscInt ldof, rdof; 732 733 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 734 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 735 if (ldof > 0) { 736 /* We do not own this point */ 737 } else if (rdof > 0) { 738 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 739 } else { 740 found = PETSC_FALSE; 741 } 742 } 743 if (found) continue; 744 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 745 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 746 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 747 for (q = 0; q < numAdj; ++q) { 748 PetscInt ndof, ncdof, noff; 749 750 /* Adjacent points may not be in the section chart */ 751 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 752 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 753 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 754 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 755 for (d = goff; d < goff+dof-cdof; ++d) { 756 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 757 } 758 } 759 } 760 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 761 if (debug) { 762 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 763 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 764 } 765 /* Get adjacent indices */ 766 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 767 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 768 for (p = pStart; p < pEnd; ++p) { 769 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 770 PetscBool found = PETSC_TRUE; 771 772 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 773 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 774 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 775 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 776 for (d = 0; d < dof-cdof; ++d) { 777 PetscInt ldof, rdof; 778 779 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 780 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 781 if (ldof > 0) { 782 /* We do not own this point */ 783 } else if (rdof > 0) { 784 PetscInt aoff, roff; 785 786 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 787 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 788 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 789 } else { 790 found = PETSC_FALSE; 791 } 792 } 793 if (found) continue; 794 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 795 for (d = goff; d < goff+dof-cdof; ++d) { 796 PetscInt adof, aoff, i = 0; 797 798 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 799 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 800 for (q = 0; q < numAdj; ++q) { 801 PetscInt ndof, ncdof, ngoff, nd; 802 const PetscInt *ncind; 803 804 /* Adjacent points may not be in the section chart */ 805 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 806 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 807 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 808 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 809 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 810 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 811 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 812 } 813 } 814 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); 815 } 816 } 817 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 818 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 819 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 820 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 821 /* Debugging */ 822 if (debug) { 823 IS tmp; 824 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 825 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 826 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 827 } 828 /* Create allocation vectors from adjacency graph */ 829 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 830 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 831 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 832 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 833 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 834 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 835 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 836 /* Only loop over blocks of rows */ 837 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); 838 for (r = rStart/bs; r < rEnd/bs; ++r) { 839 const PetscInt row = r*bs; 840 PetscInt numCols, cStart, c; 841 842 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 843 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 844 for (c = cStart; c < cStart+numCols; ++c) { 845 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 846 ++dnz[r-rStart]; 847 if (cols[c] >= row) {++dnzu[r-rStart];} 848 } else { 849 ++onz[r-rStart]; 850 if (cols[c] >= row) {++onzu[r-rStart];} 851 } 852 } 853 } 854 if (bs > 1) { 855 for (r = 0; r < locRows/bs; ++r) { 856 dnz[r] /= bs; 857 onz[r] /= bs; 858 dnzu[r] /= bs; 859 onzu[r] /= bs; 860 } 861 } 862 /* Set matrix pattern */ 863 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 864 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 865 /* Fill matrix with zeros */ 866 if (fillMatrix) { 867 PetscScalar *values; 868 PetscInt maxRowLen = 0; 869 870 for (r = rStart; r < rEnd; ++r) { 871 PetscInt len; 872 873 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 874 maxRowLen = PetscMax(maxRowLen, len); 875 } 876 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 877 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 878 for (r = rStart; r < rEnd; ++r) { 879 PetscInt numCols, cStart; 880 881 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 882 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 883 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 884 } 885 ierr = PetscFree(values);CHKERRQ(ierr); 886 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 887 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 888 } 889 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 890 ierr = PetscFree(cols);CHKERRQ(ierr); 891 PetscFunctionReturn(0); 892 } 893 894 #if 0 895 #undef __FUNCT__ 896 #define __FUNCT__ "DMPlexPreallocateOperator_2" 897 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 898 { 899 PetscErrorCode ierr; 900 PetscInt c,cStart,cEnd,pStart,pEnd; 901 PetscInt *tmpClosure,*tmpAdj,*visits; 902 903 PetscFunctionBegin; 904 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 905 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 906 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 907 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 908 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 909 npoints = pEnd - pStart; 910 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 911 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 912 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 913 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 914 for (c=cStart; c<cEnd; c++) { 915 PetscInt *support = tmpClosure; 916 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 917 for (p=0; p<supportSize; p++) { 918 lvisits[support[p]]++; 919 } 920 } 921 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 922 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 923 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 924 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 925 926 ierr = PetscSFGetRanks();CHKERRQ(ierr); 927 928 929 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 930 for (c=cStart; c<cEnd; c++) { 931 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 932 /* 933 Depth-first walk of transitive closure. 934 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. 935 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 936 */ 937 } 938 939 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 940 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 941 PetscFunctionReturn(0); 942 } 943 #endif 944 945 #undef __FUNCT__ 946 #define __FUNCT__ "DMCreateMatrix_Plex" 947 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 948 { 949 PetscSection section, sectionGlobal; 950 PetscInt bs = -1; 951 PetscInt localSize; 952 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 953 PetscErrorCode ierr; 954 955 PetscFunctionBegin; 956 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 957 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 958 #endif 959 if (!mtype) mtype = MATAIJ; 960 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 961 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 962 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 963 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 964 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 965 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 966 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 967 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 974 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 975 /* Check for symmetric storage */ 976 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 977 if (isSymmetric) { 978 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 979 } 980 if (!isShell) { 981 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 982 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal; 983 984 if (bs < 0) { 985 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 986 PetscInt pStart, pEnd, p, dof; 987 988 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 989 for (p = pStart; p < pEnd; ++p) { 990 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 991 if (dof) { 992 bs = dof; 993 break; 994 } 995 } 996 } else { 997 bs = 1; 998 } 999 /* Must have same blocksize on all procs (some might have no points) */ 1000 bsLocal = bs; 1001 ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1002 } 1003 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1004 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1005 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1006 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1007 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1008 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1009 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1010 } 1011 PetscFunctionReturn(0); 1012 } 1013 1014 #undef __FUNCT__ 1015 #define __FUNCT__ "DMPlexGetDimension" 1016 /*@ 1017 DMPlexGetDimension - Return the topological mesh dimension 1018 1019 Not collective 1020 1021 Input Parameter: 1022 . mesh - The DMPlex 1023 1024 Output Parameter: 1025 . dim - The topological mesh dimension 1026 1027 Level: beginner 1028 1029 .seealso: DMPlexCreate() 1030 @*/ 1031 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1032 { 1033 DM_Plex *mesh = (DM_Plex *) dm->data; 1034 1035 PetscFunctionBegin; 1036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1037 PetscValidPointer(dim, 2); 1038 *dim = mesh->dim; 1039 PetscFunctionReturn(0); 1040 } 1041 1042 #undef __FUNCT__ 1043 #define __FUNCT__ "DMPlexSetDimension" 1044 /*@ 1045 DMPlexSetDimension - Set the topological mesh dimension 1046 1047 Collective on mesh 1048 1049 Input Parameters: 1050 + mesh - The DMPlex 1051 - dim - The topological mesh dimension 1052 1053 Level: beginner 1054 1055 .seealso: DMPlexCreate() 1056 @*/ 1057 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1058 { 1059 DM_Plex *mesh = (DM_Plex *) dm->data; 1060 1061 PetscFunctionBegin; 1062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1063 PetscValidLogicalCollectiveInt(dm, dim, 2); 1064 mesh->dim = dim; 1065 mesh->preallocCenterDim = dim; 1066 PetscFunctionReturn(0); 1067 } 1068 1069 #undef __FUNCT__ 1070 #define __FUNCT__ "DMPlexGetChart" 1071 /*@ 1072 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1073 1074 Not collective 1075 1076 Input Parameter: 1077 . mesh - The DMPlex 1078 1079 Output Parameters: 1080 + pStart - The first mesh point 1081 - pEnd - The upper bound for mesh points 1082 1083 Level: beginner 1084 1085 .seealso: DMPlexCreate(), DMPlexSetChart() 1086 @*/ 1087 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1088 { 1089 DM_Plex *mesh = (DM_Plex *) dm->data; 1090 PetscErrorCode ierr; 1091 1092 PetscFunctionBegin; 1093 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1094 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1095 PetscFunctionReturn(0); 1096 } 1097 1098 #undef __FUNCT__ 1099 #define __FUNCT__ "DMPlexSetChart" 1100 /*@ 1101 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1102 1103 Not collective 1104 1105 Input Parameters: 1106 + mesh - The DMPlex 1107 . pStart - The first mesh point 1108 - pEnd - The upper bound for mesh points 1109 1110 Output Parameters: 1111 1112 Level: beginner 1113 1114 .seealso: DMPlexCreate(), DMPlexGetChart() 1115 @*/ 1116 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1117 { 1118 DM_Plex *mesh = (DM_Plex *) dm->data; 1119 PetscErrorCode ierr; 1120 1121 PetscFunctionBegin; 1122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1123 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1124 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1125 PetscFunctionReturn(0); 1126 } 1127 1128 #undef __FUNCT__ 1129 #define __FUNCT__ "DMPlexGetConeSize" 1130 /*@ 1131 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1132 1133 Not collective 1134 1135 Input Parameters: 1136 + mesh - The DMPlex 1137 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1138 1139 Output Parameter: 1140 . size - The cone size for point p 1141 1142 Level: beginner 1143 1144 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1145 @*/ 1146 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1147 { 1148 DM_Plex *mesh = (DM_Plex *) dm->data; 1149 PetscErrorCode ierr; 1150 1151 PetscFunctionBegin; 1152 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1153 PetscValidPointer(size, 3); 1154 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1155 PetscFunctionReturn(0); 1156 } 1157 1158 #undef __FUNCT__ 1159 #define __FUNCT__ "DMPlexSetConeSize" 1160 /*@ 1161 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1162 1163 Not collective 1164 1165 Input Parameters: 1166 + mesh - The DMPlex 1167 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1168 - size - The cone size for point p 1169 1170 Output Parameter: 1171 1172 Note: 1173 This should be called after DMPlexSetChart(). 1174 1175 Level: beginner 1176 1177 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1178 @*/ 1179 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1180 { 1181 DM_Plex *mesh = (DM_Plex *) dm->data; 1182 PetscErrorCode ierr; 1183 1184 PetscFunctionBegin; 1185 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1186 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1187 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1188 PetscFunctionReturn(0); 1189 } 1190 1191 #undef __FUNCT__ 1192 #define __FUNCT__ "DMPlexGetCone" 1193 /*@C 1194 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1195 1196 Not collective 1197 1198 Input Parameters: 1199 + mesh - The DMPlex 1200 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1201 1202 Output Parameter: 1203 . cone - An array of points which are on the in-edges for point p 1204 1205 Level: beginner 1206 1207 Note: 1208 This routine is not available in Fortran. 1209 1210 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1211 @*/ 1212 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1213 { 1214 DM_Plex *mesh = (DM_Plex *) dm->data; 1215 PetscInt off; 1216 PetscErrorCode ierr; 1217 1218 PetscFunctionBegin; 1219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1220 PetscValidPointer(cone, 3); 1221 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1222 *cone = &mesh->cones[off]; 1223 PetscFunctionReturn(0); 1224 } 1225 1226 #undef __FUNCT__ 1227 #define __FUNCT__ "DMPlexSetCone" 1228 /*@ 1229 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1230 1231 Not collective 1232 1233 Input Parameters: 1234 + mesh - The DMPlex 1235 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1236 - cone - An array of points which are on the in-edges for point p 1237 1238 Output Parameter: 1239 1240 Note: 1241 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1242 1243 Level: beginner 1244 1245 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1246 @*/ 1247 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1248 { 1249 DM_Plex *mesh = (DM_Plex *) dm->data; 1250 PetscInt pStart, pEnd; 1251 PetscInt dof, off, c; 1252 PetscErrorCode ierr; 1253 1254 PetscFunctionBegin; 1255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1256 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1257 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1258 if (dof) PetscValidPointer(cone, 3); 1259 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1260 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1261 for (c = 0; c < dof; ++c) { 1262 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1263 mesh->cones[off+c] = cone[c]; 1264 } 1265 PetscFunctionReturn(0); 1266 } 1267 1268 #undef __FUNCT__ 1269 #define __FUNCT__ "DMPlexGetConeOrientation" 1270 /*@C 1271 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1272 1273 Not collective 1274 1275 Input Parameters: 1276 + mesh - The DMPlex 1277 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1278 1279 Output Parameter: 1280 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1281 integer giving the prescription for cone traversal. If it is negative, the cone is 1282 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1283 the index of the cone point on which to start. 1284 1285 Level: beginner 1286 1287 Note: 1288 This routine is not available in Fortran. 1289 1290 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1291 @*/ 1292 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1293 { 1294 DM_Plex *mesh = (DM_Plex *) dm->data; 1295 PetscInt off; 1296 PetscErrorCode ierr; 1297 1298 PetscFunctionBegin; 1299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1300 #if defined(PETSC_USE_DEBUG) 1301 { 1302 PetscInt dof; 1303 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1304 if (dof) PetscValidPointer(coneOrientation, 3); 1305 } 1306 #endif 1307 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1308 *coneOrientation = &mesh->coneOrientations[off]; 1309 PetscFunctionReturn(0); 1310 } 1311 1312 #undef __FUNCT__ 1313 #define __FUNCT__ "DMPlexSetConeOrientation" 1314 /*@ 1315 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1316 1317 Not collective 1318 1319 Input Parameters: 1320 + mesh - The DMPlex 1321 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1322 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1323 integer giving the prescription for cone traversal. If it is negative, the cone is 1324 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1325 the index of the cone point on which to start. 1326 1327 Output Parameter: 1328 1329 Note: 1330 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1331 1332 Level: beginner 1333 1334 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1335 @*/ 1336 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1337 { 1338 DM_Plex *mesh = (DM_Plex *) dm->data; 1339 PetscInt pStart, pEnd; 1340 PetscInt dof, off, c; 1341 PetscErrorCode ierr; 1342 1343 PetscFunctionBegin; 1344 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1345 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1346 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1347 if (dof) PetscValidPointer(coneOrientation, 3); 1348 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1349 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); 1350 for (c = 0; c < dof; ++c) { 1351 PetscInt cdof, o = coneOrientation[c]; 1352 1353 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1354 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); 1355 mesh->coneOrientations[off+c] = o; 1356 } 1357 PetscFunctionReturn(0); 1358 } 1359 1360 #undef __FUNCT__ 1361 #define __FUNCT__ "DMPlexInsertCone" 1362 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1363 { 1364 DM_Plex *mesh = (DM_Plex *) dm->data; 1365 PetscInt pStart, pEnd; 1366 PetscInt dof, off; 1367 PetscErrorCode ierr; 1368 1369 PetscFunctionBegin; 1370 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1371 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1372 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1373 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1374 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); 1375 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); 1376 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); 1377 mesh->cones[off+conePos] = conePoint; 1378 PetscFunctionReturn(0); 1379 } 1380 1381 #undef __FUNCT__ 1382 #define __FUNCT__ "DMPlexGetSupportSize" 1383 /*@ 1384 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1385 1386 Not collective 1387 1388 Input Parameters: 1389 + mesh - The DMPlex 1390 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1391 1392 Output Parameter: 1393 . size - The support size for point p 1394 1395 Level: beginner 1396 1397 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1398 @*/ 1399 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1400 { 1401 DM_Plex *mesh = (DM_Plex *) dm->data; 1402 PetscErrorCode ierr; 1403 1404 PetscFunctionBegin; 1405 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1406 PetscValidPointer(size, 3); 1407 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1408 PetscFunctionReturn(0); 1409 } 1410 1411 #undef __FUNCT__ 1412 #define __FUNCT__ "DMPlexSetSupportSize" 1413 /*@ 1414 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1415 1416 Not collective 1417 1418 Input Parameters: 1419 + mesh - The DMPlex 1420 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1421 - size - The support size for point p 1422 1423 Output Parameter: 1424 1425 Note: 1426 This should be called after DMPlexSetChart(). 1427 1428 Level: beginner 1429 1430 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1431 @*/ 1432 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1433 { 1434 DM_Plex *mesh = (DM_Plex *) dm->data; 1435 PetscErrorCode ierr; 1436 1437 PetscFunctionBegin; 1438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1439 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1440 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1441 PetscFunctionReturn(0); 1442 } 1443 1444 #undef __FUNCT__ 1445 #define __FUNCT__ "DMPlexGetSupport" 1446 /*@C 1447 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1448 1449 Not collective 1450 1451 Input Parameters: 1452 + mesh - The DMPlex 1453 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1454 1455 Output Parameter: 1456 . support - An array of points which are on the out-edges for point p 1457 1458 Level: beginner 1459 1460 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1461 @*/ 1462 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1463 { 1464 DM_Plex *mesh = (DM_Plex *) dm->data; 1465 PetscInt off; 1466 PetscErrorCode ierr; 1467 1468 PetscFunctionBegin; 1469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1470 PetscValidPointer(support, 3); 1471 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1472 *support = &mesh->supports[off]; 1473 PetscFunctionReturn(0); 1474 } 1475 1476 #undef __FUNCT__ 1477 #define __FUNCT__ "DMPlexSetSupport" 1478 /*@ 1479 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1480 1481 Not collective 1482 1483 Input Parameters: 1484 + mesh - The DMPlex 1485 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1486 - support - An array of points which are on the in-edges for point p 1487 1488 Output Parameter: 1489 1490 Note: 1491 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1492 1493 Level: beginner 1494 1495 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1496 @*/ 1497 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1498 { 1499 DM_Plex *mesh = (DM_Plex *) dm->data; 1500 PetscInt pStart, pEnd; 1501 PetscInt dof, off, c; 1502 PetscErrorCode ierr; 1503 1504 PetscFunctionBegin; 1505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1506 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1507 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1508 if (dof) PetscValidPointer(support, 3); 1509 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1510 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); 1511 for (c = 0; c < dof; ++c) { 1512 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); 1513 mesh->supports[off+c] = support[c]; 1514 } 1515 PetscFunctionReturn(0); 1516 } 1517 1518 #undef __FUNCT__ 1519 #define __FUNCT__ "DMPlexInsertSupport" 1520 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1521 { 1522 DM_Plex *mesh = (DM_Plex *) dm->data; 1523 PetscInt pStart, pEnd; 1524 PetscInt dof, off; 1525 PetscErrorCode ierr; 1526 1527 PetscFunctionBegin; 1528 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1529 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1530 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1531 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1532 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); 1533 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); 1534 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); 1535 mesh->supports[off+supportPos] = supportPoint; 1536 PetscFunctionReturn(0); 1537 } 1538 1539 #undef __FUNCT__ 1540 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1541 /*@C 1542 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1543 1544 Not collective 1545 1546 Input Parameters: 1547 + mesh - The DMPlex 1548 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1549 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1550 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1551 1552 Output Parameters: 1553 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1554 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1555 1556 Note: 1557 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1558 1559 Level: beginner 1560 1561 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1562 @*/ 1563 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1564 { 1565 DM_Plex *mesh = (DM_Plex *) dm->data; 1566 PetscInt *closure, *fifo; 1567 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1568 PetscInt tmpSize, t; 1569 PetscInt depth = 0, maxSize; 1570 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1571 PetscErrorCode ierr; 1572 1573 PetscFunctionBegin; 1574 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1575 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1576 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1577 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1578 if (*points) { 1579 closure = *points; 1580 } else { 1581 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1582 } 1583 closure[0] = p; closure[1] = 0; 1584 /* This is only 1-level */ 1585 if (useCone) { 1586 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1587 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1588 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1589 } else { 1590 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1591 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1592 } 1593 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1594 const PetscInt cp = tmp[t]; 1595 const PetscInt co = tmpO ? tmpO[t] : 0; 1596 1597 closure[closureSize] = cp; 1598 closure[closureSize+1] = co; 1599 fifo[fifoSize] = cp; 1600 fifo[fifoSize+1] = co; 1601 } 1602 while (fifoSize - fifoStart) { 1603 const PetscInt q = fifo[fifoStart]; 1604 const PetscInt o = fifo[fifoStart+1]; 1605 const PetscInt rev = o >= 0 ? 0 : 1; 1606 const PetscInt off = rev ? -(o+1) : o; 1607 1608 if (useCone) { 1609 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1610 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1611 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1612 } else { 1613 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1614 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1615 tmpO = PETSC_NULL; 1616 } 1617 for (t = 0; t < tmpSize; ++t) { 1618 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1619 const PetscInt cp = tmp[i]; 1620 /* Must propogate orientation */ 1621 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1622 PetscInt c; 1623 1624 /* Check for duplicate */ 1625 for (c = 0; c < closureSize; c += 2) { 1626 if (closure[c] == cp) break; 1627 } 1628 if (c == closureSize) { 1629 closure[closureSize] = cp; 1630 closure[closureSize+1] = co; 1631 fifo[fifoSize] = cp; 1632 fifo[fifoSize+1] = co; 1633 closureSize += 2; 1634 fifoSize += 2; 1635 } 1636 } 1637 fifoStart += 2; 1638 } 1639 if (numPoints) *numPoints = closureSize/2; 1640 if (points) *points = closure; 1641 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1642 PetscFunctionReturn(0); 1643 } 1644 1645 #undef __FUNCT__ 1646 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1647 /*@C 1648 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1649 1650 Not collective 1651 1652 Input Parameters: 1653 + mesh - The DMPlex 1654 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1655 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1656 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1657 1658 Output Parameters: 1659 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1660 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1661 1662 Note: 1663 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1664 1665 Level: beginner 1666 1667 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1668 @*/ 1669 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1670 { 1671 PetscErrorCode ierr; 1672 1673 PetscFunctionBegin; 1674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1675 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1676 PetscFunctionReturn(0); 1677 } 1678 1679 #undef __FUNCT__ 1680 #define __FUNCT__ "DMPlexGetFaces" 1681 /* 1682 DMPlexGetFaces - 1683 1684 Note: This will only work for cell-vertex meshes. 1685 */ 1686 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1687 { 1688 DM_Plex *mesh = (DM_Plex *) dm->data; 1689 const PetscInt *cone = PETSC_NULL; 1690 PetscInt depth = 0, dim, coneSize; 1691 PetscErrorCode ierr; 1692 1693 PetscFunctionBegin; 1694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1695 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1696 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1697 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1698 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1699 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1700 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1701 switch (dim) { 1702 case 2: 1703 switch (coneSize) { 1704 case 3: 1705 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1706 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1707 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1708 *numFaces = 3; 1709 *faceSize = 2; 1710 *faces = mesh->facesTmp; 1711 break; 1712 case 4: 1713 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1714 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1715 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1716 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1717 *numFaces = 4; 1718 *faceSize = 2; 1719 *faces = mesh->facesTmp; 1720 break; 1721 default: 1722 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1723 } 1724 break; 1725 case 3: 1726 switch (coneSize) { 1727 case 3: 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[0]; 1731 *numFaces = 3; 1732 *faceSize = 2; 1733 *faces = mesh->facesTmp; 1734 break; 1735 case 4: 1736 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1737 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1738 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1739 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1740 *numFaces = 4; 1741 *faceSize = 3; 1742 *faces = mesh->facesTmp; 1743 break; 1744 default: 1745 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1746 } 1747 break; 1748 default: 1749 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1750 } 1751 PetscFunctionReturn(0); 1752 } 1753 1754 #undef __FUNCT__ 1755 #define __FUNCT__ "DMPlexGetMaxSizes" 1756 /*@ 1757 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1758 1759 Not collective 1760 1761 Input Parameter: 1762 . mesh - The DMPlex 1763 1764 Output Parameters: 1765 + maxConeSize - The maximum number of in-edges 1766 - maxSupportSize - The maximum number of out-edges 1767 1768 Level: beginner 1769 1770 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1771 @*/ 1772 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1773 { 1774 DM_Plex *mesh = (DM_Plex *) dm->data; 1775 1776 PetscFunctionBegin; 1777 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1778 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1779 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1780 PetscFunctionReturn(0); 1781 } 1782 1783 #undef __FUNCT__ 1784 #define __FUNCT__ "DMSetUp_Plex" 1785 PetscErrorCode DMSetUp_Plex(DM dm) 1786 { 1787 DM_Plex *mesh = (DM_Plex *) dm->data; 1788 PetscInt size; 1789 PetscErrorCode ierr; 1790 1791 PetscFunctionBegin; 1792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1793 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1794 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1795 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1796 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1797 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1798 if (mesh->maxSupportSize) { 1799 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1800 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1801 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1802 } 1803 PetscFunctionReturn(0); 1804 } 1805 1806 #undef __FUNCT__ 1807 #define __FUNCT__ "DMCreateSubDM_Plex" 1808 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1809 { 1810 PetscSection section, sectionGlobal; 1811 PetscInt *subIndices; 1812 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1813 PetscErrorCode ierr; 1814 1815 PetscFunctionBegin; 1816 if (!numFields) PetscFunctionReturn(0); 1817 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1818 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1819 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1820 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1821 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1822 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); 1823 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1824 for (p = pStart; p < pEnd; ++p) { 1825 PetscInt gdof; 1826 1827 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1828 if (gdof > 0) { 1829 for (f = 0; f < numFields; ++f) { 1830 PetscInt fdof, fcdof; 1831 1832 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1833 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1834 subSize += fdof-fcdof; 1835 } 1836 } 1837 } 1838 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1839 for (p = pStart; p < pEnd; ++p) { 1840 PetscInt gdof, goff; 1841 1842 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1843 if (gdof > 0) { 1844 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1845 for (f = 0; f < numFields; ++f) { 1846 PetscInt fdof, fcdof, fc, f2, poff = 0; 1847 1848 /* Can get rid of this loop by storing field information in the global section */ 1849 for (f2 = 0; f2 < fields[f]; ++f2) { 1850 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1851 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1852 poff += fdof-fcdof; 1853 } 1854 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1855 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1856 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1857 subIndices[subOff] = goff+poff+fc; 1858 } 1859 } 1860 } 1861 } 1862 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1863 if (subdm) { 1864 PetscSection subsection; 1865 PetscBool haveNull = PETSC_FALSE; 1866 PetscInt f, nf = 0; 1867 1868 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1869 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1870 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1871 for (f = 0; f < numFields; ++f) { 1872 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1873 if ((*subdm)->nullspaceConstructors[f]) { 1874 haveNull = PETSC_TRUE; 1875 nf = f; 1876 } 1877 } 1878 if (haveNull) { 1879 MatNullSpace nullSpace; 1880 1881 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1882 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1883 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1884 } 1885 if (dm->fields) { 1886 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); 1887 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1888 for (f = 0; f < numFields; ++f) { 1889 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1890 } 1891 if (numFields == 1) { 1892 MatNullSpace space; 1893 Mat pmat; 1894 1895 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr); 1896 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1897 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr); 1898 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1899 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr); 1900 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1901 } 1902 } 1903 } 1904 PetscFunctionReturn(0); 1905 } 1906 1907 #undef __FUNCT__ 1908 #define __FUNCT__ "DMPlexSymmetrize" 1909 /*@ 1910 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1911 1912 Not collective 1913 1914 Input Parameter: 1915 . mesh - The DMPlex 1916 1917 Output Parameter: 1918 1919 Note: 1920 This should be called after all calls to DMPlexSetCone() 1921 1922 Level: beginner 1923 1924 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1925 @*/ 1926 PetscErrorCode DMPlexSymmetrize(DM dm) 1927 { 1928 DM_Plex *mesh = (DM_Plex *) dm->data; 1929 PetscInt *offsets; 1930 PetscInt supportSize; 1931 PetscInt pStart, pEnd, p; 1932 PetscErrorCode ierr; 1933 1934 PetscFunctionBegin; 1935 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1936 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1937 /* Calculate support sizes */ 1938 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1939 for (p = pStart; p < pEnd; ++p) { 1940 PetscInt dof, off, c; 1941 1942 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1943 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1944 for (c = off; c < off+dof; ++c) { 1945 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1946 } 1947 } 1948 for (p = pStart; p < pEnd; ++p) { 1949 PetscInt dof; 1950 1951 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1952 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1953 } 1954 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1955 /* Calculate supports */ 1956 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1957 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1958 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1959 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1960 for (p = pStart; p < pEnd; ++p) { 1961 PetscInt dof, off, c; 1962 1963 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1964 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1965 for (c = off; c < off+dof; ++c) { 1966 const PetscInt q = mesh->cones[c]; 1967 PetscInt offS; 1968 1969 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1970 mesh->supports[offS+offsets[q]] = p; 1971 ++offsets[q]; 1972 } 1973 } 1974 ierr = PetscFree(offsets);CHKERRQ(ierr); 1975 PetscFunctionReturn(0); 1976 } 1977 1978 #undef __FUNCT__ 1979 #define __FUNCT__ "DMPlexSetDepth_Private" 1980 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1981 { 1982 PetscInt d; 1983 PetscErrorCode ierr; 1984 1985 PetscFunctionBegin; 1986 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1987 if (d < 0) { 1988 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1989 const PetscInt *cone = PETSC_NULL; 1990 PetscInt dCone; 1991 1992 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1993 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1994 d = dCone+1; 1995 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1996 } 1997 *depth = d; 1998 PetscFunctionReturn(0); 1999 } 2000 2001 #undef __FUNCT__ 2002 #define __FUNCT__ "DMPlexStratify" 2003 /*@ 2004 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2005 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2006 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2007 the DAG. 2008 2009 Not collective 2010 2011 Input Parameter: 2012 . mesh - The DMPlex 2013 2014 Output Parameter: 2015 2016 Notes: 2017 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2018 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2019 2020 This should be called after all calls to DMPlexSymmetrize() 2021 2022 Level: beginner 2023 2024 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2025 @*/ 2026 PetscErrorCode DMPlexStratify(DM dm) 2027 { 2028 DM_Plex *mesh = (DM_Plex *) dm->data; 2029 PetscInt pStart, pEnd, p; 2030 PetscInt numRoots = 0, numLeaves = 0; 2031 PetscErrorCode ierr; 2032 2033 PetscFunctionBegin; 2034 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2035 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2036 /* Calculate depth */ 2037 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2038 /* Initialize roots and count leaves */ 2039 for (p = pStart; p < pEnd; ++p) { 2040 PetscInt coneSize, supportSize; 2041 2042 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2043 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2044 if (!coneSize && supportSize) { 2045 ++numRoots; 2046 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2047 } else if (!supportSize && coneSize) { 2048 ++numLeaves; 2049 } else if (!supportSize && !coneSize) { 2050 /* Isolated points */ 2051 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2052 } 2053 } 2054 if (numRoots + numLeaves == (pEnd - pStart)) { 2055 for (p = pStart; p < pEnd; ++p) { 2056 PetscInt coneSize, supportSize; 2057 2058 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2059 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2060 if (!supportSize && coneSize) { 2061 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2062 } 2063 } 2064 } else { 2065 /* This might be slow since lookup is not fast */ 2066 for (p = pStart; p < pEnd; ++p) { 2067 PetscInt depth; 2068 2069 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2070 } 2071 } 2072 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2073 PetscFunctionReturn(0); 2074 } 2075 2076 #undef __FUNCT__ 2077 #define __FUNCT__ "DMPlexGetJoin" 2078 /*@C 2079 DMPlexGetJoin - Get an array for the join of the set of points 2080 2081 Not Collective 2082 2083 Input Parameters: 2084 + dm - The DMPlex object 2085 . numPoints - The number of input points for the join 2086 - points - The input points 2087 2088 Output Parameters: 2089 + numCoveredPoints - The number of points in the join 2090 - coveredPoints - The points in the join 2091 2092 Level: intermediate 2093 2094 Note: Currently, this is restricted to a single level join 2095 2096 .keywords: mesh 2097 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2098 @*/ 2099 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2100 { 2101 DM_Plex *mesh = (DM_Plex *) dm->data; 2102 PetscInt *join[2]; 2103 PetscInt joinSize, i = 0; 2104 PetscInt dof, off, p, c, m; 2105 PetscErrorCode ierr; 2106 2107 PetscFunctionBegin; 2108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2109 PetscValidPointer(points, 2); 2110 PetscValidPointer(numCoveredPoints, 3); 2111 PetscValidPointer(coveredPoints, 4); 2112 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2113 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2114 /* Copy in support of first point */ 2115 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2116 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2117 for (joinSize = 0; joinSize < dof; ++joinSize) { 2118 join[i][joinSize] = mesh->supports[off+joinSize]; 2119 } 2120 /* Check each successive support */ 2121 for (p = 1; p < numPoints; ++p) { 2122 PetscInt newJoinSize = 0; 2123 2124 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2125 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2126 for (c = 0; c < dof; ++c) { 2127 const PetscInt point = mesh->supports[off+c]; 2128 2129 for (m = 0; m < joinSize; ++m) { 2130 if (point == join[i][m]) { 2131 join[1-i][newJoinSize++] = point; 2132 break; 2133 } 2134 } 2135 } 2136 joinSize = newJoinSize; 2137 i = 1-i; 2138 } 2139 *numCoveredPoints = joinSize; 2140 *coveredPoints = join[i]; 2141 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2142 PetscFunctionReturn(0); 2143 } 2144 2145 #undef __FUNCT__ 2146 #define __FUNCT__ "DMPlexRestoreJoin" 2147 /*@C 2148 DMPlexRestoreJoin - Restore an array for the join of the set of points 2149 2150 Not Collective 2151 2152 Input Parameters: 2153 + dm - The DMPlex object 2154 . numPoints - The number of input points for the join 2155 - points - The input points 2156 2157 Output Parameters: 2158 + numCoveredPoints - The number of points in the join 2159 - coveredPoints - The points in the join 2160 2161 Level: intermediate 2162 2163 .keywords: mesh 2164 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2165 @*/ 2166 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2167 { 2168 PetscErrorCode ierr; 2169 2170 PetscFunctionBegin; 2171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2172 PetscValidPointer(coveredPoints, 4); 2173 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2174 PetscFunctionReturn(0); 2175 } 2176 2177 #undef __FUNCT__ 2178 #define __FUNCT__ "DMPlexGetFullJoin" 2179 /*@C 2180 DMPlexGetFullJoin - Get an array for the join of the set of points 2181 2182 Not Collective 2183 2184 Input Parameters: 2185 + dm - The DMPlex object 2186 . numPoints - The number of input points for the join 2187 - points - The input points 2188 2189 Output Parameters: 2190 + numCoveredPoints - The number of points in the join 2191 - coveredPoints - The points in the join 2192 2193 Level: intermediate 2194 2195 .keywords: mesh 2196 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2197 @*/ 2198 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2199 { 2200 DM_Plex *mesh = (DM_Plex *) dm->data; 2201 PetscInt *offsets, **closures; 2202 PetscInt *join[2]; 2203 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2204 PetscInt p, d, c, m; 2205 PetscErrorCode ierr; 2206 2207 PetscFunctionBegin; 2208 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2209 PetscValidPointer(points, 2); 2210 PetscValidPointer(numCoveredPoints, 3); 2211 PetscValidPointer(coveredPoints, 4); 2212 2213 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2214 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2215 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2216 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2217 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2218 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2219 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2220 2221 for (p = 0; p < numPoints; ++p) { 2222 PetscInt closureSize; 2223 2224 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2225 offsets[p*(depth+2)+0] = 0; 2226 for (d = 0; d < depth+1; ++d) { 2227 PetscInt pStart, pEnd, i; 2228 2229 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2230 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2231 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2232 offsets[p*(depth+2)+d+1] = i; 2233 break; 2234 } 2235 } 2236 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2237 } 2238 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); 2239 } 2240 for (d = 0; d < depth+1; ++d) { 2241 PetscInt dof; 2242 2243 /* Copy in support of first point */ 2244 dof = offsets[d+1] - offsets[d]; 2245 for (joinSize = 0; joinSize < dof; ++joinSize) { 2246 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2247 } 2248 /* Check each successive cone */ 2249 for (p = 1; p < numPoints && joinSize; ++p) { 2250 PetscInt newJoinSize = 0; 2251 2252 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2253 for (c = 0; c < dof; ++c) { 2254 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2255 2256 for (m = 0; m < joinSize; ++m) { 2257 if (point == join[i][m]) { 2258 join[1-i][newJoinSize++] = point; 2259 break; 2260 } 2261 } 2262 } 2263 joinSize = newJoinSize; 2264 i = 1-i; 2265 } 2266 if (joinSize) break; 2267 } 2268 *numCoveredPoints = joinSize; 2269 *coveredPoints = join[i]; 2270 for (p = 0; p < numPoints; ++p) { 2271 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2272 } 2273 ierr = PetscFree(closures);CHKERRQ(ierr); 2274 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2275 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2276 PetscFunctionReturn(0); 2277 } 2278 2279 #undef __FUNCT__ 2280 #define __FUNCT__ "DMPlexGetMeet" 2281 /*@C 2282 DMPlexGetMeet - Get an array for the meet of the set of points 2283 2284 Not Collective 2285 2286 Input Parameters: 2287 + dm - The DMPlex object 2288 . numPoints - The number of input points for the meet 2289 - points - The input points 2290 2291 Output Parameters: 2292 + numCoveredPoints - The number of points in the meet 2293 - coveredPoints - The points in the meet 2294 2295 Level: intermediate 2296 2297 Note: Currently, this is restricted to a single level meet 2298 2299 .keywords: mesh 2300 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2301 @*/ 2302 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2303 { 2304 DM_Plex *mesh = (DM_Plex *) dm->data; 2305 PetscInt *meet[2]; 2306 PetscInt meetSize, i = 0; 2307 PetscInt dof, off, p, c, m; 2308 PetscErrorCode ierr; 2309 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2312 PetscValidPointer(points, 2); 2313 PetscValidPointer(numCoveringPoints, 3); 2314 PetscValidPointer(coveringPoints, 4); 2315 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2316 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2317 /* Copy in cone of first point */ 2318 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2319 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2320 for (meetSize = 0; meetSize < dof; ++meetSize) { 2321 meet[i][meetSize] = mesh->cones[off+meetSize]; 2322 } 2323 /* Check each successive cone */ 2324 for (p = 1; p < numPoints; ++p) { 2325 PetscInt newMeetSize = 0; 2326 2327 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2328 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2329 for (c = 0; c < dof; ++c) { 2330 const PetscInt point = mesh->cones[off+c]; 2331 2332 for (m = 0; m < meetSize; ++m) { 2333 if (point == meet[i][m]) { 2334 meet[1-i][newMeetSize++] = point; 2335 break; 2336 } 2337 } 2338 } 2339 meetSize = newMeetSize; 2340 i = 1-i; 2341 } 2342 *numCoveringPoints = meetSize; 2343 *coveringPoints = meet[i]; 2344 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2345 PetscFunctionReturn(0); 2346 } 2347 2348 #undef __FUNCT__ 2349 #define __FUNCT__ "DMPlexRestoreMeet" 2350 /*@C 2351 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2352 2353 Not Collective 2354 2355 Input Parameters: 2356 + dm - The DMPlex object 2357 . numPoints - The number of input points for the meet 2358 - points - The input points 2359 2360 Output Parameters: 2361 + numCoveredPoints - The number of points in the meet 2362 - coveredPoints - The points in the meet 2363 2364 Level: intermediate 2365 2366 .keywords: mesh 2367 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2368 @*/ 2369 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2370 { 2371 PetscErrorCode ierr; 2372 2373 PetscFunctionBegin; 2374 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2375 PetscValidPointer(coveredPoints, 4); 2376 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2377 PetscFunctionReturn(0); 2378 } 2379 2380 #undef __FUNCT__ 2381 #define __FUNCT__ "DMPlexGetFullMeet" 2382 /*@C 2383 DMPlexGetFullMeet - Get an array for the meet of the set of points 2384 2385 Not Collective 2386 2387 Input Parameters: 2388 + dm - The DMPlex object 2389 . numPoints - The number of input points for the meet 2390 - points - The input points 2391 2392 Output Parameters: 2393 + numCoveredPoints - The number of points in the meet 2394 - coveredPoints - The points in the meet 2395 2396 Level: intermediate 2397 2398 .keywords: mesh 2399 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2400 @*/ 2401 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2402 { 2403 DM_Plex *mesh = (DM_Plex *) dm->data; 2404 PetscInt *offsets, **closures; 2405 PetscInt *meet[2]; 2406 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2407 PetscInt p, h, c, m; 2408 PetscErrorCode ierr; 2409 2410 PetscFunctionBegin; 2411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2412 PetscValidPointer(points, 2); 2413 PetscValidPointer(numCoveredPoints, 3); 2414 PetscValidPointer(coveredPoints, 4); 2415 2416 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2417 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2418 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2419 maxSize = PetscPowInt(mesh->maxConeSize,height); 2420 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2421 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2422 2423 for (p = 0; p < numPoints; ++p) { 2424 PetscInt closureSize; 2425 2426 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2427 offsets[p*(height+2)+0] = 0; 2428 for (h = 0; h < height+1; ++h) { 2429 PetscInt pStart, pEnd, i; 2430 2431 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2432 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2433 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2434 offsets[p*(height+2)+h+1] = i; 2435 break; 2436 } 2437 } 2438 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2439 } 2440 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); 2441 } 2442 for (h = 0; h < height+1; ++h) { 2443 PetscInt dof; 2444 2445 /* Copy in cone of first point */ 2446 dof = offsets[h+1] - offsets[h]; 2447 for (meetSize = 0; meetSize < dof; ++meetSize) { 2448 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2449 } 2450 /* Check each successive cone */ 2451 for (p = 1; p < numPoints && meetSize; ++p) { 2452 PetscInt newMeetSize = 0; 2453 2454 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2455 for (c = 0; c < dof; ++c) { 2456 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2457 2458 for (m = 0; m < meetSize; ++m) { 2459 if (point == meet[i][m]) { 2460 meet[1-i][newMeetSize++] = point; 2461 break; 2462 } 2463 } 2464 } 2465 meetSize = newMeetSize; 2466 i = 1-i; 2467 } 2468 if (meetSize) break; 2469 } 2470 *numCoveredPoints = meetSize; 2471 *coveredPoints = meet[i]; 2472 for (p = 0; p < numPoints; ++p) { 2473 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2474 } 2475 ierr = PetscFree(closures);CHKERRQ(ierr); 2476 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2477 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2478 PetscFunctionReturn(0); 2479 } 2480 2481 #undef __FUNCT__ 2482 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2483 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2484 { 2485 MPI_Comm comm = ((PetscObject) dm)->comm; 2486 PetscInt cellDim; 2487 PetscErrorCode ierr; 2488 2489 PetscFunctionBegin; 2490 PetscValidPointer(numFaceVertices,3); 2491 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2492 switch (cellDim) { 2493 case 0: 2494 *numFaceVertices = 0; 2495 break; 2496 case 1: 2497 *numFaceVertices = 1; 2498 break; 2499 case 2: 2500 switch (numCorners) { 2501 case 3: /* triangle */ 2502 *numFaceVertices = 2; /* Edge has 2 vertices */ 2503 break; 2504 case 4: /* quadrilateral */ 2505 *numFaceVertices = 2; /* Edge has 2 vertices */ 2506 break; 2507 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2508 *numFaceVertices = 3; /* Edge has 3 vertices */ 2509 break; 2510 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2511 *numFaceVertices = 3; /* Edge has 3 vertices */ 2512 break; 2513 default: 2514 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2515 } 2516 break; 2517 case 3: 2518 switch (numCorners) { 2519 case 4: /* tetradehdron */ 2520 *numFaceVertices = 3; /* Face has 3 vertices */ 2521 break; 2522 case 6: /* tet cohesive cells */ 2523 *numFaceVertices = 4; /* Face has 4 vertices */ 2524 break; 2525 case 8: /* hexahedron */ 2526 *numFaceVertices = 4; /* Face has 4 vertices */ 2527 break; 2528 case 9: /* tet cohesive Lagrange cells */ 2529 *numFaceVertices = 6; /* Face has 6 vertices */ 2530 break; 2531 case 10: /* quadratic tetrahedron */ 2532 *numFaceVertices = 6; /* Face has 6 vertices */ 2533 break; 2534 case 12: /* hex cohesive Lagrange cells */ 2535 *numFaceVertices = 6; /* Face has 6 vertices */ 2536 break; 2537 case 18: /* quadratic tet cohesive Lagrange cells */ 2538 *numFaceVertices = 6; /* Face has 6 vertices */ 2539 break; 2540 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2541 *numFaceVertices = 9; /* Face has 9 vertices */ 2542 break; 2543 default: 2544 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2545 } 2546 break; 2547 default: 2548 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2549 } 2550 PetscFunctionReturn(0); 2551 } 2552 2553 #undef __FUNCT__ 2554 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2555 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2556 { 2557 const PetscInt maxFaceCases = 30; 2558 PetscInt numFaceCases = 0; 2559 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2560 PetscInt *off, *adj; 2561 PetscInt *neighborCells, *tmpClosure; 2562 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2563 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2564 PetscErrorCode ierr; 2565 2566 PetscFunctionBegin; 2567 /* For parallel partitioning, I think you have to communicate supports */ 2568 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2569 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2570 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2571 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2572 if (cEnd - cStart == 0) { 2573 if (numVertices) *numVertices = 0; 2574 if (offsets) *offsets = PETSC_NULL; 2575 if (adjacency) *adjacency = PETSC_NULL; 2576 PetscFunctionReturn(0); 2577 } 2578 numCells = cEnd - cStart; 2579 /* Setup face recognition */ 2580 { 2581 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 */ 2582 2583 for (c = cStart; c < cEnd; ++c) { 2584 PetscInt corners; 2585 2586 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2587 if (!cornersSeen[corners]) { 2588 PetscInt nFV; 2589 2590 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2591 cornersSeen[corners] = 1; 2592 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2593 numFaceVertices[numFaceCases++] = nFV; 2594 } 2595 } 2596 } 2597 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2598 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2599 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2600 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2601 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2602 /* Count neighboring cells */ 2603 for (cell = cStart; cell < cEnd; ++cell) { 2604 PetscInt numNeighbors = maxNeighbors, n; 2605 2606 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2607 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2608 for (n = 0; n < numNeighbors; ++n) { 2609 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2610 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2611 PetscInt meetSize = 0; 2612 const PetscInt *meet = PETSC_NULL; 2613 2614 if (cellPair[0] == cellPair[1]) continue; 2615 if (!found) { 2616 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2617 if (meetSize) { 2618 PetscInt f; 2619 2620 for (f = 0; f < numFaceCases; ++f) { 2621 if (numFaceVertices[f] == meetSize) { 2622 found = PETSC_TRUE; 2623 break; 2624 } 2625 } 2626 } 2627 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2628 } 2629 if (found) { 2630 ++off[cell-cStart+1]; 2631 } 2632 } 2633 } 2634 /* Prefix sum */ 2635 for (cell = 1; cell <= numCells; ++cell) { 2636 off[cell] += off[cell-1]; 2637 } 2638 if (adjacency) { 2639 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2640 /* Get neighboring cells */ 2641 for (cell = cStart; cell < cEnd; ++cell) { 2642 PetscInt numNeighbors = maxNeighbors, n; 2643 PetscInt cellOffset = 0; 2644 2645 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2646 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2647 for (n = 0; n < numNeighbors; ++n) { 2648 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2649 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2650 PetscInt meetSize = 0; 2651 const PetscInt *meet = PETSC_NULL; 2652 2653 if (cellPair[0] == cellPair[1]) continue; 2654 if (!found) { 2655 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2656 if (meetSize) { 2657 PetscInt f; 2658 2659 for (f = 0; f < numFaceCases; ++f) { 2660 if (numFaceVertices[f] == meetSize) { 2661 found = PETSC_TRUE; 2662 break; 2663 } 2664 } 2665 } 2666 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2667 } 2668 if (found) { 2669 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2670 ++cellOffset; 2671 } 2672 } 2673 } 2674 } 2675 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2676 if (numVertices) *numVertices = numCells; 2677 if (offsets) *offsets = off; 2678 if (adjacency) *adjacency = adj; 2679 PetscFunctionReturn(0); 2680 } 2681 2682 #if defined(PETSC_HAVE_CHACO) 2683 #if defined(PETSC_HAVE_UNISTD_H) 2684 #include <unistd.h> 2685 #endif 2686 /* Chaco does not have an include file */ 2687 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2688 float *ewgts, float *x, float *y, float *z, char *outassignname, 2689 char *outfilename, short *assignment, int architecture, int ndims_tot, 2690 int mesh_dims[3], double *goal, int global_method, int local_method, 2691 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2692 2693 extern int FREE_GRAPH; 2694 2695 #undef __FUNCT__ 2696 #define __FUNCT__ "DMPlexPartition_Chaco" 2697 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2698 { 2699 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2700 MPI_Comm comm = ((PetscObject) dm)->comm; 2701 int nvtxs = numVertices; /* number of vertices in full graph */ 2702 int *vwgts = NULL; /* weights for all vertices */ 2703 float *ewgts = NULL; /* weights for all edges */ 2704 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2705 char *outassignname = NULL; /* name of assignment output file */ 2706 char *outfilename = NULL; /* output file name */ 2707 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2708 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2709 int mesh_dims[3]; /* dimensions of mesh of processors */ 2710 double *goal = NULL; /* desired set sizes for each set */ 2711 int global_method = 1; /* global partitioning algorithm */ 2712 int local_method = 1; /* local partitioning algorithm */ 2713 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2714 int vmax = 200; /* how many vertices to coarsen down to? */ 2715 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2716 double eigtol = 0.001; /* tolerance on eigenvectors */ 2717 long seed = 123636512; /* for random graph mutations */ 2718 short int *assignment; /* Output partition */ 2719 int fd_stdout, fd_pipe[2]; 2720 PetscInt *points; 2721 PetscMPIInt commSize; 2722 int i, v, p; 2723 PetscErrorCode ierr; 2724 2725 PetscFunctionBegin; 2726 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2727 if (!numVertices) { 2728 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2729 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2730 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2731 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2732 PetscFunctionReturn(0); 2733 } 2734 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2735 for (i = 0; i < start[numVertices]; ++i) { 2736 ++adjacency[i]; 2737 } 2738 if (global_method == INERTIAL_METHOD) { 2739 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2740 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2741 } 2742 mesh_dims[0] = commSize; 2743 mesh_dims[1] = 1; 2744 mesh_dims[2] = 1; 2745 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2746 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2747 /* TODO: check error codes for UNIX calls */ 2748 #if defined(PETSC_HAVE_UNISTD_H) 2749 { 2750 int piperet; 2751 piperet = pipe(fd_pipe); 2752 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2753 fd_stdout = dup(1); 2754 close(1); 2755 dup2(fd_pipe[1], 1); 2756 } 2757 #endif 2758 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2759 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2760 vmax, ndims, eigtol, seed); 2761 #if defined(PETSC_HAVE_UNISTD_H) 2762 { 2763 char msgLog[10000]; 2764 int count; 2765 2766 fflush(stdout); 2767 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2768 if (count < 0) count = 0; 2769 msgLog[count] = 0; 2770 close(1); 2771 dup2(fd_stdout, 1); 2772 close(fd_stdout); 2773 close(fd_pipe[0]); 2774 close(fd_pipe[1]); 2775 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2776 } 2777 #endif 2778 /* Convert to PetscSection+IS */ 2779 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2780 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2781 for (v = 0; v < nvtxs; ++v) { 2782 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2783 } 2784 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2785 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2786 for (p = 0, i = 0; p < commSize; ++p) { 2787 for (v = 0; v < nvtxs; ++v) { 2788 if (assignment[v] == p) points[i++] = v; 2789 } 2790 } 2791 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2792 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2793 if (global_method == INERTIAL_METHOD) { 2794 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2795 } 2796 ierr = PetscFree(assignment);CHKERRQ(ierr); 2797 for (i = 0; i < start[numVertices]; ++i) { 2798 --adjacency[i]; 2799 } 2800 PetscFunctionReturn(0); 2801 } 2802 #endif 2803 2804 #if defined(PETSC_HAVE_PARMETIS) 2805 #undef __FUNCT__ 2806 #define __FUNCT__ "DMPlexPartition_ParMetis" 2807 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2808 { 2809 PetscFunctionBegin; 2810 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2811 PetscFunctionReturn(0); 2812 } 2813 #endif 2814 2815 #undef __FUNCT__ 2816 #define __FUNCT__ "DMPlexEnlargePartition" 2817 /* Expand the partition by BFS on the adjacency graph */ 2818 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2819 { 2820 PetscHashI h; 2821 const PetscInt *points; 2822 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2823 PetscInt pStart, pEnd, part, q; 2824 PetscErrorCode ierr; 2825 2826 PetscFunctionBegin; 2827 PetscHashICreate(h); 2828 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2829 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2830 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2831 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2832 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2833 for (part = pStart; part < pEnd; ++part) { 2834 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2835 2836 PetscHashIClear(h); 2837 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2838 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2839 /* Add all existing points to h */ 2840 for (p = 0; p < numPoints; ++p) { 2841 const PetscInt point = points[off+p]; 2842 PetscHashIAdd(h, point, 1); 2843 } 2844 PetscHashISize(h, nP); 2845 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2846 /* Add all points in next BFS level */ 2847 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2848 for (p = 0; p < numPoints; ++p) { 2849 const PetscInt point = points[off+p]; 2850 PetscInt s = start[point], e = start[point+1], a; 2851 2852 for (a = s; a < e; ++a) { 2853 PetscHashIAdd(h, adjacency[a], 1); 2854 } 2855 } 2856 PetscHashISize(h, numNewPoints); 2857 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2858 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2859 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2860 totPoints += numNewPoints; 2861 } 2862 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2863 PetscHashIDestroy(h); 2864 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2865 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2866 for (part = pStart, q = 0; part < pEnd; ++part) { 2867 PetscInt numPoints, p; 2868 2869 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2870 for (p = 0; p < numPoints; ++p, ++q) { 2871 newPoints[q] = tmpPoints[part][p]; 2872 } 2873 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2874 } 2875 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2876 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2877 PetscFunctionReturn(0); 2878 } 2879 2880 #undef __FUNCT__ 2881 #define __FUNCT__ "DMPlexCreatePartition" 2882 /* 2883 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2884 2885 Collective on DM 2886 2887 Input Parameters: 2888 + dm - The DM 2889 . height - The height for points in the partition 2890 - enlarge - Expand each partition with neighbors 2891 2892 Output Parameters: 2893 + partSection - The PetscSection giving the division of points by partition 2894 . partition - The list of points by partition 2895 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2896 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2897 2898 Level: developer 2899 2900 .seealso DMPlexDistribute() 2901 */ 2902 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2903 { 2904 PetscMPIInt size; 2905 PetscErrorCode ierr; 2906 2907 PetscFunctionBegin; 2908 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2909 *origPartSection = PETSC_NULL; 2910 *origPartition = PETSC_NULL; 2911 if (size == 1) { 2912 PetscInt *points; 2913 PetscInt cStart, cEnd, c; 2914 2915 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2916 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2917 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2918 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2919 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2920 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2921 for (c = cStart; c < cEnd; ++c) { 2922 points[c] = c; 2923 } 2924 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2925 PetscFunctionReturn(0); 2926 } 2927 if (height == 0) { 2928 PetscInt numVertices; 2929 PetscInt *start = PETSC_NULL; 2930 PetscInt *adjacency = PETSC_NULL; 2931 2932 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2933 if (1) { 2934 #if defined(PETSC_HAVE_CHACO) 2935 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2936 #endif 2937 } else { 2938 #if defined(PETSC_HAVE_PARMETIS) 2939 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2940 #endif 2941 } 2942 if (enlarge) { 2943 *origPartSection = *partSection; 2944 *origPartition = *partition; 2945 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2946 } 2947 ierr = PetscFree(start);CHKERRQ(ierr); 2948 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2949 # if 0 2950 } else if (height == 1) { 2951 /* Build the dual graph for faces and partition the hypergraph */ 2952 PetscInt numEdges; 2953 2954 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2955 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2956 destroyCSR(numEdges, start, adjacency); 2957 #endif 2958 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2959 PetscFunctionReturn(0); 2960 } 2961 2962 #undef __FUNCT__ 2963 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2964 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2965 { 2966 /* const PetscInt height = 0; */ 2967 const PetscInt *partArray; 2968 PetscInt *allPoints, *partPoints = PETSC_NULL; 2969 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2970 PetscErrorCode ierr; 2971 2972 PetscFunctionBegin; 2973 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2974 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2975 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2976 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2977 for (rank = rStart; rank < rEnd; ++rank) { 2978 PetscInt partSize = 0; 2979 PetscInt numPoints, offset, p; 2980 2981 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2982 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2983 for (p = 0; p < numPoints; ++p) { 2984 PetscInt point = partArray[offset+p], closureSize, c; 2985 PetscInt *closure = PETSC_NULL; 2986 2987 /* TODO Include support for height > 0 case */ 2988 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2989 /* Merge into existing points */ 2990 if (partSize+closureSize > maxPartSize) { 2991 PetscInt *tmpPoints; 2992 2993 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2994 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2995 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2996 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2997 partPoints = tmpPoints; 2998 } 2999 for (c = 0; c < closureSize; ++c) { 3000 partPoints[partSize+c] = closure[c*2]; 3001 } 3002 partSize += closureSize; 3003 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3004 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3005 } 3006 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3007 } 3008 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3009 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3010 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3011 3012 for (rank = rStart; rank < rEnd; ++rank) { 3013 PetscInt partSize = 0, newOffset; 3014 PetscInt numPoints, offset, p; 3015 3016 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3017 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3018 for (p = 0; p < numPoints; ++p) { 3019 PetscInt point = partArray[offset+p], closureSize, c; 3020 PetscInt *closure = PETSC_NULL; 3021 3022 /* TODO Include support for height > 0 case */ 3023 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3024 /* Merge into existing points */ 3025 for (c = 0; c < closureSize; ++c) { 3026 partPoints[partSize+c] = closure[c*2]; 3027 } 3028 partSize += closureSize; 3029 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3030 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3031 } 3032 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3033 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3034 } 3035 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3036 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3037 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3038 PetscFunctionReturn(0); 3039 } 3040 3041 #undef __FUNCT__ 3042 #define __FUNCT__ "DMPlexDistributeField" 3043 /* 3044 Input Parameters: 3045 . originalSection 3046 , originalVec 3047 3048 Output Parameters: 3049 . newSection 3050 . newVec 3051 */ 3052 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3053 { 3054 PetscSF fieldSF; 3055 PetscInt *remoteOffsets, fieldSize; 3056 PetscScalar *originalValues, *newValues; 3057 PetscErrorCode ierr; 3058 3059 PetscFunctionBegin; 3060 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3061 3062 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3063 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3064 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3065 3066 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3067 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3068 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3069 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3070 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3071 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3072 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3073 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3074 PetscFunctionReturn(0); 3075 } 3076 3077 #undef __FUNCT__ 3078 #define __FUNCT__ "DMPlexDistribute" 3079 /*@C 3080 DMPlexDistribute - Distributes the mesh and any associated sections. 3081 3082 Not Collective 3083 3084 Input Parameter: 3085 + dm - The original DMPlex object 3086 . partitioner - The partitioning package, or NULL for the default 3087 - overlap - The overlap of partitions, 0 is the default 3088 3089 Output Parameter: 3090 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3091 3092 Note: If the mesh was not distributed, the return value is PETSC_NULL 3093 3094 Level: intermediate 3095 3096 .keywords: mesh, elements 3097 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3098 @*/ 3099 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3100 { 3101 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3102 MPI_Comm comm = ((PetscObject) dm)->comm; 3103 const PetscInt height = 0; 3104 PetscInt dim, numRemoteRanks; 3105 IS origCellPart, cellPart, part; 3106 PetscSection origCellPartSection, cellPartSection, partSection; 3107 PetscSFNode *remoteRanks; 3108 PetscSF partSF, pointSF, coneSF; 3109 ISLocalToGlobalMapping renumbering; 3110 PetscSection originalConeSection, newConeSection; 3111 PetscInt *remoteOffsets; 3112 PetscInt *cones, *newCones, newConesSize; 3113 PetscBool flg; 3114 PetscMPIInt rank, numProcs, p; 3115 PetscErrorCode ierr; 3116 3117 PetscFunctionBegin; 3118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3119 PetscValidPointer(dmParallel,4); 3120 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3121 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3122 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3123 *dmParallel = PETSC_NULL; 3124 if (numProcs == 1) PetscFunctionReturn(0); 3125 3126 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3127 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3128 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3129 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3130 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3131 if (!rank) { 3132 numRemoteRanks = numProcs; 3133 } else { 3134 numRemoteRanks = 0; 3135 } 3136 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3137 for (p = 0; p < numRemoteRanks; ++p) { 3138 remoteRanks[p].rank = p; 3139 remoteRanks[p].index = 0; 3140 } 3141 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3142 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3143 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3144 if (flg) { 3145 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3146 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3147 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3148 if (origCellPart) { 3149 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3150 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3151 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3152 } 3153 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3154 } 3155 /* Close the partition over the mesh */ 3156 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3157 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3158 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3159 /* Create new mesh */ 3160 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3161 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3162 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3163 pmesh = (DM_Plex *) (*dmParallel)->data; 3164 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3165 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3166 if (flg) { 3167 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3168 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3169 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3170 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3171 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3172 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3173 } 3174 /* Distribute cone section */ 3175 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3176 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3177 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3178 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3179 { 3180 PetscInt pStart, pEnd, p; 3181 3182 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3183 for (p = pStart; p < pEnd; ++p) { 3184 PetscInt coneSize; 3185 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3186 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3187 } 3188 } 3189 /* Communicate and renumber cones */ 3190 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3191 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3192 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3193 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3194 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3195 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3196 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3197 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3198 if (flg) { 3199 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3200 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3201 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3202 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3203 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3204 } 3205 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3206 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3207 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3208 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3209 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3210 /* Create supports and stratify sieve */ 3211 { 3212 PetscInt pStart, pEnd; 3213 3214 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3215 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3216 } 3217 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3218 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3219 /* Distribute Coordinates */ 3220 { 3221 PetscSection originalCoordSection, newCoordSection; 3222 Vec originalCoordinates, newCoordinates; 3223 const char *name; 3224 3225 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3226 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3227 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3228 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3229 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3230 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3231 3232 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3233 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3234 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3235 } 3236 /* Distribute labels */ 3237 { 3238 DMLabel next = mesh->labels, newNext = pmesh->labels; 3239 PetscInt numLabels = 0, l; 3240 3241 /* Bcast number of labels */ 3242 while (next) {++numLabels; next = next->next;} 3243 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3244 next = mesh->labels; 3245 for (l = 0; l < numLabels; ++l) { 3246 DMLabel newLabel; 3247 const PetscInt *partArray; 3248 char *name; 3249 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3250 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3251 PetscInt nameSize, s, p; 3252 PetscBool isdepth; 3253 size_t len = 0; 3254 3255 /* Bcast name (could filter for no points) */ 3256 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3257 nameSize = len; 3258 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3259 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3260 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3261 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3262 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3263 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3264 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3265 newLabel->name = name; 3266 /* Bcast numStrata (could filter for no points in stratum) */ 3267 if (!rank) {newLabel->numStrata = next->numStrata;} 3268 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3269 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3270 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3271 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3272 /* Bcast stratumValues (could filter for no points in stratum) */ 3273 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3274 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3275 /* Find size on each process and Scatter */ 3276 if (!rank) { 3277 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3278 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3279 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3280 for (s = 0; s < next->numStrata; ++s) { 3281 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3282 const PetscInt point = next->points[p]; 3283 PetscInt proc; 3284 3285 for (proc = 0; proc < numProcs; ++proc) { 3286 PetscInt dof, off, pPart; 3287 3288 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3289 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3290 for (pPart = off; pPart < off+dof; ++pPart) { 3291 if (partArray[pPart] == point) { 3292 ++stratumSizes[proc*next->numStrata+s]; 3293 break; 3294 } 3295 } 3296 } 3297 } 3298 } 3299 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3300 } 3301 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3302 /* Calculate stratumOffsets */ 3303 newLabel->stratumOffsets[0] = 0; 3304 for (s = 0; s < newLabel->numStrata; ++s) { 3305 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3306 } 3307 /* Pack points and Scatter */ 3308 if (!rank) { 3309 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3310 displs[0] = 0; 3311 for (p = 0; p < numProcs; ++p) { 3312 sendcnts[p] = 0; 3313 for (s = 0; s < next->numStrata; ++s) { 3314 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3315 } 3316 offsets[p] = displs[p]; 3317 displs[p+1] = displs[p] + sendcnts[p]; 3318 } 3319 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3320 for (s = 0; s < next->numStrata; ++s) { 3321 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3322 const PetscInt point = next->points[p]; 3323 PetscInt proc; 3324 3325 for (proc = 0; proc < numProcs; ++proc) { 3326 PetscInt dof, off, pPart; 3327 3328 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3329 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3330 for (pPart = off; pPart < off+dof; ++pPart) { 3331 if (partArray[pPart] == point) { 3332 points[offsets[proc]++] = point; 3333 break; 3334 } 3335 } 3336 } 3337 } 3338 } 3339 } 3340 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3341 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3342 ierr = PetscFree(points);CHKERRQ(ierr); 3343 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3344 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3345 /* Renumber points */ 3346 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3347 /* Sort points */ 3348 for (s = 0; s < newLabel->numStrata; ++s) { 3349 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3350 } 3351 /* Insert into list */ 3352 if (newNext) { 3353 newNext->next = newLabel; 3354 } else { 3355 pmesh->labels = newLabel; 3356 } 3357 newNext = newLabel; 3358 if (!rank) {next = next->next;} 3359 } 3360 } 3361 /* Cleanup Partition */ 3362 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3363 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3364 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3365 ierr = ISDestroy(&part);CHKERRQ(ierr); 3366 /* Create point SF for parallel mesh */ 3367 { 3368 const PetscInt *leaves; 3369 PetscSFNode *remotePoints, *rowners, *lowners; 3370 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3371 PetscInt pStart, pEnd; 3372 3373 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3374 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3375 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3376 for (p=0; p<numRoots; p++) { 3377 rowners[p].rank = -1; 3378 rowners[p].index = -1; 3379 } 3380 if (origCellPart) { 3381 /* Make sure cells in the original partition are not assigned to other procs */ 3382 const PetscInt *origCells; 3383 3384 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3385 for (p = 0; p < numProcs; ++p) { 3386 PetscInt dof, off, d; 3387 3388 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3389 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3390 for (d = off; d < off+dof; ++d) { 3391 rowners[origCells[d]].rank = p; 3392 } 3393 } 3394 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3395 } 3396 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3397 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3398 3399 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3400 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3401 for (p = 0; p < numLeaves; ++p) { 3402 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3403 lowners[p].rank = rank; 3404 lowners[p].index = leaves ? leaves[p] : p; 3405 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3406 lowners[p].rank = -2; 3407 lowners[p].index = -2; 3408 } 3409 } 3410 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3411 rowners[p].rank = -3; 3412 rowners[p].index = -3; 3413 } 3414 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3415 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3416 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3417 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3418 for (p = 0; p < numLeaves; ++p) { 3419 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3420 if (lowners[p].rank != rank) ++numGhostPoints; 3421 } 3422 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3423 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3424 for (p = 0, gp = 0; p < numLeaves; ++p) { 3425 if (lowners[p].rank != rank) { 3426 ghostPoints[gp] = leaves ? leaves[p] : p; 3427 remotePoints[gp].rank = lowners[p].rank; 3428 remotePoints[gp].index = lowners[p].index; 3429 ++gp; 3430 } 3431 } 3432 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3433 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3434 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3435 } 3436 /* Cleanup */ 3437 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3438 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3439 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3440 PetscFunctionReturn(0); 3441 } 3442 3443 #undef __FUNCT__ 3444 #define __FUNCT__ "DMPlexRenumber_Private" 3445 /* 3446 Reasons to renumber: 3447 3448 1) Permute points, e.g. bandwidth reduction (Renumber) 3449 3450 a) Must not mix strata 3451 3452 2) Shift numbers for point insertion (Shift) 3453 3454 a) Want operation brken into parts so that insertion can be interleaved 3455 3456 renumbering - An IS which provides the new numbering 3457 */ 3458 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3459 { 3460 PetscFunctionBegin; 3461 PetscFunctionReturn(0); 3462 } 3463 3464 #undef __FUNCT__ 3465 #define __FUNCT__ "DMPlexShiftPoint_Private" 3466 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3467 { 3468 if (depth < 0) return p; 3469 /* Cells */ if (p < depthEnd[depth]) return p; 3470 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3471 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3472 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3473 } 3474 3475 #undef __FUNCT__ 3476 #define __FUNCT__ "DMPlexShiftSizes_Private" 3477 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3478 { 3479 PetscInt *depthEnd; 3480 PetscInt depth = 0, d, pStart, pEnd, p; 3481 PetscErrorCode ierr; 3482 3483 PetscFunctionBegin; 3484 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3485 if (depth < 0) PetscFunctionReturn(0); 3486 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3487 /* Step 1: Expand chart */ 3488 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3489 for (d = 0; d <= depth; ++d) { 3490 pEnd += depthShift[d]; 3491 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3492 } 3493 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3494 /* Step 2: Set cone and support sizes */ 3495 for (d = 0; d <= depth; ++d) { 3496 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3497 for (p = pStart; p < pEnd; ++p) { 3498 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3499 PetscInt size; 3500 3501 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3502 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3503 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3504 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3505 } 3506 } 3507 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3508 PetscFunctionReturn(0); 3509 } 3510 3511 #undef __FUNCT__ 3512 #define __FUNCT__ "DMPlexShiftPoints_Private" 3513 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3514 { 3515 PetscInt *depthEnd, *newpoints; 3516 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3517 PetscErrorCode ierr; 3518 3519 PetscFunctionBegin; 3520 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3521 if (depth < 0) PetscFunctionReturn(0); 3522 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3523 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3524 for (d = 0; d <= depth; ++d) { 3525 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3526 } 3527 /* Step 5: Set cones and supports */ 3528 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3529 for (p = pStart; p < pEnd; ++p) { 3530 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3531 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3532 3533 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3534 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3535 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3536 for (i = 0; i < size; ++i) { 3537 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3538 } 3539 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3540 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3541 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3542 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3543 for (i = 0; i < size; ++i) { 3544 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3545 } 3546 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3547 } 3548 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3549 PetscFunctionReturn(0); 3550 } 3551 3552 #undef __FUNCT__ 3553 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3554 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3555 { 3556 PetscSection coordSection, newCoordSection; 3557 Vec coordinates, newCoordinates; 3558 PetscScalar *coords, *newCoords; 3559 PetscInt *depthEnd, coordSize; 3560 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3561 PetscErrorCode ierr; 3562 3563 PetscFunctionBegin; 3564 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3565 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3566 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3567 for (d = 0; d <= depth; ++d) { 3568 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3569 } 3570 /* Step 8: Convert coordinates */ 3571 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3572 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3573 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3574 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3575 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3576 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3577 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3578 for (v = vStartNew; v < vEndNew; ++v) { 3579 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3580 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3581 } 3582 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3583 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3584 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3585 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3586 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3587 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3588 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3589 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3590 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3591 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3592 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3593 for (v = vStart; v < vEnd; ++v) { 3594 PetscInt dof, off, noff, d; 3595 3596 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3597 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3598 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3599 for (d = 0; d < dof; ++d) { 3600 newCoords[noff+d] = coords[off+d]; 3601 } 3602 } 3603 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3604 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3605 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3606 PetscFunctionReturn(0); 3607 } 3608 3609 #undef __FUNCT__ 3610 #define __FUNCT__ "DMPlexShiftSF_Private" 3611 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3612 { 3613 PetscInt *depthEnd; 3614 PetscInt depth = 0, d; 3615 PetscSF sfPoint, sfPointNew; 3616 const PetscSFNode *remotePoints; 3617 PetscSFNode *gremotePoints; 3618 const PetscInt *localPoints; 3619 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3620 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3621 PetscMPIInt numProcs; 3622 PetscErrorCode ierr; 3623 3624 PetscFunctionBegin; 3625 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3626 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3627 for (d = 0; d <= depth; ++d) { 3628 totShift += depthShift[d]; 3629 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3630 } 3631 /* Step 9: Convert pointSF */ 3632 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3633 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3634 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3635 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3636 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3637 if (numRoots >= 0) { 3638 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3639 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3640 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3641 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3642 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3643 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3644 for (l = 0; l < numLeaves; ++l) { 3645 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3646 gremotePoints[l].rank = remotePoints[l].rank; 3647 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3648 } 3649 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3650 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3651 } 3652 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3653 PetscFunctionReturn(0); 3654 } 3655 3656 #undef __FUNCT__ 3657 #define __FUNCT__ "DMPlexShiftLabels_Private" 3658 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3659 { 3660 PetscSF sfPoint; 3661 DMLabel vtkLabel, ghostLabel; 3662 PetscInt *depthEnd; 3663 const PetscSFNode *leafRemote; 3664 const PetscInt *leafLocal; 3665 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3666 PetscMPIInt rank; 3667 PetscErrorCode ierr; 3668 3669 PetscFunctionBegin; 3670 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3671 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3672 for (d = 0; d <= depth; ++d) { 3673 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3674 } 3675 /* Step 10: Convert labels */ 3676 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3677 for (l = 0; l < numLabels; ++l) { 3678 DMLabel label, newlabel; 3679 const char *lname; 3680 PetscBool isDepth; 3681 IS valueIS; 3682 const PetscInt *values; 3683 PetscInt numValues, val; 3684 3685 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3686 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3687 if (isDepth) continue; 3688 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3689 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3690 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3691 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3692 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3693 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3694 for (val = 0; val < numValues; ++val) { 3695 IS pointIS; 3696 const PetscInt *points; 3697 PetscInt numPoints, p; 3698 3699 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3700 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3701 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3702 for (p = 0; p < numPoints; ++p) { 3703 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3704 3705 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3706 } 3707 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3708 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3709 } 3710 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3711 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3712 } 3713 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3714 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3715 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3716 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3717 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3718 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3719 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3720 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3721 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3722 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3723 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3724 for (; c < leafLocal[l] && c < cEnd; ++c) { 3725 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3726 } 3727 if (leafLocal[l] >= cEnd) break; 3728 if (leafRemote[l].rank == rank) { 3729 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3730 } else { 3731 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3732 } 3733 } 3734 for (; c < cEnd; ++c) { 3735 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3736 } 3737 if (0) { 3738 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3739 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3740 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3741 } 3742 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3743 for (f = fStart; f < fEnd; ++f) { 3744 PetscInt numCells; 3745 3746 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3747 if (numCells < 2) { 3748 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3749 } else { 3750 const PetscInt *cells = PETSC_NULL; 3751 PetscInt vA, vB; 3752 3753 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3754 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3755 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3756 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3757 } 3758 } 3759 if (0) { 3760 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3761 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3762 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3763 } 3764 PetscFunctionReturn(0); 3765 } 3766 3767 #undef __FUNCT__ 3768 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3769 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3770 { 3771 DMLabel label; 3772 IS valueIS; 3773 const PetscInt *values; 3774 PetscInt *depthShift; 3775 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3776 PetscErrorCode ierr; 3777 3778 PetscFunctionBegin; 3779 /* Count ghost cells */ 3780 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3781 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3782 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3783 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3784 *numGhostCells = 0; 3785 for (fs = 0; fs < numFS; ++fs) { 3786 PetscInt numBdFaces; 3787 3788 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3789 *numGhostCells += numBdFaces; 3790 } 3791 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3792 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3793 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3794 if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3795 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3796 /* Step 3: Set cone/support sizes for new points */ 3797 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3798 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3799 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3800 } 3801 for (fs = 0; fs < numFS; ++fs) { 3802 IS faceIS; 3803 const PetscInt *faces; 3804 PetscInt numFaces, f; 3805 3806 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3807 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3808 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3809 for (f = 0; f < numFaces; ++f) { 3810 PetscInt size; 3811 3812 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3813 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3814 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3815 } 3816 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3817 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3818 } 3819 /* Step 4: Setup ghosted DM */ 3820 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3821 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3822 /* Step 6: Set cones and supports for new points */ 3823 ghostCell = cEnd; 3824 for (fs = 0; fs < numFS; ++fs) { 3825 IS faceIS; 3826 const PetscInt *faces; 3827 PetscInt numFaces, f; 3828 3829 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3830 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3831 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3832 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3833 PetscInt newFace = faces[f] + *numGhostCells; 3834 3835 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3836 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3837 } 3838 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3839 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3840 } 3841 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3842 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3843 /* Step 7: Stratify */ 3844 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3845 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3846 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3847 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3848 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3849 PetscFunctionReturn(0); 3850 } 3851 3852 #undef __FUNCT__ 3853 #define __FUNCT__ "DMPlexConstructGhostCells" 3854 /*@C 3855 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3856 3857 Collective on dm 3858 3859 Input Parameters: 3860 + dm - The original DM 3861 - labelName - The label specifying the boundary faces (this could be auto-generated) 3862 3863 Output Parameters: 3864 + numGhostCells - The number of ghost cells added to the DM 3865 - dmGhosted - The new DM 3866 3867 Level: developer 3868 3869 .seealso: DMCreate() 3870 */ 3871 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3872 { 3873 DM gdm; 3874 PetscInt dim; 3875 PetscErrorCode ierr; 3876 3877 PetscFunctionBegin; 3878 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3879 PetscValidPointer(numGhostCells, 3); 3880 PetscValidPointer(dmGhosted, 4); 3881 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3882 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3883 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3884 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3885 switch (dim) { 3886 case 2: 3887 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3888 break; 3889 default: 3890 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3891 } 3892 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3893 *dmGhosted = gdm; 3894 PetscFunctionReturn(0); 3895 } 3896 3897 #undef __FUNCT__ 3898 #define __FUNCT__ "DMPlexConstructCohesiveCells_2D" 3899 PetscErrorCode DMPlexConstructCohesiveCells_2D(DM dm, const char labelName[], DM sdm) 3900 { 3901 MPI_Comm comm = ((PetscObject) dm)->comm; 3902 DMLabel label; 3903 IS valueIS, svIS = PETSC_NULL, seIS = PETSC_NULL; 3904 const PetscInt *values, *splitVertices = PETSC_NULL, *splitEdges = PETSC_NULL; 3905 PetscSection coordSection; 3906 Vec coordinates; 3907 PetscScalar *coords; 3908 PetscInt *depthShift, *depthOffset, *pMaxNew, *coneNew, *supportNew; 3909 PetscInt shift = 100, depth = 0, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numSplitVertices = 0, v, numSplitEdges = 0, numLabels, l; 3910 PetscErrorCode ierr; 3911 3912 PetscFunctionBegin; 3913 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3914 /* Count split points and add cohesive cells */ 3915 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 3916 if (label) { 3917 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3918 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3919 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3920 ierr = DMLabelGetStratumIS(label, 0, &svIS);CHKERRQ(ierr); 3921 if (svIS) { 3922 ierr = ISGetLocalSize(svIS, &numSplitVertices);CHKERRQ(ierr); 3923 ierr = ISGetIndices(svIS, &splitVertices);CHKERRQ(ierr); 3924 } 3925 ierr = DMLabelGetStratumIS(label, 1, &seIS);CHKERRQ(ierr); 3926 if (seIS) { 3927 ierr = ISGetLocalSize(seIS, &numSplitEdges);CHKERRQ(ierr); 3928 ierr = ISGetIndices(seIS, &splitEdges);CHKERRQ(ierr); 3929 } 3930 } 3931 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3932 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3933 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3934 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3935 for(d = 0; d <= depth; ++d) { 3936 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3937 } 3938 for(sp = 0; sp < numSP; ++sp) { 3939 if ((values[sp] < 0) || (values[sp] > depth)) continue; 3940 ierr = DMLabelGetStratumSize(label, values[sp], &depthShift[values[sp]]);CHKERRQ(ierr); 3941 } 3942 if (depth >= 0) { 3943 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3944 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3945 pMaxNew[0] += depthShift[depth]; 3946 if (depth > 1) {pMaxNew[1] += depthShift[depth] + depthShift[0];} 3947 if (depth > 2) {pMaxNew[2] += depthShift[depth] + depthShift[0] + depthShift[1];} 3948 depthOffset[depth] = 0; 3949 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3950 if (depth > 1) {depthOffset[1] = depthOffset[0] + depthShift[0];} 3951 if (depth > 2) {depthOffset[2] = depthOffset[1] + depthShift[1];} 3952 } 3953 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3954 /* Step 3: Set cone/support sizes for new points */ 3955 for(sp = 0; sp < numSP; ++sp) { 3956 const PetscInt dep = values[sp]; 3957 const PetscInt *points; 3958 IS dimIS; 3959 PetscInt numPoints, p; 3960 3961 if ((values[sp] < 0) || (values[sp] > depth)) continue; 3962 ierr = DMLabelGetStratumIS(label, dep, &dimIS);CHKERRQ(ierr); 3963 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 3964 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 3965 for(p = 0; p < numPoints; ++p) { 3966 const PetscInt *support; 3967 PetscInt coneSize, supportSize, q, e; 3968 3969 ierr = DMPlexGetConeSize(dm, points[p], &coneSize);CHKERRQ(ierr); 3970 ierr = DMPlexSetConeSize(sdm, pMaxNew[dep] + p, coneSize);CHKERRQ(ierr); 3971 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 3972 ierr = DMPlexSetSupportSize(sdm, pMaxNew[dep] + p, supportSize);CHKERRQ(ierr); 3973 if (dep == depth-1) { 3974 /* Add cohesive cells, they are prisms */ 3975 ierr = DMPlexSetConeSize(sdm, pMaxNew[depth] + p, 2 + coneSize);CHKERRQ(ierr); 3976 } else if (dep == 0) { 3977 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 3978 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3979 for(e = 0, q = 0; e < supportSize; ++e) { 3980 PetscInt val; 3981 3982 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3983 if ((val == 1) || (val == (shift + 1))) ++q; 3984 } 3985 ierr = DMPlexSetSupportSize(sdm, depthShift[depth] + points[p], q+1);CHKERRQ(ierr); 3986 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3987 for(e = 0, q = 0; e < supportSize; ++e) { 3988 PetscInt val; 3989 3990 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3991 if ((val == 1) || (val == -(shift + 1))) ++q; 3992 } 3993 ierr = DMPlexSetSupportSize(sdm, pMaxNew[dep] + p, q+1);CHKERRQ(ierr); 3994 /* Add cohesive edges */ 3995 ierr = DMPlexSetConeSize(sdm, pMaxNew[1] + (depthShift[1] - depthShift[0]) + p, 2);CHKERRQ(ierr); 3996 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3997 } 3998 } 3999 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4000 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4001 } 4002 /* Step 4: Setup ghosted DM */ 4003 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4004 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4005 /* Step 6: Set cones and supports for new points */ 4006 for(sp = 0; sp < numSP; ++sp) { 4007 const PetscInt dep = values[sp]; 4008 const PetscInt *points; 4009 IS dimIS; 4010 PetscInt numPoints, p; 4011 4012 if ((values[sp] < 0) || (values[sp] > depth)) continue; 4013 ierr = DMLabelGetStratumIS(label, dep, &dimIS);CHKERRQ(ierr); 4014 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4015 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4016 for(p = 0; p < numPoints; ++p) { 4017 const PetscInt *cone, *support; 4018 PetscInt coneSize, supportSize, q, v, e, s; 4019 4020 ierr = DMPlexGetConeSize(dm, points[p], &coneSize);CHKERRQ(ierr); 4021 ierr = DMPlexGetCone(dm, points[p], &cone);CHKERRQ(ierr); 4022 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4023 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4024 if (dep == depth-1) { 4025 const PetscInt newp = depthOffset[dep] + points[p]; 4026 const PetscInt splitp = pMaxNew[dep] + p; 4027 const PetscInt ccell = pMaxNew[depth] + p; 4028 const PetscInt *supportF; 4029 4030 /* Split face: copy in old face to new face to start */ 4031 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4032 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4033 /* Split old face: old vertices in cone so no change */ 4034 /* Split new face: new vertices in cone */ 4035 for(q = 0; q < coneSize; ++q) { 4036 ierr = PetscFindInt(cone[q], numSplitVertices, splitVertices, &v);CHKERRQ(ierr); 4037 coneNew[2+q] = pMaxNew[0] + v; 4038 } 4039 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4040 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4041 coneNew[0] = newp; 4042 coneNew[1] = splitp; 4043 for(q = 0; q < coneSize; ++q) { 4044 coneNew[2+q] = (pMaxNew[1] - pMaxNew[0]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4045 } 4046 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4047 for(s = 0; s < supportSize; ++s) { 4048 PetscInt val; 4049 4050 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4051 if (val < 0) { 4052 const PetscInt *scone; 4053 PetscInt sconeSize, sc; 4054 4055 /* Split old face: Replace negative side cell with cohesive cell */ 4056 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4057 /* Negative cell: replace split face */ 4058 ierr = DMPlexGetConeSize(sdm, support[s], &sconeSize);CHKERRQ(ierr); 4059 ierr = DMPlexGetCone(sdm, support[s], &scone);CHKERRQ(ierr); 4060 for(sc = 0; sc < sconeSize; ++sc) { 4061 if (scone[sc] == newp) { 4062 ierr = DMPlexInsertCone(sdm, support[s], sc, splitp);CHKERRQ(ierr); 4063 break; 4064 } 4065 } 4066 } else { 4067 /* Split new face: Replace positive side cell with cohesive cell */ 4068 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4069 } 4070 } 4071 } else if (dep == 0) { 4072 const PetscInt newp = depthOffset[dep] + points[p]; 4073 const PetscInt splitp = pMaxNew[dep] + p; 4074 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4075 4076 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4077 for(e = 0, q = 0; e < supportSize; ++e) { 4078 PetscInt val; 4079 4080 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4081 if ((val == 1) || (val == (shift + 1))) { 4082 supportNew[q++] = depthOffset[1] + support[e]; 4083 } 4084 } 4085 supportNew[q] = cedge; 4086 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4087 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4088 for(e = 0, q = 0; e < supportSize; ++e) { 4089 PetscInt val, edge; 4090 4091 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4092 if (val == 1) { 4093 ierr = PetscFindInt(support[e], numSplitEdges, splitEdges, &edge);CHKERRQ(ierr); 4094 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4095 supportNew[q++] = pMaxNew[1] + edge; 4096 } else if (val == -(shift + 1)) { 4097 const PetscInt *scone; 4098 PetscInt sconeSize, sc; 4099 4100 supportNew[q++] = depthOffset[1] + support[e]; 4101 /* Negative edge: replace split vertex */ 4102 ierr = DMPlexGetConeSize(sdm, depthOffset[1] + support[e], &sconeSize);CHKERRQ(ierr); 4103 ierr = DMPlexGetCone(sdm, depthOffset[1] + support[e], &scone);CHKERRQ(ierr); 4104 for(sc = 0; sc < sconeSize; ++sc) { 4105 if (scone[sc] == newp) { 4106 ierr = DMPlexInsertCone(sdm, depthOffset[1] + support[e], sc, splitp);CHKERRQ(ierr); 4107 break; 4108 } 4109 } 4110 if (sc == sconeSize) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Edge %d does not contain split vertex %d", support[e], newp); 4111 } 4112 } 4113 supportNew[q] = cedge; 4114 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4115 /* Cohesive edge: Old and new split vertex, punting on support */ 4116 coneNew[0] = newp; 4117 coneNew[1] = splitp; 4118 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4119 } 4120 } 4121 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4122 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4123 } 4124 if (label) { 4125 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4126 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4127 } 4128 /* Step 7: Stratify */ 4129 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4130 /* Step 8: Coordinates */ 4131 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4132 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4133 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4134 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4135 for(v = 0; v < numSplitVertices; ++v) { 4136 const PetscInt newp = depthOffset[0] + splitVertices[v]; 4137 const PetscInt splitp = pMaxNew[0] + v; 4138 PetscInt dof, off, soff, d; 4139 4140 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4141 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4142 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4143 for(d = 0; d < dof; ++d) { 4144 coords[soff+d] = coords[off+d]; 4145 } 4146 } 4147 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4148 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4149 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4150 /* Step 10: Labels */ 4151 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4152 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4153 for(sp = 0; sp < numSP; ++sp) { 4154 const PetscInt dep = values[sp]; 4155 const PetscInt *points; 4156 IS dimIS; 4157 PetscInt numPoints, p; 4158 4159 if ((values[sp] < 0) || (values[sp] > depth)) continue; 4160 ierr = DMLabelGetStratumIS(label, dep, &dimIS);CHKERRQ(ierr); 4161 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4162 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4163 for(p = 0; p < numPoints; ++p) { 4164 const PetscInt newp = depthOffset[dep] + points[p]; 4165 const PetscInt splitp = pMaxNew[dep] + p; 4166 4167 for (l = 0; l < numLabels; ++l) { 4168 DMLabel label; 4169 const char *lname; 4170 PetscInt val; 4171 4172 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4173 ierr = DMPlexGetLabel(sdm, lname, &label);CHKERRQ(ierr); 4174 ierr = DMLabelGetValue(label, newp, &val);CHKERRQ(ierr); 4175 if (val >= 0) { 4176 ierr = DMLabelSetValue(label, splitp, val);CHKERRQ(ierr); 4177 if (dep == 0) { 4178 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4179 ierr = DMLabelSetValue(label, cedge, val);CHKERRQ(ierr); 4180 } 4181 } 4182 } 4183 } 4184 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4185 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4186 } 4187 if (svIS) {ierr = ISRestoreIndices(svIS, &splitVertices);CHKERRQ(ierr);} 4188 if (seIS) {ierr = ISRestoreIndices(seIS, &splitEdges);CHKERRQ(ierr);} 4189 ierr = ISDestroy(&svIS);CHKERRQ(ierr); 4190 ierr = ISDestroy(&seIS);CHKERRQ(ierr); 4191 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4192 PetscFunctionReturn(0); 4193 } 4194 4195 #undef __FUNCT__ 4196 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4197 /*@C 4198 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4199 4200 Collective on dm 4201 4202 Input Parameters: 4203 + dm - The original DM 4204 - labelName - The label specifying the boundary faces (this could be auto-generated) 4205 4206 Output Parameters: 4207 - dmSplit - The new DM 4208 4209 Level: developer 4210 4211 .seealso: DMCreate() 4212 */ 4213 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, const char labelName[], DM *dmSplit) 4214 { 4215 DM sdm; 4216 PetscInt dim; 4217 PetscErrorCode ierr; 4218 4219 PetscFunctionBegin; 4220 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4221 PetscValidPointer(dmSplit, 4); 4222 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4223 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4224 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4225 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4226 switch(dim) { 4227 case 2: 4228 ierr = DMPlexConstructCohesiveCells_2D(dm, labelName, sdm);CHKERRQ(ierr); 4229 break; 4230 default: 4231 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4232 } 4233 *dmSplit = sdm; 4234 PetscFunctionReturn(0); 4235 } 4236 4237 #undef __FUNCT__ 4238 #define __FUNCT__ "DMLabelCohesiveComplete" 4239 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4240 { 4241 IS dimIS; 4242 const PetscInt *points; 4243 PetscInt shift = 100, dim, numPoints, p; 4244 PetscErrorCode ierr; 4245 4246 PetscFunctionBegin; 4247 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4248 /* Cell orientation for face gives the side of the fault */ 4249 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4250 if (!dimIS) PetscFunctionReturn(0); 4251 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4252 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4253 for(p = 0; p < numPoints; ++p) { 4254 const PetscInt *support; 4255 PetscInt supportSize, s; 4256 4257 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4258 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4259 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4260 for(s = 0; s < supportSize; ++s) { 4261 const PetscInt *cone, *ornt; 4262 PetscInt coneSize, c; 4263 PetscBool pos = PETSC_TRUE; 4264 4265 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4266 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4267 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4268 for(c = 0; c < coneSize; ++c) { 4269 if (cone[c] == points[p]) { 4270 if (ornt[c] >= 0) { 4271 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4272 } else { 4273 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4274 pos = PETSC_FALSE; 4275 } 4276 break; 4277 } 4278 } 4279 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]); 4280 for(c = 0; c < coneSize; ++c) { 4281 if (cone[c] != points[p]) { 4282 if (pos) { 4283 ierr = DMLabelSetValue(label, cone[c], shift+dim-1);CHKERRQ(ierr); 4284 } else { 4285 ierr = DMLabelSetValue(label, cone[c], -(shift+dim-1));CHKERRQ(ierr); 4286 pos = PETSC_FALSE; 4287 } 4288 } 4289 } 4290 } 4291 } 4292 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4293 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4294 /* Search for other cells/faces/edges connected to the fault */ 4295 PetscFunctionReturn(0); 4296 } 4297 4298 #undef __FUNCT__ 4299 #define __FUNCT__ "DMPlexInterpolate_2D" 4300 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4301 { 4302 DM idm; 4303 DM_Plex *mesh; 4304 PetscHashIJ edgeTable; 4305 PetscInt *off; 4306 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4307 PetscInt numEdges, firstEdge, edge, e; 4308 PetscErrorCode ierr; 4309 4310 PetscFunctionBegin; 4311 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4312 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4313 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4314 numCells = cEnd - cStart; 4315 numVertices = vEnd - vStart; 4316 firstEdge = numCells + numVertices; 4317 numEdges = 0 ; 4318 /* Count edges using algorithm from CreateNeighborCSR */ 4319 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4320 if (off) { 4321 PetscInt numCorners = 0; 4322 4323 numEdges = off[numCells]/2; 4324 #if 0 4325 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4326 numEdges += 3*numCells - off[numCells]; 4327 #else 4328 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4329 for (c = cStart; c < cEnd; ++c) { 4330 PetscInt coneSize; 4331 4332 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4333 numCorners += coneSize; 4334 } 4335 numEdges += numCorners - off[numCells]; 4336 #endif 4337 } 4338 #if 0 4339 /* Check Euler characteristic V - E + F = 1 */ 4340 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4341 #endif 4342 /* Create interpolated mesh */ 4343 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4344 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4345 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4346 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4347 for (c = 0; c < numCells; ++c) { 4348 PetscInt numCorners; 4349 4350 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4351 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4352 } 4353 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4354 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4355 } 4356 ierr = DMSetUp(idm);CHKERRQ(ierr); 4357 /* Get edge cones from subsets of cell vertices */ 4358 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4359 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4360 4361 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4362 const PetscInt *cellFaces; 4363 PetscInt numCellFaces, faceSize, cf; 4364 4365 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4366 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4367 for (cf = 0; cf < numCellFaces; ++cf) { 4368 #if 1 4369 PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]), 4370 PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])}; 4371 4372 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4373 if (e < 0) { 4374 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4375 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4376 e = edge++; 4377 } 4378 #else 4379 PetscBool found = PETSC_FALSE; 4380 4381 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4382 for (e = firstEdge; e < edge; ++e) { 4383 const PetscInt *cone; 4384 4385 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4386 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4387 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4388 found = PETSC_TRUE; 4389 break; 4390 } 4391 } 4392 if (!found) { 4393 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4394 ++edge; 4395 } 4396 #endif 4397 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4398 } 4399 } 4400 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4401 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4402 ierr = PetscFree(off);CHKERRQ(ierr); 4403 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4404 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4405 mesh = (DM_Plex *) (idm)->data; 4406 /* Orient edges */ 4407 for (c = 0; c < numCells; ++c) { 4408 const PetscInt *cone = PETSC_NULL, *cellFaces; 4409 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4410 4411 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4412 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4413 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4414 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4415 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4416 for (cf = 0; cf < numCellFaces; ++cf) { 4417 const PetscInt *econe = PETSC_NULL; 4418 PetscInt esize; 4419 4420 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4421 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4422 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]); 4423 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4424 /* Correctly oriented */ 4425 mesh->coneOrientations[coff+cf] = 0; 4426 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4427 /* Start at index 1, and reverse orientation */ 4428 mesh->coneOrientations[coff+cf] = -(1+1); 4429 } 4430 } 4431 } 4432 *dmInt = idm; 4433 PetscFunctionReturn(0); 4434 } 4435 4436 #undef __FUNCT__ 4437 #define __FUNCT__ "DMPlexInterpolate_3D" 4438 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4439 { 4440 DM idm, fdm; 4441 DM_Plex *mesh; 4442 PetscInt *off; 4443 const PetscInt numCorners = 4; 4444 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4445 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4446 PetscErrorCode ierr; 4447 4448 PetscFunctionBegin; 4449 { 4450 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4451 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4452 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4453 } 4454 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4455 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4456 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4457 numCells = cEnd - cStart; 4458 numVertices = vEnd - vStart; 4459 firstFace = numCells + numVertices; 4460 numFaces = 0 ; 4461 /* Count faces using algorithm from CreateNeighborCSR */ 4462 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4463 if (off) { 4464 numFaces = off[numCells]/2; 4465 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4466 numFaces += 4*numCells - off[numCells]; 4467 } 4468 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4469 firstEdge = firstFace + numFaces; 4470 numEdges = numVertices + numFaces - numCells - 1; 4471 /* Create interpolated mesh */ 4472 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4473 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4474 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4475 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4476 for (c = 0; c < numCells; ++c) { 4477 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4478 } 4479 for (f = firstFace; f < firstFace+numFaces; ++f) { 4480 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4481 } 4482 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4483 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4484 } 4485 ierr = DMSetUp(idm);CHKERRQ(ierr); 4486 /* Get face cones from subsets of cell vertices */ 4487 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4488 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4489 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4490 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4491 for (f = firstFace; f < firstFace+numFaces; ++f) { 4492 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4493 } 4494 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4495 for (c = 0, face = firstFace; c < numCells; ++c) { 4496 const PetscInt *cellFaces; 4497 PetscInt numCellFaces, faceSize, cf; 4498 4499 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4500 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4501 for (cf = 0; cf < numCellFaces; ++cf) { 4502 PetscBool found = PETSC_FALSE; 4503 4504 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4505 for (f = firstFace; f < face; ++f) { 4506 const PetscInt *cone = PETSC_NULL; 4507 4508 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4509 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4510 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4511 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4512 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4513 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4514 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4515 found = PETSC_TRUE; 4516 break; 4517 } 4518 } 4519 if (!found) { 4520 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4521 /* Save the vertices for orientation calculation */ 4522 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4523 ++face; 4524 } 4525 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4526 } 4527 } 4528 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4529 /* Get edge cones from subsets of face vertices */ 4530 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4531 const PetscInt *cellFaces; 4532 PetscInt numCellFaces, faceSize, cf; 4533 4534 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4535 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4536 for (cf = 0; cf < numCellFaces; ++cf) { 4537 PetscBool found = PETSC_FALSE; 4538 4539 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4540 for (e = firstEdge; e < edge; ++e) { 4541 const PetscInt *cone = PETSC_NULL; 4542 4543 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4544 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4545 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4546 found = PETSC_TRUE; 4547 break; 4548 } 4549 } 4550 if (!found) { 4551 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4552 ++edge; 4553 } 4554 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4555 } 4556 } 4557 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4558 ierr = PetscFree(off);CHKERRQ(ierr); 4559 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4560 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4561 mesh = (DM_Plex *) (idm)->data; 4562 /* Orient edges */ 4563 for (f = firstFace; f < firstFace+numFaces; ++f) { 4564 const PetscInt *cone, *cellFaces; 4565 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4566 4567 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4568 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4569 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4570 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4571 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4572 for (cf = 0; cf < numCellFaces; ++cf) { 4573 const PetscInt *econe; 4574 PetscInt esize; 4575 4576 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4577 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4578 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4579 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4580 /* Correctly oriented */ 4581 mesh->coneOrientations[coff+cf] = 0; 4582 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4583 /* Start at index 1, and reverse orientation */ 4584 mesh->coneOrientations[coff+cf] = -(1+1); 4585 } 4586 } 4587 } 4588 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4589 /* Orient faces */ 4590 for (c = 0; c < numCells; ++c) { 4591 const PetscInt *cone, *cellFaces; 4592 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4593 4594 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4595 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4596 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4597 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4598 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4599 for (cf = 0; cf < numCellFaces; ++cf) { 4600 PetscInt *origClosure = PETSC_NULL, *closure; 4601 PetscInt closureSize, i; 4602 4603 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4604 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4605 for (i = 4; i < 7; ++i) { 4606 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); 4607 } 4608 closure = &origClosure[4*2]; 4609 /* Remember that this is the orientation for edges, not vertices */ 4610 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4611 /* Correctly oriented */ 4612 mesh->coneOrientations[coff+cf] = 0; 4613 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4614 /* Shifted by 1 */ 4615 mesh->coneOrientations[coff+cf] = 1; 4616 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4617 /* Shifted by 2 */ 4618 mesh->coneOrientations[coff+cf] = 2; 4619 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4620 /* Start at edge 1, and reverse orientation */ 4621 mesh->coneOrientations[coff+cf] = -(1+1); 4622 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4623 /* Start at index 0, and reverse orientation */ 4624 mesh->coneOrientations[coff+cf] = -(0+1); 4625 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4626 /* Start at index 2, and reverse orientation */ 4627 mesh->coneOrientations[coff+cf] = -(2+1); 4628 } 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); 4629 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4630 } 4631 } 4632 { 4633 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4634 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4635 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4636 } 4637 *dmInt = idm; 4638 PetscFunctionReturn(0); 4639 } 4640 4641 #undef __FUNCT__ 4642 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4643 /* 4644 This takes as input the common mesh generator output, a list of the vertices for each cell 4645 */ 4646 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4647 { 4648 PetscInt *cone, c, p; 4649 PetscErrorCode ierr; 4650 4651 PetscFunctionBegin; 4652 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4653 for (c = 0; c < numCells; ++c) { 4654 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4655 } 4656 ierr = DMSetUp(dm);CHKERRQ(ierr); 4657 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4658 for (c = 0; c < numCells; ++c) { 4659 for (p = 0; p < numCorners; ++p) { 4660 cone[p] = cells[c*numCorners+p]+numCells; 4661 } 4662 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4663 } 4664 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4665 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4666 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4667 PetscFunctionReturn(0); 4668 } 4669 4670 #undef __FUNCT__ 4671 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4672 /* 4673 This takes as input the coordinates for each vertex 4674 */ 4675 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4676 { 4677 PetscSection coordSection; 4678 Vec coordinates; 4679 PetscScalar *coords; 4680 PetscInt coordSize, v, d; 4681 PetscErrorCode ierr; 4682 4683 PetscFunctionBegin; 4684 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4685 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4686 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4687 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4688 for (v = numCells; v < numCells+numVertices; ++v) { 4689 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4690 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4691 } 4692 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4693 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4694 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4695 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4696 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4697 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4698 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4699 for (v = 0; v < numVertices; ++v) { 4700 for (d = 0; d < spaceDim; ++d) { 4701 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4702 } 4703 } 4704 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4705 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4706 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4707 PetscFunctionReturn(0); 4708 } 4709 4710 #undef __FUNCT__ 4711 #define __FUNCT__ "DMPlexCreateFromCellList" 4712 /* 4713 This takes as input the common mesh generator output, a list of the vertices for each cell 4714 */ 4715 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4716 { 4717 PetscErrorCode ierr; 4718 4719 PetscFunctionBegin; 4720 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4721 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4722 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4723 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4724 if (interpolate) { 4725 DM idm; 4726 4727 switch (dim) { 4728 case 2: 4729 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4730 case 3: 4731 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4732 default: 4733 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4734 } 4735 ierr = DMDestroy(dm);CHKERRQ(ierr); 4736 *dm = idm; 4737 } 4738 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4739 PetscFunctionReturn(0); 4740 } 4741 4742 #if defined(PETSC_HAVE_TRIANGLE) 4743 #include <triangle.h> 4744 4745 #undef __FUNCT__ 4746 #define __FUNCT__ "InitInput_Triangle" 4747 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4748 { 4749 PetscFunctionBegin; 4750 inputCtx->numberofpoints = 0; 4751 inputCtx->numberofpointattributes = 0; 4752 inputCtx->pointlist = PETSC_NULL; 4753 inputCtx->pointattributelist = PETSC_NULL; 4754 inputCtx->pointmarkerlist = PETSC_NULL; 4755 inputCtx->numberofsegments = 0; 4756 inputCtx->segmentlist = PETSC_NULL; 4757 inputCtx->segmentmarkerlist = PETSC_NULL; 4758 inputCtx->numberoftriangleattributes = 0; 4759 inputCtx->trianglelist = PETSC_NULL; 4760 inputCtx->numberofholes = 0; 4761 inputCtx->holelist = PETSC_NULL; 4762 inputCtx->numberofregions = 0; 4763 inputCtx->regionlist = PETSC_NULL; 4764 PetscFunctionReturn(0); 4765 } 4766 4767 #undef __FUNCT__ 4768 #define __FUNCT__ "InitOutput_Triangle" 4769 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4770 { 4771 PetscFunctionBegin; 4772 outputCtx->numberofpoints = 0; 4773 outputCtx->pointlist = PETSC_NULL; 4774 outputCtx->pointattributelist = PETSC_NULL; 4775 outputCtx->pointmarkerlist = PETSC_NULL; 4776 outputCtx->numberoftriangles = 0; 4777 outputCtx->trianglelist = PETSC_NULL; 4778 outputCtx->triangleattributelist = PETSC_NULL; 4779 outputCtx->neighborlist = PETSC_NULL; 4780 outputCtx->segmentlist = PETSC_NULL; 4781 outputCtx->segmentmarkerlist = PETSC_NULL; 4782 outputCtx->numberofedges = 0; 4783 outputCtx->edgelist = PETSC_NULL; 4784 outputCtx->edgemarkerlist = PETSC_NULL; 4785 PetscFunctionReturn(0); 4786 } 4787 4788 #undef __FUNCT__ 4789 #define __FUNCT__ "FiniOutput_Triangle" 4790 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4791 { 4792 PetscFunctionBegin; 4793 free(outputCtx->pointmarkerlist); 4794 free(outputCtx->edgelist); 4795 free(outputCtx->edgemarkerlist); 4796 free(outputCtx->trianglelist); 4797 free(outputCtx->neighborlist); 4798 PetscFunctionReturn(0); 4799 } 4800 4801 #undef __FUNCT__ 4802 #define __FUNCT__ "DMPlexGenerate_Triangle" 4803 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4804 { 4805 MPI_Comm comm = ((PetscObject) boundary)->comm; 4806 PetscInt dim = 2; 4807 const PetscBool createConvexHull = PETSC_FALSE; 4808 const PetscBool constrained = PETSC_FALSE; 4809 struct triangulateio in; 4810 struct triangulateio out; 4811 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4812 PetscMPIInt rank; 4813 PetscErrorCode ierr; 4814 4815 PetscFunctionBegin; 4816 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4817 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4818 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4819 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4820 in.numberofpoints = vEnd - vStart; 4821 if (in.numberofpoints > 0) { 4822 PetscSection coordSection; 4823 Vec coordinates; 4824 PetscScalar *array; 4825 4826 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4827 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4828 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4829 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4830 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4831 for (v = vStart; v < vEnd; ++v) { 4832 const PetscInt idx = v - vStart; 4833 PetscInt off, d; 4834 4835 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4836 for (d = 0; d < dim; ++d) { 4837 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4838 } 4839 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4840 } 4841 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4842 } 4843 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4844 in.numberofsegments = eEnd - eStart; 4845 if (in.numberofsegments > 0) { 4846 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4847 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4848 for (e = eStart; e < eEnd; ++e) { 4849 const PetscInt idx = e - eStart; 4850 const PetscInt *cone; 4851 4852 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4853 in.segmentlist[idx*2+0] = cone[0] - vStart; 4854 in.segmentlist[idx*2+1] = cone[1] - vStart; 4855 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4856 } 4857 } 4858 #if 0 /* Do not currently support holes */ 4859 PetscReal *holeCoords; 4860 PetscInt h, d; 4861 4862 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4863 if (in.numberofholes > 0) { 4864 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4865 for (h = 0; h < in.numberofholes; ++h) { 4866 for (d = 0; d < dim; ++d) { 4867 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4868 } 4869 } 4870 } 4871 #endif 4872 if (!rank) { 4873 char args[32]; 4874 4875 /* Take away 'Q' for verbose output */ 4876 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4877 if (createConvexHull) { 4878 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4879 } 4880 if (constrained) { 4881 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4882 } 4883 triangulate(args, &in, &out, PETSC_NULL); 4884 } 4885 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4886 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4887 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4888 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4889 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4890 4891 { 4892 const PetscInt numCorners = 3; 4893 const PetscInt numCells = out.numberoftriangles; 4894 const PetscInt numVertices = out.numberofpoints; 4895 const int *cells = out.trianglelist; 4896 const double *meshCoords = out.pointlist; 4897 4898 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4899 /* Set labels */ 4900 for (v = 0; v < numVertices; ++v) { 4901 if (out.pointmarkerlist[v]) { 4902 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4903 } 4904 } 4905 if (interpolate) { 4906 for (e = 0; e < out.numberofedges; e++) { 4907 if (out.edgemarkerlist[e]) { 4908 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4909 const PetscInt *edges; 4910 PetscInt numEdges; 4911 4912 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4913 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4914 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4915 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4916 } 4917 } 4918 } 4919 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4920 } 4921 #if 0 /* Do not currently support holes */ 4922 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4923 #endif 4924 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4925 PetscFunctionReturn(0); 4926 } 4927 4928 #undef __FUNCT__ 4929 #define __FUNCT__ "DMPlexRefine_Triangle" 4930 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4931 { 4932 MPI_Comm comm = ((PetscObject) dm)->comm; 4933 PetscInt dim = 2; 4934 struct triangulateio in; 4935 struct triangulateio out; 4936 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4937 PetscMPIInt rank; 4938 PetscErrorCode ierr; 4939 4940 PetscFunctionBegin; 4941 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4942 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4943 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4944 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4945 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4946 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4947 in.numberofpoints = vEnd - vStart; 4948 if (in.numberofpoints > 0) { 4949 PetscSection coordSection; 4950 Vec coordinates; 4951 PetscScalar *array; 4952 4953 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4954 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4955 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4956 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4957 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4958 for (v = vStart; v < vEnd; ++v) { 4959 const PetscInt idx = v - vStart; 4960 PetscInt off, d; 4961 4962 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4963 for (d = 0; d < dim; ++d) { 4964 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4965 } 4966 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4967 } 4968 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4969 } 4970 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4971 in.numberofcorners = 3; 4972 in.numberoftriangles = cEnd - cStart; 4973 in.trianglearealist = (double *) maxVolumes; 4974 if (in.numberoftriangles > 0) { 4975 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4976 for (c = cStart; c < cEnd; ++c) { 4977 const PetscInt idx = c - cStart; 4978 PetscInt *closure = PETSC_NULL; 4979 PetscInt closureSize; 4980 4981 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4982 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4983 for (v = 0; v < 3; ++v) { 4984 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4985 } 4986 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4987 } 4988 } 4989 /* TODO: Segment markers are missing on input */ 4990 #if 0 /* Do not currently support holes */ 4991 PetscReal *holeCoords; 4992 PetscInt h, d; 4993 4994 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4995 if (in.numberofholes > 0) { 4996 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4997 for (h = 0; h < in.numberofholes; ++h) { 4998 for (d = 0; d < dim; ++d) { 4999 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5000 } 5001 } 5002 } 5003 #endif 5004 if (!rank) { 5005 char args[32]; 5006 5007 /* Take away 'Q' for verbose output */ 5008 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5009 triangulate(args, &in, &out, PETSC_NULL); 5010 } 5011 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5012 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5013 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5014 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5015 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5016 5017 { 5018 const PetscInt numCorners = 3; 5019 const PetscInt numCells = out.numberoftriangles; 5020 const PetscInt numVertices = out.numberofpoints; 5021 const int *cells = out.trianglelist; 5022 const double *meshCoords = out.pointlist; 5023 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5024 5025 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5026 /* Set labels */ 5027 for (v = 0; v < numVertices; ++v) { 5028 if (out.pointmarkerlist[v]) { 5029 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5030 } 5031 } 5032 if (interpolate) { 5033 PetscInt e; 5034 5035 for (e = 0; e < out.numberofedges; e++) { 5036 if (out.edgemarkerlist[e]) { 5037 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5038 const PetscInt *edges; 5039 PetscInt numEdges; 5040 5041 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5042 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5043 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5044 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5045 } 5046 } 5047 } 5048 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5049 } 5050 #if 0 /* Do not currently support holes */ 5051 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5052 #endif 5053 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5054 PetscFunctionReturn(0); 5055 } 5056 #endif 5057 5058 #if defined(PETSC_HAVE_TETGEN) 5059 #include <tetgen.h> 5060 #undef __FUNCT__ 5061 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5062 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5063 { 5064 MPI_Comm comm = ((PetscObject) boundary)->comm; 5065 const PetscInt dim = 3; 5066 ::tetgenio in; 5067 ::tetgenio out; 5068 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5069 PetscMPIInt rank; 5070 PetscErrorCode ierr; 5071 5072 PetscFunctionBegin; 5073 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5074 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5075 in.numberofpoints = vEnd - vStart; 5076 if (in.numberofpoints > 0) { 5077 PetscSection coordSection; 5078 Vec coordinates; 5079 PetscScalar *array; 5080 5081 in.pointlist = new double[in.numberofpoints*dim]; 5082 in.pointmarkerlist = new int[in.numberofpoints]; 5083 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5084 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5085 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5086 for (v = vStart; v < vEnd; ++v) { 5087 const PetscInt idx = v - vStart; 5088 PetscInt off, d; 5089 5090 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5091 for (d = 0; d < dim; ++d) { 5092 in.pointlist[idx*dim + d] = array[off+d]; 5093 } 5094 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5095 } 5096 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5097 } 5098 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5099 in.numberoffacets = fEnd - fStart; 5100 if (in.numberoffacets > 0) { 5101 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5102 in.facetmarkerlist = new int[in.numberoffacets]; 5103 for (f = fStart; f < fEnd; ++f) { 5104 const PetscInt idx = f - fStart; 5105 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5106 5107 in.facetlist[idx].numberofpolygons = 1; 5108 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5109 in.facetlist[idx].numberofholes = 0; 5110 in.facetlist[idx].holelist = NULL; 5111 5112 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5113 for (p = 0; p < numPoints*2; p += 2) { 5114 const PetscInt point = points[p]; 5115 if ((point >= vStart) && (point < vEnd)) { 5116 points[numVertices++] = point; 5117 } 5118 } 5119 5120 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5121 poly->numberofvertices = numVertices; 5122 poly->vertexlist = new int[poly->numberofvertices]; 5123 for (v = 0; v < numVertices; ++v) { 5124 const PetscInt vIdx = points[v] - vStart; 5125 poly->vertexlist[v] = vIdx; 5126 } 5127 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5128 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5129 } 5130 } 5131 if (!rank) { 5132 char args[32]; 5133 5134 /* Take away 'Q' for verbose output */ 5135 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5136 ::tetrahedralize(args, &in, &out); 5137 } 5138 { 5139 const PetscInt numCorners = 4; 5140 const PetscInt numCells = out.numberoftetrahedra; 5141 const PetscInt numVertices = out.numberofpoints; 5142 const int *cells = out.tetrahedronlist; 5143 const double *meshCoords = out.pointlist; 5144 5145 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5146 /* Set labels */ 5147 for (v = 0; v < numVertices; ++v) { 5148 if (out.pointmarkerlist[v]) { 5149 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5150 } 5151 } 5152 if (interpolate) { 5153 PetscInt e; 5154 5155 for (e = 0; e < out.numberofedges; e++) { 5156 if (out.edgemarkerlist[e]) { 5157 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5158 const PetscInt *edges; 5159 PetscInt numEdges; 5160 5161 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5162 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5163 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5164 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5165 } 5166 } 5167 for (f = 0; f < out.numberoftrifaces; f++) { 5168 if (out.trifacemarkerlist[f]) { 5169 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5170 const PetscInt *faces; 5171 PetscInt numFaces; 5172 5173 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5174 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5175 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5176 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5177 } 5178 } 5179 } 5180 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5181 } 5182 PetscFunctionReturn(0); 5183 } 5184 5185 #undef __FUNCT__ 5186 #define __FUNCT__ "DMPlexRefine_Tetgen" 5187 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5188 { 5189 MPI_Comm comm = ((PetscObject) dm)->comm; 5190 const PetscInt dim = 3; 5191 ::tetgenio in; 5192 ::tetgenio out; 5193 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5194 PetscMPIInt rank; 5195 PetscErrorCode ierr; 5196 5197 PetscFunctionBegin; 5198 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5199 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5200 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5201 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5202 in.numberofpoints = vEnd - vStart; 5203 if (in.numberofpoints > 0) { 5204 PetscSection coordSection; 5205 Vec coordinates; 5206 PetscScalar *array; 5207 5208 in.pointlist = new double[in.numberofpoints*dim]; 5209 in.pointmarkerlist = new int[in.numberofpoints]; 5210 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5211 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5212 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5213 for (v = vStart; v < vEnd; ++v) { 5214 const PetscInt idx = v - vStart; 5215 PetscInt off, d; 5216 5217 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5218 for (d = 0; d < dim; ++d) { 5219 in.pointlist[idx*dim + d] = array[off+d]; 5220 } 5221 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5222 } 5223 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5224 } 5225 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5226 in.numberofcorners = 4; 5227 in.numberoftetrahedra = cEnd - cStart; 5228 in.tetrahedronvolumelist = (double *) maxVolumes; 5229 if (in.numberoftetrahedra > 0) { 5230 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5231 for (c = cStart; c < cEnd; ++c) { 5232 const PetscInt idx = c - cStart; 5233 PetscInt *closure = PETSC_NULL; 5234 PetscInt closureSize; 5235 5236 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5237 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5238 for (v = 0; v < 4; ++v) { 5239 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5240 } 5241 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5242 } 5243 } 5244 /* TODO: Put in boundary faces with markers */ 5245 if (!rank) { 5246 char args[32]; 5247 5248 /* Take away 'Q' for verbose output */ 5249 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5250 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5251 ::tetrahedralize(args, &in, &out); 5252 } 5253 in.tetrahedronvolumelist = NULL; 5254 5255 { 5256 const PetscInt numCorners = 4; 5257 const PetscInt numCells = out.numberoftetrahedra; 5258 const PetscInt numVertices = out.numberofpoints; 5259 const int *cells = out.tetrahedronlist; 5260 const double *meshCoords = out.pointlist; 5261 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5262 5263 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5264 /* Set labels */ 5265 for (v = 0; v < numVertices; ++v) { 5266 if (out.pointmarkerlist[v]) { 5267 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5268 } 5269 } 5270 if (interpolate) { 5271 PetscInt e, f; 5272 5273 for (e = 0; e < out.numberofedges; e++) { 5274 if (out.edgemarkerlist[e]) { 5275 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5276 const PetscInt *edges; 5277 PetscInt numEdges; 5278 5279 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5280 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5281 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5282 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5283 } 5284 } 5285 for (f = 0; f < out.numberoftrifaces; f++) { 5286 if (out.trifacemarkerlist[f]) { 5287 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5288 const PetscInt *faces; 5289 PetscInt numFaces; 5290 5291 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5292 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5293 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5294 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5295 } 5296 } 5297 } 5298 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5299 } 5300 PetscFunctionReturn(0); 5301 } 5302 #endif 5303 5304 #if defined(PETSC_HAVE_CTETGEN) 5305 #include "ctetgen.h" 5306 5307 #undef __FUNCT__ 5308 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5309 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5310 { 5311 MPI_Comm comm = ((PetscObject) boundary)->comm; 5312 const PetscInt dim = 3; 5313 PLC *in, *out; 5314 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5315 PetscMPIInt rank; 5316 PetscErrorCode ierr; 5317 5318 PetscFunctionBegin; 5319 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5320 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5321 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5322 ierr = PLCCreate(&in);CHKERRQ(ierr); 5323 ierr = PLCCreate(&out);CHKERRQ(ierr); 5324 in->numberofpoints = vEnd - vStart; 5325 if (in->numberofpoints > 0) { 5326 PetscSection coordSection; 5327 Vec coordinates; 5328 PetscScalar *array; 5329 5330 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5331 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5332 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5333 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5334 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5335 for (v = vStart; v < vEnd; ++v) { 5336 const PetscInt idx = v - vStart; 5337 PetscInt off, d, m; 5338 5339 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5340 for (d = 0; d < dim; ++d) { 5341 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5342 } 5343 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5344 in->pointmarkerlist[idx] = (int) m; 5345 } 5346 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5347 } 5348 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5349 in->numberoffacets = fEnd - fStart; 5350 if (in->numberoffacets > 0) { 5351 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5352 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5353 for (f = fStart; f < fEnd; ++f) { 5354 const PetscInt idx = f - fStart; 5355 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5356 polygon *poly; 5357 5358 in->facetlist[idx].numberofpolygons = 1; 5359 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5360 in->facetlist[idx].numberofholes = 0; 5361 in->facetlist[idx].holelist = PETSC_NULL; 5362 5363 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5364 for (p = 0; p < numPoints*2; p += 2) { 5365 const PetscInt point = points[p]; 5366 if ((point >= vStart) && (point < vEnd)) { 5367 points[numVertices++] = point; 5368 } 5369 } 5370 5371 poly = in->facetlist[idx].polygonlist; 5372 poly->numberofvertices = numVertices; 5373 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5374 for (v = 0; v < numVertices; ++v) { 5375 const PetscInt vIdx = points[v] - vStart; 5376 poly->vertexlist[v] = vIdx; 5377 } 5378 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5379 in->facetmarkerlist[idx] = (int) m; 5380 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5381 } 5382 } 5383 if (!rank) { 5384 TetGenOpts t; 5385 5386 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5387 t.in = boundary; /* Should go away */ 5388 t.plc = 1; 5389 t.quality = 1; 5390 t.edgesout = 1; 5391 t.zeroindex = 1; 5392 t.quiet = 1; 5393 t.verbose = verbose; 5394 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5395 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5396 } 5397 { 5398 const PetscInt numCorners = 4; 5399 const PetscInt numCells = out->numberoftetrahedra; 5400 const PetscInt numVertices = out->numberofpoints; 5401 const int *cells = out->tetrahedronlist; 5402 const double *meshCoords = out->pointlist; 5403 5404 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5405 /* Set labels */ 5406 for (v = 0; v < numVertices; ++v) { 5407 if (out->pointmarkerlist[v]) { 5408 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5409 } 5410 } 5411 if (interpolate) { 5412 PetscInt e; 5413 5414 for (e = 0; e < out->numberofedges; e++) { 5415 if (out->edgemarkerlist[e]) { 5416 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5417 const PetscInt *edges; 5418 PetscInt numEdges; 5419 5420 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5421 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5422 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5423 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5424 } 5425 } 5426 for (f = 0; f < out->numberoftrifaces; f++) { 5427 if (out->trifacemarkerlist[f]) { 5428 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5429 const PetscInt *faces; 5430 PetscInt numFaces; 5431 5432 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5433 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5434 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5435 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5436 } 5437 } 5438 } 5439 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5440 } 5441 5442 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5443 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5444 PetscFunctionReturn(0); 5445 } 5446 5447 #undef __FUNCT__ 5448 #define __FUNCT__ "DMPlexRefine_CTetgen" 5449 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5450 { 5451 MPI_Comm comm = ((PetscObject) dm)->comm; 5452 const PetscInt dim = 3; 5453 PLC *in, *out; 5454 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5455 PetscMPIInt rank; 5456 PetscErrorCode ierr; 5457 5458 PetscFunctionBegin; 5459 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5460 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5461 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5462 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5463 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5464 ierr = PLCCreate(&in);CHKERRQ(ierr); 5465 ierr = PLCCreate(&out);CHKERRQ(ierr); 5466 in->numberofpoints = vEnd - vStart; 5467 if (in->numberofpoints > 0) { 5468 PetscSection coordSection; 5469 Vec coordinates; 5470 PetscScalar *array; 5471 5472 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5473 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5474 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5475 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5476 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5477 for (v = vStart; v < vEnd; ++v) { 5478 const PetscInt idx = v - vStart; 5479 PetscInt off, d, m; 5480 5481 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5482 for (d = 0; d < dim; ++d) { 5483 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5484 } 5485 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5486 in->pointmarkerlist[idx] = (int) m; 5487 } 5488 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5489 } 5490 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5491 in->numberofcorners = 4; 5492 in->numberoftetrahedra = cEnd - cStart; 5493 in->tetrahedronvolumelist = maxVolumes; 5494 if (in->numberoftetrahedra > 0) { 5495 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5496 for (c = cStart; c < cEnd; ++c) { 5497 const PetscInt idx = c - cStart; 5498 PetscInt *closure = PETSC_NULL; 5499 PetscInt closureSize; 5500 5501 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5502 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5503 for (v = 0; v < 4; ++v) { 5504 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5505 } 5506 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5507 } 5508 } 5509 if (!rank) { 5510 TetGenOpts t; 5511 5512 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5513 t.in = dm; /* Should go away */ 5514 t.refine = 1; 5515 t.varvolume = 1; 5516 t.quality = 1; 5517 t.edgesout = 1; 5518 t.zeroindex = 1; 5519 t.quiet = 1; 5520 t.verbose = verbose; /* Change this */ 5521 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5522 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5523 } 5524 { 5525 const PetscInt numCorners = 4; 5526 const PetscInt numCells = out->numberoftetrahedra; 5527 const PetscInt numVertices = out->numberofpoints; 5528 const int *cells = out->tetrahedronlist; 5529 const double *meshCoords = out->pointlist; 5530 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5531 5532 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5533 /* Set labels */ 5534 for (v = 0; v < numVertices; ++v) { 5535 if (out->pointmarkerlist[v]) { 5536 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5537 } 5538 } 5539 if (interpolate) { 5540 PetscInt e, f; 5541 5542 for (e = 0; e < out->numberofedges; e++) { 5543 if (out->edgemarkerlist[e]) { 5544 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5545 const PetscInt *edges; 5546 PetscInt numEdges; 5547 5548 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5549 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5550 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5551 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5552 } 5553 } 5554 for (f = 0; f < out->numberoftrifaces; f++) { 5555 if (out->trifacemarkerlist[f]) { 5556 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5557 const PetscInt *faces; 5558 PetscInt numFaces; 5559 5560 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5561 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5562 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5563 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5564 } 5565 } 5566 } 5567 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5568 } 5569 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5570 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5571 PetscFunctionReturn(0); 5572 } 5573 #endif 5574 5575 #undef __FUNCT__ 5576 #define __FUNCT__ "DMPlexGenerate" 5577 /*@C 5578 DMPlexGenerate - Generates a mesh. 5579 5580 Not Collective 5581 5582 Input Parameters: 5583 + boundary - The DMPlex boundary object 5584 . name - The mesh generation package name 5585 - interpolate - Flag to create intermediate mesh elements 5586 5587 Output Parameter: 5588 . mesh - The DMPlex object 5589 5590 Level: intermediate 5591 5592 .keywords: mesh, elements 5593 .seealso: DMPlexCreate(), DMRefine() 5594 @*/ 5595 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5596 { 5597 PetscInt dim; 5598 char genname[1024]; 5599 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5600 PetscErrorCode ierr; 5601 5602 PetscFunctionBegin; 5603 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5604 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5605 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5606 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5607 if (flg) {name = genname;} 5608 if (name) { 5609 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5610 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5611 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5612 } 5613 switch (dim) { 5614 case 1: 5615 if (!name || isTriangle) { 5616 #if defined(PETSC_HAVE_TRIANGLE) 5617 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5618 #else 5619 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5620 #endif 5621 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5622 break; 5623 case 2: 5624 if (!name || isCTetgen) { 5625 #if defined(PETSC_HAVE_CTETGEN) 5626 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5627 #else 5628 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5629 #endif 5630 } else if (isTetgen) { 5631 #if defined(PETSC_HAVE_TETGEN) 5632 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5633 #else 5634 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5635 #endif 5636 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5637 break; 5638 default: 5639 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5640 } 5641 PetscFunctionReturn(0); 5642 } 5643 5644 typedef PetscInt CellRefiner; 5645 5646 #undef __FUNCT__ 5647 #define __FUNCT__ "GetDepthStart_Private" 5648 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5649 { 5650 PetscFunctionBegin; 5651 if (cStart) *cStart = 0; 5652 if (vStart) *vStart = depthSize[depth]; 5653 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5654 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5655 PetscFunctionReturn(0); 5656 } 5657 5658 #undef __FUNCT__ 5659 #define __FUNCT__ "GetDepthEnd_Private" 5660 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5661 { 5662 PetscFunctionBegin; 5663 if (cEnd) *cEnd = depthSize[depth]; 5664 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5665 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5666 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5667 PetscFunctionReturn(0); 5668 } 5669 5670 #undef __FUNCT__ 5671 #define __FUNCT__ "CellRefinerGetSizes" 5672 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5673 { 5674 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5675 PetscErrorCode ierr; 5676 5677 PetscFunctionBegin; 5678 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5679 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5680 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5681 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5682 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5683 switch (refiner) { 5684 case 1: 5685 /* Simplicial 2D */ 5686 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5687 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5688 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5689 break; 5690 case 3: 5691 /* Hybrid 2D */ 5692 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5693 cMax = PetscMin(cEnd, cMax); 5694 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5695 fMax = PetscMin(fEnd, fMax); 5696 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5697 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 */ 5698 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5699 break; 5700 case 2: 5701 /* Hex 2D */ 5702 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5703 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5704 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5705 break; 5706 default: 5707 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5708 } 5709 PetscFunctionReturn(0); 5710 } 5711 5712 #undef __FUNCT__ 5713 #define __FUNCT__ "CellRefinerSetConeSizes" 5714 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5715 { 5716 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5717 PetscErrorCode ierr; 5718 5719 PetscFunctionBegin; 5720 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5721 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5722 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5723 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5724 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5725 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5726 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5727 switch (refiner) { 5728 case 1: 5729 /* Simplicial 2D */ 5730 /* All cells have 3 faces */ 5731 for (c = cStart; c < cEnd; ++c) { 5732 for (r = 0; r < 4; ++r) { 5733 const PetscInt newp = (c - cStart)*4 + r; 5734 5735 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5736 } 5737 } 5738 /* Split faces have 2 vertices and the same cells as the parent */ 5739 for (f = fStart; f < fEnd; ++f) { 5740 for (r = 0; r < 2; ++r) { 5741 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5742 PetscInt size; 5743 5744 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5745 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5746 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5747 } 5748 } 5749 /* Interior faces have 2 vertices and 2 cells */ 5750 for (c = cStart; c < cEnd; ++c) { 5751 for (r = 0; r < 3; ++r) { 5752 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5753 5754 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5755 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5756 } 5757 } 5758 /* Old vertices have identical supports */ 5759 for (v = vStart; v < vEnd; ++v) { 5760 const PetscInt newp = vStartNew + (v - vStart); 5761 PetscInt size; 5762 5763 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5764 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5765 } 5766 /* Face vertices have 2 + cells*2 supports */ 5767 for (f = fStart; f < fEnd; ++f) { 5768 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5769 PetscInt size; 5770 5771 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5772 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5773 } 5774 break; 5775 case 2: 5776 /* Hex 2D */ 5777 /* All cells have 4 faces */ 5778 for (c = cStart; c < cEnd; ++c) { 5779 for (r = 0; r < 4; ++r) { 5780 const PetscInt newp = (c - cStart)*4 + r; 5781 5782 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5783 } 5784 } 5785 /* Split faces have 2 vertices and the same cells as the parent */ 5786 for (f = fStart; f < fEnd; ++f) { 5787 for (r = 0; r < 2; ++r) { 5788 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5789 PetscInt size; 5790 5791 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5792 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5793 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5794 } 5795 } 5796 /* Interior faces have 2 vertices and 2 cells */ 5797 for (c = cStart; c < cEnd; ++c) { 5798 for (r = 0; r < 4; ++r) { 5799 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5800 5801 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5802 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5803 } 5804 } 5805 /* Old vertices have identical supports */ 5806 for (v = vStart; v < vEnd; ++v) { 5807 const PetscInt newp = vStartNew + (v - vStart); 5808 PetscInt size; 5809 5810 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5811 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5812 } 5813 /* Face vertices have 2 + cells supports */ 5814 for (f = fStart; f < fEnd; ++f) { 5815 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5816 PetscInt size; 5817 5818 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5819 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5820 } 5821 /* Cell vertices have 4 supports */ 5822 for (c = cStart; c < cEnd; ++c) { 5823 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5824 5825 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5826 } 5827 break; 5828 case 3: 5829 /* Hybrid 2D */ 5830 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5831 cMax = PetscMin(cEnd, cMax); 5832 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5833 fMax = PetscMin(fEnd, fMax); 5834 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5835 /* Interior cells have 3 faces */ 5836 for (c = cStart; c < cMax; ++c) { 5837 for (r = 0; r < 4; ++r) { 5838 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5839 5840 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5841 } 5842 } 5843 /* Hybrid cells have 4 faces */ 5844 for (c = cMax; c < cEnd; ++c) { 5845 for (r = 0; r < 2; ++r) { 5846 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5847 5848 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5849 } 5850 } 5851 /* Interior split faces have 2 vertices and the same cells as the parent */ 5852 for (f = fStart; f < fMax; ++f) { 5853 for (r = 0; r < 2; ++r) { 5854 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5855 PetscInt size; 5856 5857 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5858 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5859 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5860 } 5861 } 5862 /* Interior cell faces have 2 vertices and 2 cells */ 5863 for (c = cStart; c < cMax; ++c) { 5864 for (r = 0; r < 3; ++r) { 5865 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5866 5867 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5868 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5869 } 5870 } 5871 /* Hybrid faces have 2 vertices and the same cells */ 5872 for (f = fMax; f < fEnd; ++f) { 5873 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5874 PetscInt size; 5875 5876 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5877 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5878 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5879 } 5880 /* Hybrid cell faces have 2 vertices and 2 cells */ 5881 for (c = cMax; c < cEnd; ++c) { 5882 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5883 5884 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5885 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5886 } 5887 /* Old vertices have identical supports */ 5888 for (v = vStart; v < vEnd; ++v) { 5889 const PetscInt newp = vStartNew + (v - vStart); 5890 PetscInt size; 5891 5892 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5893 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5894 } 5895 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5896 for (f = fStart; f < fMax; ++f) { 5897 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5898 const PetscInt *support; 5899 PetscInt size, newSize = 2, s; 5900 5901 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5902 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5903 for (s = 0; s < size; ++s) { 5904 if (support[s] >= cMax) { 5905 newSize += 1; 5906 } else { 5907 newSize += 2; 5908 } 5909 } 5910 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5911 } 5912 break; 5913 default: 5914 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5915 } 5916 PetscFunctionReturn(0); 5917 } 5918 5919 #undef __FUNCT__ 5920 #define __FUNCT__ "CellRefinerSetCones" 5921 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5922 { 5923 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; 5924 PetscInt maxSupportSize, *supportRef; 5925 PetscErrorCode ierr; 5926 5927 PetscFunctionBegin; 5928 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5929 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5930 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5931 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5932 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5933 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5934 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5935 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5936 switch (refiner) { 5937 case 1: 5938 /* Simplicial 2D */ 5939 /* 5940 2 5941 |\ 5942 | \ 5943 | \ 5944 | \ 5945 | C \ 5946 | \ 5947 | \ 5948 2---1---1 5949 |\ D / \ 5950 | 2 0 \ 5951 |A \ / B \ 5952 0---0-------1 5953 */ 5954 /* All cells have 3 faces */ 5955 for (c = cStart; c < cEnd; ++c) { 5956 const PetscInt newp = cStartNew + (c - cStart)*4; 5957 const PetscInt *cone, *ornt; 5958 PetscInt coneNew[3], orntNew[3]; 5959 5960 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5961 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5962 /* A triangle */ 5963 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5964 orntNew[0] = ornt[0]; 5965 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5966 orntNew[1] = -2; 5967 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5968 orntNew[2] = ornt[2]; 5969 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5970 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5971 #if 1 5972 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); 5973 for (p = 0; p < 3; ++p) { 5974 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); 5975 } 5976 #endif 5977 /* B triangle */ 5978 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5979 orntNew[0] = ornt[0]; 5980 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5981 orntNew[1] = ornt[1]; 5982 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5983 orntNew[2] = -2; 5984 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5985 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5986 #if 1 5987 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); 5988 for (p = 0; p < 3; ++p) { 5989 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); 5990 } 5991 #endif 5992 /* C triangle */ 5993 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5994 orntNew[0] = -2; 5995 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5996 orntNew[1] = ornt[1]; 5997 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5998 orntNew[2] = ornt[2]; 5999 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6000 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6001 #if 1 6002 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); 6003 for (p = 0; p < 3; ++p) { 6004 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); 6005 } 6006 #endif 6007 /* D triangle */ 6008 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6009 orntNew[0] = 0; 6010 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6011 orntNew[1] = 0; 6012 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6013 orntNew[2] = 0; 6014 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6015 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6016 #if 1 6017 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); 6018 for (p = 0; p < 3; ++p) { 6019 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); 6020 } 6021 #endif 6022 } 6023 /* Split faces have 2 vertices and the same cells as the parent */ 6024 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6025 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6026 for (f = fStart; f < fEnd; ++f) { 6027 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6028 6029 for (r = 0; r < 2; ++r) { 6030 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6031 const PetscInt *cone, *support; 6032 PetscInt coneNew[2], coneSize, c, supportSize, s; 6033 6034 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6035 coneNew[0] = vStartNew + (cone[0] - vStart); 6036 coneNew[1] = vStartNew + (cone[1] - vStart); 6037 coneNew[(r+1)%2] = newv; 6038 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6039 #if 1 6040 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6041 for (p = 0; p < 2; ++p) { 6042 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); 6043 } 6044 #endif 6045 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6046 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6047 for (s = 0; s < supportSize; ++s) { 6048 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6049 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6050 for (c = 0; c < coneSize; ++c) { 6051 if (cone[c] == f) { 6052 break; 6053 } 6054 } 6055 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6056 } 6057 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6058 #if 1 6059 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6060 for (p = 0; p < supportSize; ++p) { 6061 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); 6062 } 6063 #endif 6064 } 6065 } 6066 /* Interior faces have 2 vertices and 2 cells */ 6067 for (c = cStart; c < cEnd; ++c) { 6068 const PetscInt *cone; 6069 6070 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6071 for (r = 0; r < 3; ++r) { 6072 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6073 PetscInt coneNew[2]; 6074 PetscInt supportNew[2]; 6075 6076 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6077 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6078 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6079 #if 1 6080 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6081 for (p = 0; p < 2; ++p) { 6082 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); 6083 } 6084 #endif 6085 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6086 supportNew[1] = (c - cStart)*4 + 3; 6087 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6088 #if 1 6089 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6090 for (p = 0; p < 2; ++p) { 6091 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); 6092 } 6093 #endif 6094 } 6095 } 6096 /* Old vertices have identical supports */ 6097 for (v = vStart; v < vEnd; ++v) { 6098 const PetscInt newp = vStartNew + (v - vStart); 6099 const PetscInt *support, *cone; 6100 PetscInt size, s; 6101 6102 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6103 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6104 for (s = 0; s < size; ++s) { 6105 PetscInt r = 0; 6106 6107 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6108 if (cone[1] == v) r = 1; 6109 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6110 } 6111 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6112 #if 1 6113 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6114 for (p = 0; p < size; ++p) { 6115 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); 6116 } 6117 #endif 6118 } 6119 /* Face vertices have 2 + cells*2 supports */ 6120 for (f = fStart; f < fEnd; ++f) { 6121 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6122 const PetscInt *cone, *support; 6123 PetscInt size, s; 6124 6125 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6126 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6127 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6128 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6129 for (s = 0; s < size; ++s) { 6130 PetscInt r = 0; 6131 6132 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6133 if (cone[1] == f) r = 1; 6134 else if (cone[2] == f) r = 2; 6135 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6136 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6137 } 6138 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6139 #if 1 6140 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6141 for (p = 0; p < 2+size*2; ++p) { 6142 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); 6143 } 6144 #endif 6145 } 6146 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6147 break; 6148 case 2: 6149 /* Hex 2D */ 6150 /* 6151 3---------2---------2 6152 | | | 6153 | D 2 C | 6154 | | | 6155 3----3----0----1----1 6156 | | | 6157 | A 0 B | 6158 | | | 6159 0---------0---------1 6160 */ 6161 /* All cells have 4 faces */ 6162 for (c = cStart; c < cEnd; ++c) { 6163 const PetscInt newp = (c - cStart)*4; 6164 const PetscInt *cone, *ornt; 6165 PetscInt coneNew[4], orntNew[4]; 6166 6167 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6168 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6169 /* A quad */ 6170 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6171 orntNew[0] = ornt[0]; 6172 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6173 orntNew[1] = 0; 6174 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6175 orntNew[2] = -2; 6176 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6177 orntNew[3] = ornt[3]; 6178 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6179 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6180 #if 1 6181 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); 6182 for (p = 0; p < 4; ++p) { 6183 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6184 } 6185 #endif 6186 /* B quad */ 6187 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6188 orntNew[0] = ornt[0]; 6189 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6190 orntNew[1] = ornt[1]; 6191 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6192 orntNew[2] = 0; 6193 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6194 orntNew[3] = -2; 6195 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6196 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6197 #if 1 6198 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); 6199 for (p = 0; p < 4; ++p) { 6200 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); 6201 } 6202 #endif 6203 /* C quad */ 6204 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6205 orntNew[0] = -2; 6206 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6207 orntNew[1] = ornt[1]; 6208 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6209 orntNew[2] = ornt[2]; 6210 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6211 orntNew[3] = 0; 6212 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6213 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6214 #if 1 6215 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); 6216 for (p = 0; p < 4; ++p) { 6217 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); 6218 } 6219 #endif 6220 /* D quad */ 6221 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6222 orntNew[0] = 0; 6223 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6224 orntNew[1] = -2; 6225 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6226 orntNew[2] = ornt[2]; 6227 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6228 orntNew[3] = ornt[3]; 6229 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6230 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6231 #if 1 6232 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); 6233 for (p = 0; p < 4; ++p) { 6234 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); 6235 } 6236 #endif 6237 } 6238 /* Split faces have 2 vertices and the same cells as the parent */ 6239 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6240 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6241 for (f = fStart; f < fEnd; ++f) { 6242 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6243 6244 for (r = 0; r < 2; ++r) { 6245 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6246 const PetscInt *cone, *support; 6247 PetscInt coneNew[2], coneSize, c, supportSize, s; 6248 6249 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6250 coneNew[0] = vStartNew + (cone[0] - vStart); 6251 coneNew[1] = vStartNew + (cone[1] - vStart); 6252 coneNew[(r+1)%2] = newv; 6253 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6254 #if 1 6255 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6256 for (p = 0; p < 2; ++p) { 6257 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); 6258 } 6259 #endif 6260 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6261 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6262 for (s = 0; s < supportSize; ++s) { 6263 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6264 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6265 for (c = 0; c < coneSize; ++c) { 6266 if (cone[c] == f) { 6267 break; 6268 } 6269 } 6270 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6271 } 6272 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6273 #if 1 6274 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6275 for (p = 0; p < supportSize; ++p) { 6276 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); 6277 } 6278 #endif 6279 } 6280 } 6281 /* Interior faces have 2 vertices and 2 cells */ 6282 for (c = cStart; c < cEnd; ++c) { 6283 const PetscInt *cone; 6284 PetscInt coneNew[2], supportNew[2]; 6285 6286 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6287 for (r = 0; r < 4; ++r) { 6288 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6289 6290 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6291 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6292 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6293 #if 1 6294 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6295 for (p = 0; p < 2; ++p) { 6296 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); 6297 } 6298 #endif 6299 supportNew[0] = (c - cStart)*4 + r; 6300 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6301 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6302 #if 1 6303 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6304 for (p = 0; p < 2; ++p) { 6305 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); 6306 } 6307 #endif 6308 } 6309 } 6310 /* Old vertices have identical supports */ 6311 for (v = vStart; v < vEnd; ++v) { 6312 const PetscInt newp = vStartNew + (v - vStart); 6313 const PetscInt *support, *cone; 6314 PetscInt size, s; 6315 6316 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6317 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6318 for (s = 0; s < size; ++s) { 6319 PetscInt r = 0; 6320 6321 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6322 if (cone[1] == v) r = 1; 6323 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6324 } 6325 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6326 #if 1 6327 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6328 for (p = 0; p < size; ++p) { 6329 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); 6330 } 6331 #endif 6332 } 6333 /* Face vertices have 2 + cells supports */ 6334 for (f = fStart; f < fEnd; ++f) { 6335 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6336 const PetscInt *cone, *support; 6337 PetscInt size, s; 6338 6339 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6340 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6341 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6342 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6343 for (s = 0; s < size; ++s) { 6344 PetscInt r = 0; 6345 6346 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6347 if (cone[1] == f) r = 1; 6348 else if (cone[2] == f) r = 2; 6349 else if (cone[3] == f) r = 3; 6350 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6351 } 6352 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6353 #if 1 6354 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6355 for (p = 0; p < 2+size; ++p) { 6356 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); 6357 } 6358 #endif 6359 } 6360 /* Cell vertices have 4 supports */ 6361 for (c = cStart; c < cEnd; ++c) { 6362 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6363 PetscInt supportNew[4]; 6364 6365 for (r = 0; r < 4; ++r) { 6366 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6367 } 6368 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6369 } 6370 break; 6371 case 3: 6372 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6373 cMax = PetscMin(cEnd, cMax); 6374 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6375 fMax = PetscMin(fEnd, fMax); 6376 /* Interior cells have 3 faces */ 6377 for (c = cStart; c < cMax; ++c) { 6378 const PetscInt newp = cStartNew + (c - cStart)*4; 6379 const PetscInt *cone, *ornt; 6380 PetscInt coneNew[3], orntNew[3]; 6381 6382 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6383 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6384 /* A triangle */ 6385 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6386 orntNew[0] = ornt[0]; 6387 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6388 orntNew[1] = -2; 6389 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6390 orntNew[2] = ornt[2]; 6391 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6392 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6393 #if 1 6394 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); 6395 for (p = 0; p < 3; ++p) { 6396 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6397 } 6398 #endif 6399 /* B triangle */ 6400 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6401 orntNew[0] = ornt[0]; 6402 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6403 orntNew[1] = ornt[1]; 6404 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6405 orntNew[2] = -2; 6406 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6407 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6408 #if 1 6409 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); 6410 for (p = 0; p < 3; ++p) { 6411 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); 6412 } 6413 #endif 6414 /* C triangle */ 6415 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6416 orntNew[0] = -2; 6417 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6418 orntNew[1] = ornt[1]; 6419 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6420 orntNew[2] = ornt[2]; 6421 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6422 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6423 #if 1 6424 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); 6425 for (p = 0; p < 3; ++p) { 6426 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); 6427 } 6428 #endif 6429 /* D triangle */ 6430 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6431 orntNew[0] = 0; 6432 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6433 orntNew[1] = 0; 6434 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6435 orntNew[2] = 0; 6436 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6437 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6438 #if 1 6439 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); 6440 for (p = 0; p < 3; ++p) { 6441 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); 6442 } 6443 #endif 6444 } 6445 /* 6446 2----3----3 6447 | | 6448 | B | 6449 | | 6450 0----4--- 1 6451 | | 6452 | A | 6453 | | 6454 0----2----1 6455 */ 6456 /* Hybrid cells have 4 faces */ 6457 for (c = cMax; c < cEnd; ++c) { 6458 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6459 const PetscInt *cone, *ornt; 6460 PetscInt coneNew[4], orntNew[4]; 6461 6462 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6463 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6464 /* A quad */ 6465 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6466 orntNew[0] = ornt[0]; 6467 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6468 orntNew[1] = ornt[1]; 6469 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6470 orntNew[2] = 0; 6471 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6472 orntNew[3] = 0; 6473 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6474 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6475 #if 1 6476 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); 6477 for (p = 0; p < 4; ++p) { 6478 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); 6479 } 6480 #endif 6481 /* B quad */ 6482 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6483 orntNew[0] = ornt[0]; 6484 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6485 orntNew[1] = ornt[1]; 6486 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6487 orntNew[2] = 0; 6488 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6489 orntNew[3] = 0; 6490 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6491 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6492 #if 1 6493 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); 6494 for (p = 0; p < 4; ++p) { 6495 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); 6496 } 6497 #endif 6498 } 6499 /* Interior split faces have 2 vertices and the same cells as the parent */ 6500 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6501 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6502 for (f = fStart; f < fMax; ++f) { 6503 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6504 6505 for (r = 0; r < 2; ++r) { 6506 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6507 const PetscInt *cone, *support; 6508 PetscInt coneNew[2], coneSize, c, supportSize, s; 6509 6510 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6511 coneNew[0] = vStartNew + (cone[0] - vStart); 6512 coneNew[1] = vStartNew + (cone[1] - vStart); 6513 coneNew[(r+1)%2] = newv; 6514 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6515 #if 1 6516 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6517 for (p = 0; p < 2; ++p) { 6518 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); 6519 } 6520 #endif 6521 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6522 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6523 for (s = 0; s < supportSize; ++s) { 6524 if (support[s] >= cMax) { 6525 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6526 } else { 6527 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6528 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6529 for (c = 0; c < coneSize; ++c) { 6530 if (cone[c] == f) { 6531 break; 6532 } 6533 } 6534 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6535 } 6536 } 6537 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6538 #if 1 6539 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6540 for (p = 0; p < supportSize; ++p) { 6541 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); 6542 } 6543 #endif 6544 } 6545 } 6546 /* Interior cell faces have 2 vertices and 2 cells */ 6547 for (c = cStart; c < cMax; ++c) { 6548 const PetscInt *cone; 6549 6550 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6551 for (r = 0; r < 3; ++r) { 6552 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6553 PetscInt coneNew[2]; 6554 PetscInt supportNew[2]; 6555 6556 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6557 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6558 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6559 #if 1 6560 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6561 for (p = 0; p < 2; ++p) { 6562 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); 6563 } 6564 #endif 6565 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6566 supportNew[1] = (c - cStart)*4 + 3; 6567 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6568 #if 1 6569 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6570 for (p = 0; p < 2; ++p) { 6571 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); 6572 } 6573 #endif 6574 } 6575 } 6576 /* Interior hybrid faces have 2 vertices and the same cells */ 6577 for (f = fMax; f < fEnd; ++f) { 6578 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6579 const PetscInt *cone; 6580 const PetscInt *support; 6581 PetscInt coneNew[2]; 6582 PetscInt supportNew[2]; 6583 PetscInt size, s, r; 6584 6585 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6586 coneNew[0] = vStartNew + (cone[0] - vStart); 6587 coneNew[1] = vStartNew + (cone[1] - vStart); 6588 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6589 #if 1 6590 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6591 for (p = 0; p < 2; ++p) { 6592 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); 6593 } 6594 #endif 6595 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6596 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6597 for (s = 0; s < size; ++s) { 6598 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6599 for (r = 0; r < 2; ++r) { 6600 if (cone[r+2] == f) break; 6601 } 6602 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6603 } 6604 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6605 #if 1 6606 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6607 for (p = 0; p < size; ++p) { 6608 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); 6609 } 6610 #endif 6611 } 6612 /* Cell hybrid faces have 2 vertices and 2 cells */ 6613 for (c = cMax; c < cEnd; ++c) { 6614 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6615 const PetscInt *cone; 6616 PetscInt coneNew[2]; 6617 PetscInt supportNew[2]; 6618 6619 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6620 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6621 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6622 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6623 #if 1 6624 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6625 for (p = 0; p < 2; ++p) { 6626 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); 6627 } 6628 #endif 6629 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6630 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6631 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6632 #if 1 6633 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6634 for (p = 0; p < 2; ++p) { 6635 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); 6636 } 6637 #endif 6638 } 6639 /* Old vertices have identical supports */ 6640 for (v = vStart; v < vEnd; ++v) { 6641 const PetscInt newp = vStartNew + (v - vStart); 6642 const PetscInt *support, *cone; 6643 PetscInt size, s; 6644 6645 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6646 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6647 for (s = 0; s < size; ++s) { 6648 if (support[s] >= fMax) { 6649 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6650 } else { 6651 PetscInt r = 0; 6652 6653 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6654 if (cone[1] == v) r = 1; 6655 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6656 } 6657 } 6658 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6659 #if 1 6660 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6661 for (p = 0; p < size; ++p) { 6662 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); 6663 } 6664 #endif 6665 } 6666 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6667 for (f = fStart; f < fMax; ++f) { 6668 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6669 const PetscInt *cone, *support; 6670 PetscInt size, newSize = 2, s; 6671 6672 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6673 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6674 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6675 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6676 for (s = 0; s < size; ++s) { 6677 PetscInt r = 0; 6678 6679 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6680 if (support[s] >= cMax) { 6681 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6682 newSize += 1; 6683 } else { 6684 if (cone[1] == f) r = 1; 6685 else if (cone[2] == f) r = 2; 6686 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6687 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6688 newSize += 2; 6689 } 6690 } 6691 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6692 #if 1 6693 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6694 for (p = 0; p < newSize; ++p) { 6695 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); 6696 } 6697 #endif 6698 } 6699 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6700 break; 6701 default: 6702 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6703 } 6704 PetscFunctionReturn(0); 6705 } 6706 6707 #undef __FUNCT__ 6708 #define __FUNCT__ "CellRefinerSetCoordinates" 6709 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6710 { 6711 PetscSection coordSection, coordSectionNew; 6712 Vec coordinates, coordinatesNew; 6713 PetscScalar *coords, *coordsNew; 6714 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6715 PetscErrorCode ierr; 6716 6717 PetscFunctionBegin; 6718 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6719 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6720 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6721 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6722 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6723 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6724 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6725 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6726 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6727 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6728 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6729 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6730 if (fMax < 0) fMax = fEnd; 6731 switch (refiner) { 6732 case 1: 6733 case 2: 6734 case 3: 6735 /* Simplicial and Hex 2D */ 6736 /* All vertices have the dim coordinates */ 6737 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6738 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6739 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6740 } 6741 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6742 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6743 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6744 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6745 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6746 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6747 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6748 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6749 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6750 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6751 /* Old vertices have the same coordinates */ 6752 for (v = vStart; v < vEnd; ++v) { 6753 const PetscInt newv = vStartNew + (v - vStart); 6754 PetscInt off, offnew, d; 6755 6756 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6757 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6758 for (d = 0; d < dim; ++d) { 6759 coordsNew[offnew+d] = coords[off+d]; 6760 } 6761 } 6762 /* Face vertices have the average of endpoint coordinates */ 6763 for (f = fStart; f < fMax; ++f) { 6764 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6765 const PetscInt *cone; 6766 PetscInt coneSize, offA, offB, offnew, d; 6767 6768 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6769 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6770 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6771 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6772 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6773 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6774 for (d = 0; d < dim; ++d) { 6775 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6776 } 6777 } 6778 /* Just Hex 2D */ 6779 if (refiner == 2) { 6780 /* Cell vertices have the average of corner coordinates */ 6781 for (c = cStart; c < cEnd; ++c) { 6782 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6783 PetscInt *cone = PETSC_NULL; 6784 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6785 6786 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6787 for (p = 0; p < closureSize*2; p += 2) { 6788 const PetscInt point = cone[p]; 6789 if ((point >= vStart) && (point < vEnd)) { 6790 cone[coneSize++] = point; 6791 } 6792 } 6793 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6794 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6795 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6796 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6797 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6798 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6799 for (d = 0; d < dim; ++d) { 6800 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6801 } 6802 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6803 } 6804 } 6805 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6806 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6807 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6808 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6809 break; 6810 default: 6811 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6812 } 6813 PetscFunctionReturn(0); 6814 } 6815 6816 #undef __FUNCT__ 6817 #define __FUNCT__ "DMPlexCreateProcessSF" 6818 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6819 { 6820 PetscInt numRoots, numLeaves, l; 6821 const PetscInt *localPoints; 6822 const PetscSFNode *remotePoints; 6823 PetscInt *localPointsNew; 6824 PetscSFNode *remotePointsNew; 6825 PetscInt *ranks, *ranksNew; 6826 PetscErrorCode ierr; 6827 6828 PetscFunctionBegin; 6829 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6830 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6831 for (l = 0; l < numLeaves; ++l) { 6832 ranks[l] = remotePoints[l].rank; 6833 } 6834 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6835 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6836 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6837 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6838 for (l = 0; l < numLeaves; ++l) { 6839 ranksNew[l] = ranks[l]; 6840 localPointsNew[l] = l; 6841 remotePointsNew[l].index = 0; 6842 remotePointsNew[l].rank = ranksNew[l]; 6843 } 6844 ierr = PetscFree(ranks);CHKERRQ(ierr); 6845 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6846 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6847 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6848 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6849 PetscFunctionReturn(0); 6850 } 6851 6852 #undef __FUNCT__ 6853 #define __FUNCT__ "CellRefinerCreateSF" 6854 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6855 { 6856 PetscSF sf, sfNew, sfProcess; 6857 IS processRanks; 6858 MPI_Datatype depthType; 6859 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6860 const PetscInt *localPoints, *neighbors; 6861 const PetscSFNode *remotePoints; 6862 PetscInt *localPointsNew; 6863 PetscSFNode *remotePointsNew; 6864 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6865 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6866 PetscErrorCode ierr; 6867 6868 PetscFunctionBegin; 6869 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6870 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6871 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6872 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6873 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6874 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6875 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6876 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6877 switch (refiner) { 6878 case 3: 6879 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6880 cMax = PetscMin(cEnd, cMax); 6881 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6882 fMax = PetscMin(fEnd, fMax); 6883 } 6884 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6885 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6886 /* Caculate size of new SF */ 6887 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6888 if (numRoots < 0) PetscFunctionReturn(0); 6889 for (l = 0; l < numLeaves; ++l) { 6890 const PetscInt p = localPoints[l]; 6891 6892 switch (refiner) { 6893 case 1: 6894 /* Simplicial 2D */ 6895 if ((p >= vStart) && (p < vEnd)) { 6896 /* Old vertices stay the same */ 6897 ++numLeavesNew; 6898 } else if ((p >= fStart) && (p < fEnd)) { 6899 /* Old faces add new faces and vertex */ 6900 numLeavesNew += 1 + 2; 6901 } else if ((p >= cStart) && (p < cEnd)) { 6902 /* Old cells add new cells and interior faces */ 6903 numLeavesNew += 4 + 3; 6904 } 6905 break; 6906 case 2: 6907 /* Hex 2D */ 6908 if ((p >= vStart) && (p < vEnd)) { 6909 /* Old vertices stay the same */ 6910 ++numLeavesNew; 6911 } else if ((p >= fStart) && (p < fEnd)) { 6912 /* Old faces add new faces and vertex */ 6913 numLeavesNew += 1 + 2; 6914 } else if ((p >= cStart) && (p < cEnd)) { 6915 /* Old cells add new cells and interior faces */ 6916 numLeavesNew += 4 + 4; 6917 } 6918 break; 6919 default: 6920 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6921 } 6922 } 6923 /* Communicate depthSizes for each remote rank */ 6924 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6925 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6926 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6927 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); 6928 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6929 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6930 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6931 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6932 for (n = 0; n < numNeighbors; ++n) { 6933 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6934 } 6935 depthSizeOld[depth] = cMax; 6936 depthSizeOld[0] = vMax; 6937 depthSizeOld[depth-1] = fMax; 6938 depthSizeOld[1] = eMax; 6939 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6940 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6941 depthSizeOld[depth] = cEnd - cStart; 6942 depthSizeOld[0] = vEnd - vStart; 6943 depthSizeOld[depth-1] = fEnd - fStart; 6944 depthSizeOld[1] = eEnd - eStart; 6945 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6946 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6947 for (n = 0; n < numNeighbors; ++n) { 6948 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6949 } 6950 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6951 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6952 /* Calculate new point SF */ 6953 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6954 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6955 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6956 for (l = 0, m = 0; l < numLeaves; ++l) { 6957 PetscInt p = localPoints[l]; 6958 PetscInt rp = remotePoints[l].index, n; 6959 PetscMPIInt rrank = remotePoints[l].rank; 6960 6961 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6962 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6963 switch (refiner) { 6964 case 1: 6965 /* Simplicial 2D */ 6966 if ((p >= vStart) && (p < vEnd)) { 6967 /* Old vertices stay the same */ 6968 localPointsNew[m] = vStartNew + (p - vStart); 6969 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6970 remotePointsNew[m].rank = rrank; 6971 ++m; 6972 } else if ((p >= fStart) && (p < fEnd)) { 6973 /* Old faces add new faces and vertex */ 6974 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6975 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6976 remotePointsNew[m].rank = rrank; 6977 ++m; 6978 for (r = 0; r < 2; ++r, ++m) { 6979 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6980 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6981 remotePointsNew[m].rank = rrank; 6982 } 6983 } else if ((p >= cStart) && (p < cEnd)) { 6984 /* Old cells add new cells and interior faces */ 6985 for (r = 0; r < 4; ++r, ++m) { 6986 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6987 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6988 remotePointsNew[m].rank = rrank; 6989 } 6990 for (r = 0; r < 3; ++r, ++m) { 6991 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6992 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6993 remotePointsNew[m].rank = rrank; 6994 } 6995 } 6996 break; 6997 case 2: 6998 /* Hex 2D */ 6999 if ((p >= vStart) && (p < vEnd)) { 7000 /* Old vertices stay the same */ 7001 localPointsNew[m] = vStartNew + (p - vStart); 7002 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7003 remotePointsNew[m].rank = rrank; 7004 ++m; 7005 } else if ((p >= fStart) && (p < fEnd)) { 7006 /* Old faces add new faces and vertex */ 7007 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7008 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7009 remotePointsNew[m].rank = rrank; 7010 ++m; 7011 for (r = 0; r < 2; ++r, ++m) { 7012 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7013 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7014 remotePointsNew[m].rank = rrank; 7015 } 7016 } else if ((p >= cStart) && (p < cEnd)) { 7017 /* Old cells add new cells and interior faces */ 7018 for (r = 0; r < 4; ++r, ++m) { 7019 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7020 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7021 remotePointsNew[m].rank = rrank; 7022 } 7023 for (r = 0; r < 4; ++r, ++m) { 7024 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7025 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7026 remotePointsNew[m].rank = rrank; 7027 } 7028 } 7029 break; 7030 case 3: 7031 /* Hybrid simplicial 2D */ 7032 if ((p >= vStart) && (p < vEnd)) { 7033 /* Old vertices stay the same */ 7034 localPointsNew[m] = vStartNew + (p - vStart); 7035 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7036 remotePointsNew[m].rank = rrank; 7037 ++m; 7038 } else if ((p >= fStart) && (p < fMax)) { 7039 /* Old interior faces add new faces and vertex */ 7040 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7041 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7042 remotePointsNew[m].rank = rrank; 7043 ++m; 7044 for (r = 0; r < 2; ++r, ++m) { 7045 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7046 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7047 remotePointsNew[m].rank = rrank; 7048 } 7049 } else if ((p >= fMax) && (p < fEnd)) { 7050 /* Old hybrid faces stay the same */ 7051 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7052 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7053 remotePointsNew[m].rank = rrank; 7054 ++m; 7055 } else if ((p >= cStart) && (p < cMax)) { 7056 /* Old interior cells add new cells and interior faces */ 7057 for (r = 0; r < 4; ++r, ++m) { 7058 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7059 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7060 remotePointsNew[m].rank = rrank; 7061 } 7062 for (r = 0; r < 3; ++r, ++m) { 7063 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7064 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7065 remotePointsNew[m].rank = rrank; 7066 } 7067 } else if ((p >= cStart) && (p < cMax)) { 7068 /* Old hybrid cells add new cells and hybrid face */ 7069 for (r = 0; r < 2; ++r, ++m) { 7070 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7071 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7072 remotePointsNew[m].rank = rrank; 7073 } 7074 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7075 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]); 7076 remotePointsNew[m].rank = rrank; 7077 ++m; 7078 } 7079 break; 7080 default: 7081 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7082 } 7083 } 7084 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7085 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7086 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7087 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7088 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7089 PetscFunctionReturn(0); 7090 } 7091 7092 #undef __FUNCT__ 7093 #define __FUNCT__ "CellRefinerCreateLabels" 7094 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7095 { 7096 PetscInt numLabels, l; 7097 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7098 PetscErrorCode ierr; 7099 7100 PetscFunctionBegin; 7101 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7102 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7103 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7104 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7105 cStartNew = 0; 7106 vStartNew = depthSize[2]; 7107 fStartNew = depthSize[2] + depthSize[0]; 7108 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7109 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7110 switch (refiner) { 7111 case 3: 7112 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7113 cMax = PetscMin(cEnd, cMax); 7114 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7115 fMax = PetscMin(fEnd, fMax); 7116 } 7117 for (l = 0; l < numLabels; ++l) { 7118 DMLabel label, labelNew; 7119 const char *lname; 7120 PetscBool isDepth; 7121 IS valueIS; 7122 const PetscInt *values; 7123 PetscInt numValues, val; 7124 7125 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7126 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7127 if (isDepth) continue; 7128 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7129 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7130 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7131 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7132 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7133 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7134 for (val = 0; val < numValues; ++val) { 7135 IS pointIS; 7136 const PetscInt *points; 7137 PetscInt numPoints, n; 7138 7139 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7140 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7141 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7142 for (n = 0; n < numPoints; ++n) { 7143 const PetscInt p = points[n]; 7144 switch (refiner) { 7145 case 1: 7146 /* Simplicial 2D */ 7147 if ((p >= vStart) && (p < vEnd)) { 7148 /* Old vertices stay the same */ 7149 newp = vStartNew + (p - vStart); 7150 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7151 } else if ((p >= fStart) && (p < fEnd)) { 7152 /* Old faces add new faces and vertex */ 7153 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7154 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7155 for (r = 0; r < 2; ++r) { 7156 newp = fStartNew + (p - fStart)*2 + r; 7157 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7158 } 7159 } else if ((p >= cStart) && (p < cEnd)) { 7160 /* Old cells add new cells and interior faces */ 7161 for (r = 0; r < 4; ++r) { 7162 newp = cStartNew + (p - cStart)*4 + r; 7163 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7164 } 7165 for (r = 0; r < 3; ++r) { 7166 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7167 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7168 } 7169 } 7170 break; 7171 case 2: 7172 /* Hex 2D */ 7173 if ((p >= vStart) && (p < vEnd)) { 7174 /* Old vertices stay the same */ 7175 newp = vStartNew + (p - vStart); 7176 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7177 } else if ((p >= fStart) && (p < fEnd)) { 7178 /* Old faces add new faces and vertex */ 7179 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7180 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7181 for (r = 0; r < 2; ++r) { 7182 newp = fStartNew + (p - fStart)*2 + r; 7183 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7184 } 7185 } else if ((p >= cStart) && (p < cEnd)) { 7186 /* Old cells add new cells and interior faces and vertex */ 7187 for (r = 0; r < 4; ++r) { 7188 newp = cStartNew + (p - cStart)*4 + r; 7189 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7190 } 7191 for (r = 0; r < 4; ++r) { 7192 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7193 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7194 } 7195 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7196 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7197 } 7198 break; 7199 case 3: 7200 /* Hybrid simplicial 2D */ 7201 if ((p >= vStart) && (p < vEnd)) { 7202 /* Old vertices stay the same */ 7203 newp = vStartNew + (p - vStart); 7204 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7205 } else if ((p >= fStart) && (p < fMax)) { 7206 /* Old interior faces add new faces and vertex */ 7207 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7208 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7209 for (r = 0; r < 2; ++r) { 7210 newp = fStartNew + (p - fStart)*2 + r; 7211 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7212 } 7213 } else if ((p >= fMax) && (p < fEnd)) { 7214 /* Old hybrid faces stay the same */ 7215 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7216 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7217 } else if ((p >= cStart) && (p < cMax)) { 7218 /* Old interior cells add new cells and interior faces */ 7219 for (r = 0; r < 4; ++r) { 7220 newp = cStartNew + (p - cStart)*4 + r; 7221 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7222 } 7223 for (r = 0; r < 3; ++r) { 7224 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7225 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7226 } 7227 } else if ((p >= cMax) && (p < cEnd)) { 7228 /* Old hybrid cells add new cells and hybrid face */ 7229 for (r = 0; r < 2; ++r) { 7230 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7231 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7232 } 7233 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7234 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7235 } 7236 break; 7237 default: 7238 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7239 } 7240 } 7241 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7242 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7243 } 7244 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7245 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7246 if (0) { 7247 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7248 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7249 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7250 } 7251 } 7252 PetscFunctionReturn(0); 7253 } 7254 7255 #undef __FUNCT__ 7256 #define __FUNCT__ "DMPlexRefine_Uniform" 7257 /* This will only work for interpolated meshes */ 7258 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7259 { 7260 DM rdm; 7261 PetscInt *depthSize; 7262 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7263 PetscErrorCode ierr; 7264 7265 PetscFunctionBegin; 7266 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7267 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7268 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7269 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7270 /* Calculate number of new points of each depth */ 7271 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7272 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7273 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7274 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7275 /* Step 1: Set chart */ 7276 for (d = 0; d <= depth; ++d) { 7277 pEnd += depthSize[d]; 7278 } 7279 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7280 /* Step 2: Set cone/support sizes */ 7281 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7282 /* Step 3: Setup refined DM */ 7283 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7284 /* Step 4: Set cones and supports */ 7285 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7286 /* Step 5: Stratify */ 7287 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7288 /* Step 6: Set coordinates for vertices */ 7289 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7290 /* Step 7: Create pointSF */ 7291 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7292 /* Step 8: Create labels */ 7293 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7294 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7295 7296 *dmRefined = rdm; 7297 #if 0 7298 DM_Plex *mesh = (DM_Plex *) dm->data; 7299 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 7300 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 7301 7302 PetscFunctionBegin; 7303 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7304 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 7305 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7306 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7307 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 7308 7309 /* Count number of new cells which are normal and extra */ 7310 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 7311 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 7312 for (c = cStart; c < cEnd2; ++c) { 7313 PetscInt n; 7314 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7315 newNumCellsNormal += n; 7316 } 7317 for (c = cEnd2; c < cEnd; ++c) { 7318 PetscInt n; 7319 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7320 newNumCellsExtra += n; 7321 } 7322 newNumCells = newNumCellsNormal + newNumCellsExtra; 7323 /* Count number of new vertices which are normal and extra */ 7324 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 7325 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 7326 for (c = cStart; c < cEnd; ++c) { 7327 PetscInt *closure = PETSC_NULL; 7328 PetscInt closureSize, numCorners = 0, p; 7329 7330 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7331 for (p = 0; p < closureSize*2; p += 2) { 7332 const PetscInt point = closure[p]; 7333 if ((point >= vStart) && (point < vEnd)) { 7334 closure[numCorners++] = point; 7335 } 7336 } 7337 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 7338 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7339 } 7340 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 7341 for (c = cEnd2; c < cEnd; ++c) { 7342 PetscInt *closure = PETSC_NULL; 7343 PetscInt closureSize, numCorners = 0, p; 7344 7345 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7346 for (p = 0; p < closureSize*2; p += 2) { 7347 const PetscInt point = closure[p]; 7348 if ((point >= vStart) && (point < vEnd)) { 7349 closure[numCorners++] = point; 7350 } 7351 } 7352 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 7353 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7354 } /* for */ 7355 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 7356 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 7357 7358 #if 1 7359 PetscInt oldNumCellsNormal = cEnd2 - cStart; 7360 PetscInt oldNumCellsExtra = cEnd - cEnd2; 7361 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 7362 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 7363 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 7364 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 7365 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 7366 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 7367 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 7368 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 7369 ierr = PetscSynchronizedFlush(comm); 7370 #endif 7371 7372 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 7373 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 7374 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 7375 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 7376 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 7377 /* Set cone and support sizes for new normal cells */ 7378 PetscInt newCell = 0; 7379 for (c = cStart; c < cEnd2; ++c) { 7380 PetscInt coneSize, n, i; 7381 7382 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7383 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7384 for (i = 0; i < n; ++i, ++newCell) { 7385 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 7386 } 7387 7388 PetscInt *closure = PETSC_NULL; 7389 PetscInt closureSize, numCorners = 0, p; 7390 7391 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7392 for (p = 0; p < closureSize*2; p += 2) { 7393 const PetscInt point = closure[p]; 7394 if ((point >= vStart) && (point < vEnd)) { 7395 closure[numCorners++] = point; 7396 } 7397 } 7398 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); */ /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7399 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7400 } 7401 7402 /* Reset current new cell value and loop over censored cells. */ 7403 curNewCell = _orderNewMesh->cellsCensored().min(); 7404 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7405 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7406 /* Set new cone and support sizes */ 7407 cV.clear(); 7408 sieve->cone(*c_iter, cV); 7409 const point_type* cone = cV.getPoints(); 7410 const int coneSize = cV.getSize(); 7411 7412 const point_type* newCells; 7413 int numNewCells = 0; 7414 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7415 7416 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7417 newSieve->setConeSize(curNewCell, coneSize); 7418 for (int iVertex=0; iVertex < coneSize; ++iVertex) { 7419 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7420 } /* for */ 7421 } /* for */ 7422 } /* for */ 7423 newSieve->allocate(); 7424 7425 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7426 7427 /* Create refined cells in new sieve. */ 7428 curNewCell = _orderNewMesh->cellsNormal().min(); 7429 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7430 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7431 cV.clear(); 7432 sieve->cone(*c_iter, cV); 7433 const point_type *cone = cV.getPoints(); 7434 const int coneSize = cV.getSize(); 7435 7436 const point_type* newCells; 7437 int numNewCells = 0; 7438 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7439 7440 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7441 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7442 } /* for */ 7443 } /* for */ 7444 curNewCell = _orderNewMesh->cellsCensored().min(); 7445 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7446 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7447 cV.clear(); 7448 sieve->cone(*c_iter, cV); 7449 const point_type *cone = cV.getPoints(); 7450 const int coneSize = cV.getSize(); 7451 7452 const point_type* newCells; 7453 int numNewCells = 0; 7454 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7455 7456 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7457 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7458 } /* for */ 7459 } /* for */ 7460 newSieve->symmetrize(); 7461 7462 /* Set coordinates in refined mesh. */ 7463 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7464 assert(!coordinates.isNull()); 7465 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7466 assert(!newCoordinates.isNull()); 7467 7468 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7469 assert(vertices->size() > 0); 7470 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7471 assert(spaceDim > 0); 7472 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7473 7474 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7475 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7476 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7477 } /* for */ 7478 newCoordinates->allocatePoint(); 7479 7480 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7481 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7482 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7483 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7484 } /* for */ 7485 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7486 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7487 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7488 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7489 } /* for */ 7490 7491 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7492 7493 /* Create sensored depth */ 7494 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7495 assert(!censoredLabel.isNull()); 7496 7497 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7498 7499 newSieve->roots(depthVisitor); 7500 while (depthVisitor.isModified()) { 7501 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7502 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7503 7504 depthVisitor.clear(); 7505 newSieve->support(modifiedPoints, depthVisitor); 7506 } /* while */ 7507 /* Stratify refined mesh */ 7508 /* Calculate new point SF */ 7509 _calcNewOverlap(newMesh, mesh, refiner); 7510 /* Calculate new labels */ 7511 _createLabels(newMesh, mesh, refiner); 7512 #endif 7513 PetscFunctionReturn(0); 7514 } 7515 7516 #undef __FUNCT__ 7517 #define __FUNCT__ "DMPlexSetRefinementUniform" 7518 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7519 { 7520 DM_Plex *mesh = (DM_Plex *) dm->data; 7521 7522 PetscFunctionBegin; 7523 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7524 mesh->refinementUniform = refinementUniform; 7525 PetscFunctionReturn(0); 7526 } 7527 7528 #undef __FUNCT__ 7529 #define __FUNCT__ "DMPlexGetRefinementUniform" 7530 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7531 { 7532 DM_Plex *mesh = (DM_Plex *) dm->data; 7533 7534 PetscFunctionBegin; 7535 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7536 PetscValidPointer(refinementUniform, 2); 7537 *refinementUniform = mesh->refinementUniform; 7538 PetscFunctionReturn(0); 7539 } 7540 7541 #undef __FUNCT__ 7542 #define __FUNCT__ "DMPlexSetRefinementLimit" 7543 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7544 { 7545 DM_Plex *mesh = (DM_Plex *) dm->data; 7546 7547 PetscFunctionBegin; 7548 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7549 mesh->refinementLimit = refinementLimit; 7550 PetscFunctionReturn(0); 7551 } 7552 7553 #undef __FUNCT__ 7554 #define __FUNCT__ "DMPlexGetRefinementLimit" 7555 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7556 { 7557 DM_Plex *mesh = (DM_Plex *) dm->data; 7558 7559 PetscFunctionBegin; 7560 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7561 PetscValidPointer(refinementLimit, 2); 7562 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7563 *refinementLimit = mesh->refinementLimit; 7564 PetscFunctionReturn(0); 7565 } 7566 7567 #undef __FUNCT__ 7568 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7569 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7570 { 7571 PetscInt dim, cStart, coneSize, cMax; 7572 PetscErrorCode ierr; 7573 7574 PetscFunctionBegin; 7575 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7576 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7577 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7578 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7579 switch (dim) { 7580 case 2: 7581 switch (coneSize) { 7582 case 3: 7583 if (cMax >= 0) { 7584 *cellRefiner = 3; /* Hybrid */ 7585 } else { 7586 *cellRefiner = 1; /* Triangular */ 7587 } 7588 break; 7589 case 4: 7590 if (cMax >= 0) { 7591 *cellRefiner = 4; /* Hybrid */ 7592 } else { 7593 *cellRefiner = 2; /* Quadrilateral */ 7594 } 7595 break; 7596 default: 7597 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7598 } 7599 break; 7600 default: 7601 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7602 } 7603 PetscFunctionReturn(0); 7604 } 7605 7606 #undef __FUNCT__ 7607 #define __FUNCT__ "DMRefine_Plex" 7608 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7609 { 7610 PetscReal refinementLimit; 7611 PetscInt dim, cStart, cEnd; 7612 char genname[1024], *name = PETSC_NULL; 7613 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7614 PetscErrorCode ierr; 7615 7616 PetscFunctionBegin; 7617 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7618 if (isUniform) { 7619 CellRefiner cellRefiner; 7620 7621 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7622 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7623 PetscFunctionReturn(0); 7624 } 7625 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7626 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7627 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7628 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7629 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7630 if (flg) {name = genname;} 7631 if (name) { 7632 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7633 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7634 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7635 } 7636 switch (dim) { 7637 case 2: 7638 if (!name || isTriangle) { 7639 #if defined(PETSC_HAVE_TRIANGLE) 7640 double *maxVolumes; 7641 PetscInt c; 7642 7643 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7644 for (c = 0; c < cEnd-cStart; ++c) { 7645 maxVolumes[c] = refinementLimit; 7646 } 7647 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7648 #else 7649 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7650 #endif 7651 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7652 break; 7653 case 3: 7654 if (!name || isCTetgen) { 7655 #if defined(PETSC_HAVE_CTETGEN) 7656 PetscReal *maxVolumes; 7657 PetscInt c; 7658 7659 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7660 for (c = 0; c < cEnd-cStart; ++c) { 7661 maxVolumes[c] = refinementLimit; 7662 } 7663 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7664 #else 7665 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7666 #endif 7667 } else if (isTetgen) { 7668 #if defined(PETSC_HAVE_TETGEN) 7669 double *maxVolumes; 7670 PetscInt c; 7671 7672 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7673 for (c = 0; c < cEnd-cStart; ++c) { 7674 maxVolumes[c] = refinementLimit; 7675 } 7676 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7677 #else 7678 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7679 #endif 7680 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7681 break; 7682 default: 7683 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7684 } 7685 PetscFunctionReturn(0); 7686 } 7687 7688 #undef __FUNCT__ 7689 #define __FUNCT__ "DMPlexGetDepth" 7690 /*@ 7691 DMPlexGetDepth - get the number of strata 7692 7693 Not Collective 7694 7695 Input Parameters: 7696 . dm - The DMPlex object 7697 7698 Output Parameters: 7699 . depth - number of strata 7700 7701 Level: developer 7702 7703 Notes: 7704 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7705 7706 .keywords: mesh, points 7707 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7708 @*/ 7709 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7710 { 7711 PetscInt d; 7712 PetscErrorCode ierr; 7713 7714 PetscFunctionBegin; 7715 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7716 PetscValidPointer(depth, 2); 7717 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7718 *depth = d-1; 7719 PetscFunctionReturn(0); 7720 } 7721 7722 #undef __FUNCT__ 7723 #define __FUNCT__ "DMPlexGetDepthStratum" 7724 /*@ 7725 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7726 7727 Not Collective 7728 7729 Input Parameters: 7730 + dm - The DMPlex object 7731 - stratumValue - The requested depth 7732 7733 Output Parameters: 7734 + start - The first point at this depth 7735 - end - One beyond the last point at this depth 7736 7737 Level: developer 7738 7739 .keywords: mesh, points 7740 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7741 @*/ 7742 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7743 { 7744 DM_Plex *mesh = (DM_Plex *) dm->data; 7745 DMLabel next = mesh->labels; 7746 PetscBool flg = PETSC_FALSE; 7747 PetscInt depth; 7748 PetscErrorCode ierr; 7749 7750 PetscFunctionBegin; 7751 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7752 if (stratumValue < 0) { 7753 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7754 PetscFunctionReturn(0); 7755 } else { 7756 PetscInt pStart, pEnd; 7757 7758 if (start) {*start = 0;} 7759 if (end) {*end = 0;} 7760 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7761 if (pStart == pEnd) {PetscFunctionReturn(0);} 7762 } 7763 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7764 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7765 /* We should have a generic GetLabel() and a Label class */ 7766 while (next) { 7767 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7768 if (flg) break; 7769 next = next->next; 7770 } 7771 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7772 depth = stratumValue; 7773 if ((depth < 0) || (depth >= next->numStrata)) { 7774 if (start) {*start = 0;} 7775 if (end) {*end = 0;} 7776 } else { 7777 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7778 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7779 } 7780 PetscFunctionReturn(0); 7781 } 7782 7783 #undef __FUNCT__ 7784 #define __FUNCT__ "DMPlexGetHeightStratum" 7785 /*@ 7786 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7787 7788 Not Collective 7789 7790 Input Parameters: 7791 + dm - The DMPlex object 7792 - stratumValue - The requested height 7793 7794 Output Parameters: 7795 + start - The first point at this height 7796 - end - One beyond the last point at this height 7797 7798 Level: developer 7799 7800 .keywords: mesh, points 7801 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7802 @*/ 7803 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7804 { 7805 DM_Plex *mesh = (DM_Plex *) dm->data; 7806 DMLabel next = mesh->labels; 7807 PetscBool flg = PETSC_FALSE; 7808 PetscInt depth; 7809 PetscErrorCode ierr; 7810 7811 PetscFunctionBegin; 7812 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7813 if (stratumValue < 0) { 7814 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7815 } else { 7816 PetscInt pStart, pEnd; 7817 7818 if (start) {*start = 0;} 7819 if (end) {*end = 0;} 7820 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7821 if (pStart == pEnd) {PetscFunctionReturn(0);} 7822 } 7823 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7824 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7825 /* We should have a generic GetLabel() and a Label class */ 7826 while (next) { 7827 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7828 if (flg) break; 7829 next = next->next; 7830 } 7831 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7832 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7833 if ((depth < 0) || (depth >= next->numStrata)) { 7834 if (start) {*start = 0;} 7835 if (end) {*end = 0;} 7836 } else { 7837 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7838 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7839 } 7840 PetscFunctionReturn(0); 7841 } 7842 7843 #undef __FUNCT__ 7844 #define __FUNCT__ "DMPlexCreateSectionInitial" 7845 /* Set the number of dof on each point and separate by fields */ 7846 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7847 { 7848 PetscInt *numDofTot; 7849 PetscInt pStart = 0, pEnd = 0; 7850 PetscInt p, d, f; 7851 PetscErrorCode ierr; 7852 7853 PetscFunctionBegin; 7854 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7855 for (d = 0; d <= dim; ++d) { 7856 numDofTot[d] = 0; 7857 for (f = 0; f < numFields; ++f) { 7858 numDofTot[d] += numDof[f*(dim+1)+d]; 7859 } 7860 } 7861 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7862 if (numFields > 0) { 7863 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7864 if (numComp) { 7865 for (f = 0; f < numFields; ++f) { 7866 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7867 } 7868 } 7869 } 7870 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7871 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7872 for (d = 0; d <= dim; ++d) { 7873 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7874 for (p = pStart; p < pEnd; ++p) { 7875 for (f = 0; f < numFields; ++f) { 7876 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7877 } 7878 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7879 } 7880 } 7881 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7882 PetscFunctionReturn(0); 7883 } 7884 7885 #undef __FUNCT__ 7886 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7887 /* Set the number of dof on each point and separate by fields 7888 If constDof is PETSC_DETERMINE, constrain every dof on the point 7889 */ 7890 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7891 { 7892 PetscInt numFields; 7893 PetscInt bc; 7894 PetscErrorCode ierr; 7895 7896 PetscFunctionBegin; 7897 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7898 for (bc = 0; bc < numBC; ++bc) { 7899 PetscInt field = 0; 7900 const PetscInt *idx; 7901 PetscInt n, i; 7902 7903 if (numFields) {field = bcField[bc];} 7904 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7905 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7906 for (i = 0; i < n; ++i) { 7907 const PetscInt p = idx[i]; 7908 PetscInt numConst = constDof; 7909 7910 /* Constrain every dof on the point */ 7911 if (numConst < 0) { 7912 if (numFields) { 7913 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7914 } else { 7915 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7916 } 7917 } 7918 if (numFields) { 7919 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7920 } 7921 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7922 } 7923 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7924 } 7925 PetscFunctionReturn(0); 7926 } 7927 7928 #undef __FUNCT__ 7929 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7930 /* Set the constrained indices on each point and separate by fields */ 7931 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7932 { 7933 PetscInt *maxConstraints; 7934 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7935 PetscErrorCode ierr; 7936 7937 PetscFunctionBegin; 7938 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7939 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7940 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7941 for (f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 7942 for (p = pStart; p < pEnd; ++p) { 7943 PetscInt cdof; 7944 7945 if (numFields) { 7946 for (f = 0; f < numFields; ++f) { 7947 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7948 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7949 } 7950 } else { 7951 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7952 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7953 } 7954 } 7955 for (f = 0; f < numFields; ++f) { 7956 maxConstraints[numFields] += maxConstraints[f]; 7957 } 7958 if (maxConstraints[numFields]) { 7959 PetscInt *indices; 7960 7961 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7962 for (p = pStart; p < pEnd; ++p) { 7963 PetscInt cdof, d; 7964 7965 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7966 if (cdof) { 7967 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7968 if (numFields) { 7969 PetscInt numConst = 0, foff = 0; 7970 7971 for (f = 0; f < numFields; ++f) { 7972 PetscInt cfdof, fdof; 7973 7974 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7975 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7976 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7977 for (d = 0; d < cfdof; ++d) { 7978 indices[numConst+d] = d; 7979 } 7980 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7981 for (d = 0; d < cfdof; ++d) { 7982 indices[numConst+d] += foff; 7983 } 7984 numConst += cfdof; 7985 foff += fdof; 7986 } 7987 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7988 } else { 7989 for (d = 0; d < cdof; ++d) { 7990 indices[d] = d; 7991 } 7992 } 7993 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7994 } 7995 } 7996 ierr = PetscFree(indices);CHKERRQ(ierr); 7997 } 7998 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7999 PetscFunctionReturn(0); 8000 } 8001 8002 #undef __FUNCT__ 8003 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 8004 /* Set the constrained field indices on each point */ 8005 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 8006 { 8007 const PetscInt *points, *indices; 8008 PetscInt numFields, maxDof, numPoints, p, numConstraints; 8009 PetscErrorCode ierr; 8010 8011 PetscFunctionBegin; 8012 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8013 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 8014 8015 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 8016 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 8017 if (!constraintIndices) { 8018 PetscInt *idx, i; 8019 8020 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8021 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 8022 for (i = 0; i < maxDof; ++i) {idx[i] = i;} 8023 for (p = 0; p < numPoints; ++p) { 8024 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 8025 } 8026 ierr = PetscFree(idx);CHKERRQ(ierr); 8027 } else { 8028 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 8029 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 8030 for (p = 0; p < numPoints; ++p) { 8031 PetscInt fcdof; 8032 8033 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 8034 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); 8035 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 8036 } 8037 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 8038 } 8039 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 8040 PetscFunctionReturn(0); 8041 } 8042 8043 #undef __FUNCT__ 8044 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 8045 /* Set the constrained indices on each point and separate by fields */ 8046 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 8047 { 8048 PetscInt *indices; 8049 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 8050 PetscErrorCode ierr; 8051 8052 PetscFunctionBegin; 8053 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8054 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8055 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8056 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 8057 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8058 for (p = pStart; p < pEnd; ++p) { 8059 PetscInt cdof, d; 8060 8061 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8062 if (cdof) { 8063 PetscInt numConst = 0, foff = 0; 8064 8065 for (f = 0; f < numFields; ++f) { 8066 const PetscInt *fcind; 8067 PetscInt fdof, fcdof; 8068 8069 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8070 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8071 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 8072 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8073 for (d = 0; d < fcdof; ++d) { 8074 indices[numConst+d] = fcind[d]+foff; 8075 } 8076 foff += fdof; 8077 numConst += fcdof; 8078 } 8079 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8080 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8081 } 8082 } 8083 ierr = PetscFree(indices);CHKERRQ(ierr); 8084 PetscFunctionReturn(0); 8085 } 8086 8087 #undef __FUNCT__ 8088 #define __FUNCT__ "DMPlexCreateSection" 8089 /*@C 8090 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8091 8092 Not Collective 8093 8094 Input Parameters: 8095 + dm - The DMPlex object 8096 . dim - The spatial dimension of the problem 8097 . numFields - The number of fields in the problem 8098 . numComp - An array of size numFields that holds the number of components for each field 8099 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8100 . numBC - The number of boundary conditions 8101 . bcField - An array of size numBC giving the field number for each boundry condition 8102 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8103 8104 Output Parameter: 8105 . section - The PetscSection object 8106 8107 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 8108 nubmer of dof for field 0 on each edge. 8109 8110 Level: developer 8111 8112 .keywords: mesh, elements 8113 .seealso: DMPlexCreate(), PetscSectionCreate() 8114 @*/ 8115 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8116 { 8117 PetscErrorCode ierr; 8118 8119 PetscFunctionBegin; 8120 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8121 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8122 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8123 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8124 { 8125 PetscBool view = PETSC_FALSE; 8126 8127 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8128 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8129 } 8130 PetscFunctionReturn(0); 8131 } 8132 8133 #undef __FUNCT__ 8134 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8135 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8136 { 8137 PetscSection section; 8138 PetscErrorCode ierr; 8139 8140 PetscFunctionBegin; 8141 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8142 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8143 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8144 PetscFunctionReturn(0); 8145 } 8146 8147 #undef __FUNCT__ 8148 #define __FUNCT__ "DMPlexGetCoordinateSection" 8149 /*@ 8150 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8151 8152 Not Collective 8153 8154 Input Parameter: 8155 . dm - The DMPlex object 8156 8157 Output Parameter: 8158 . section - The PetscSection object 8159 8160 Level: intermediate 8161 8162 .keywords: mesh, coordinates 8163 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8164 @*/ 8165 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8166 { 8167 DM cdm; 8168 PetscErrorCode ierr; 8169 8170 PetscFunctionBegin; 8171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8172 PetscValidPointer(section, 2); 8173 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8174 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8175 PetscFunctionReturn(0); 8176 } 8177 8178 #undef __FUNCT__ 8179 #define __FUNCT__ "DMPlexSetCoordinateSection" 8180 /*@ 8181 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8182 8183 Not Collective 8184 8185 Input Parameters: 8186 + dm - The DMPlex object 8187 - section - The PetscSection object 8188 8189 Level: intermediate 8190 8191 .keywords: mesh, coordinates 8192 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8193 @*/ 8194 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8195 { 8196 DM cdm; 8197 PetscErrorCode ierr; 8198 8199 PetscFunctionBegin; 8200 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8201 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8202 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8203 PetscFunctionReturn(0); 8204 } 8205 8206 #undef __FUNCT__ 8207 #define __FUNCT__ "DMPlexGetConeSection" 8208 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8209 { 8210 DM_Plex *mesh = (DM_Plex *) dm->data; 8211 8212 PetscFunctionBegin; 8213 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8214 if (section) *section = mesh->coneSection; 8215 PetscFunctionReturn(0); 8216 } 8217 8218 #undef __FUNCT__ 8219 #define __FUNCT__ "DMPlexGetCones" 8220 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8221 { 8222 DM_Plex *mesh = (DM_Plex *) dm->data; 8223 8224 PetscFunctionBegin; 8225 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8226 if (cones) *cones = mesh->cones; 8227 PetscFunctionReturn(0); 8228 } 8229 8230 #undef __FUNCT__ 8231 #define __FUNCT__ "DMPlexGetConeOrientations" 8232 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8233 { 8234 DM_Plex *mesh = (DM_Plex *) dm->data; 8235 8236 PetscFunctionBegin; 8237 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8238 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8239 PetscFunctionReturn(0); 8240 } 8241 8242 #undef __FUNCT__ 8243 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8244 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8245 { 8246 const PetscInt embedDim = 2; 8247 PetscReal x = PetscRealPart(point[0]); 8248 PetscReal y = PetscRealPart(point[1]); 8249 PetscReal v0[2], J[4], invJ[4], detJ; 8250 PetscReal xi, eta; 8251 PetscErrorCode ierr; 8252 8253 PetscFunctionBegin; 8254 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8255 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8256 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8257 8258 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 8259 *cell = c; 8260 } else { 8261 *cell = -1; 8262 } 8263 PetscFunctionReturn(0); 8264 } 8265 8266 #undef __FUNCT__ 8267 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8268 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8269 { 8270 PetscSection coordSection; 8271 Vec coordsLocal; 8272 const PetscScalar *coords; 8273 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8274 PetscReal x = PetscRealPart(point[0]); 8275 PetscReal y = PetscRealPart(point[1]); 8276 PetscInt crossings = 0, f; 8277 PetscErrorCode ierr; 8278 8279 PetscFunctionBegin; 8280 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8281 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8282 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8283 for (f = 0; f < 4; ++f) { 8284 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8285 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8286 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8287 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8288 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8289 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8290 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8291 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8292 if ((cond1 || cond2) && above) ++crossings; 8293 } 8294 if (crossings % 2) { 8295 *cell = c; 8296 } else { 8297 *cell = -1; 8298 } 8299 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8300 PetscFunctionReturn(0); 8301 } 8302 8303 #undef __FUNCT__ 8304 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8305 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8306 { 8307 const PetscInt embedDim = 3; 8308 PetscReal v0[3], J[9], invJ[9], detJ; 8309 PetscReal x = PetscRealPart(point[0]); 8310 PetscReal y = PetscRealPart(point[1]); 8311 PetscReal z = PetscRealPart(point[2]); 8312 PetscReal xi, eta, zeta; 8313 PetscErrorCode ierr; 8314 8315 PetscFunctionBegin; 8316 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8317 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8318 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8319 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8320 8321 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 8322 *cell = c; 8323 } else { 8324 *cell = -1; 8325 } 8326 PetscFunctionReturn(0); 8327 } 8328 8329 #undef __FUNCT__ 8330 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8331 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8332 { 8333 PetscSection coordSection; 8334 Vec coordsLocal; 8335 const PetscScalar *coords; 8336 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8337 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8338 PetscBool found = PETSC_TRUE; 8339 PetscInt f; 8340 PetscErrorCode ierr; 8341 8342 PetscFunctionBegin; 8343 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8344 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8345 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8346 for (f = 0; f < 6; ++f) { 8347 /* Check the point is under plane */ 8348 /* Get face normal */ 8349 PetscReal v_i[3] = {PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]), 8350 PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]), 8351 PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2])}; 8352 PetscReal v_j[3] = {PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]), 8353 PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]), 8354 PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2])}; 8355 PetscReal normal[3] = {v_i[1]*v_j[2] - v_i[2]*v_j[1], v_i[2]*v_j[0] - v_i[0]*v_j[2], v_i[0]*v_j[1] - v_i[1]*v_j[0]}; 8356 PetscReal pp[3] = {PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]), 8357 PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]), 8358 PetscRealPart(coords[faces[f*4+0]*3+2] - point[2])}; 8359 PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8360 /* Check that projected point is in face (2D location problem) */ 8361 if (dot < 0.0) { 8362 found = PETSC_FALSE; 8363 break; 8364 } 8365 } 8366 if (found) { 8367 *cell = c; 8368 } else { 8369 *cell = -1; 8370 } 8371 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8372 PetscFunctionReturn(0); 8373 } 8374 8375 #undef __FUNCT__ 8376 #define __FUNCT__ "DMLocatePoints_Plex" 8377 /* 8378 Need to implement using the guess 8379 */ 8380 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8381 { 8382 PetscInt cell = -1/*, guess = -1*/; 8383 PetscInt bs, numPoints, p; 8384 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8385 PetscInt *cells; 8386 PetscScalar *a; 8387 PetscErrorCode ierr; 8388 8389 PetscFunctionBegin; 8390 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8391 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8392 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8393 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 8394 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8395 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8396 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8397 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); 8398 numPoints /= bs; 8399 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8400 for (p = 0; p < numPoints; ++p) { 8401 const PetscScalar *point = &a[p*bs]; 8402 8403 switch (dim) { 8404 case 2: 8405 for (c = cStart; c < cEnd; ++c) { 8406 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8407 switch (coneSize) { 8408 case 3: 8409 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8410 break; 8411 case 4: 8412 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8413 break; 8414 default: 8415 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8416 } 8417 if (cell >= 0) break; 8418 } 8419 break; 8420 case 3: 8421 for (c = cStart; c < cEnd; ++c) { 8422 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8423 switch (coneSize) { 8424 case 4: 8425 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8426 break; 8427 case 8: 8428 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8429 break; 8430 default: 8431 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8432 } 8433 if (cell >= 0) break; 8434 } 8435 break; 8436 default: 8437 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8438 } 8439 cells[p] = cell; 8440 } 8441 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8442 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8443 PetscFunctionReturn(0); 8444 } 8445 8446 /******************************** FEM Support **********************************/ 8447 8448 #undef __FUNCT__ 8449 #define __FUNCT__ "DMPlexVecGetClosure" 8450 /*@C 8451 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8452 8453 Not collective 8454 8455 Input Parameters: 8456 + dm - The DM 8457 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8458 . v - The local vector 8459 - point - The sieve point in the DM 8460 8461 Output Parameters: 8462 + csize - The number of values in the closure, or PETSC_NULL 8463 - values - The array of values, which is a borrowed array and should not be freed 8464 8465 Level: intermediate 8466 8467 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8468 @*/ 8469 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8470 { 8471 PetscScalar *array, *vArray; 8472 PetscInt *points = PETSC_NULL; 8473 PetscInt offsets[32]; 8474 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8475 PetscErrorCode ierr; 8476 8477 PetscFunctionBegin; 8478 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8479 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8480 if (!section) { 8481 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8482 } 8483 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8484 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8485 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8486 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8487 /* Compress out points not in the section */ 8488 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8489 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8490 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8491 points[q*2] = points[p]; 8492 points[q*2+1] = points[p+1]; 8493 ++q; 8494 } 8495 } 8496 numPoints = q; 8497 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8498 PetscInt dof, fdof; 8499 8500 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8501 for (f = 0; f < numFields; ++f) { 8502 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8503 offsets[f+1] += fdof; 8504 } 8505 size += dof; 8506 } 8507 for (f = 1; f < numFields; ++f) { 8508 offsets[f+1] += offsets[f]; 8509 } 8510 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8511 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8512 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8513 for (p = 0; p < numPoints*2; p += 2) { 8514 PetscInt o = points[p+1]; 8515 PetscInt dof, off, d; 8516 PetscScalar *varr; 8517 8518 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8519 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8520 varr = &vArray[off]; 8521 if (numFields) { 8522 PetscInt fdof, foff, fcomp, f, c; 8523 8524 for (f = 0, foff = 0; f < numFields; ++f) { 8525 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8526 if (o >= 0) { 8527 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8528 array[offsets[f]] = varr[foff+d]; 8529 } 8530 } else { 8531 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8532 for (d = fdof/fcomp-1; d >= 0; --d) { 8533 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8534 array[offsets[f]] = varr[foff+d*fcomp+c]; 8535 } 8536 } 8537 } 8538 foff += fdof; 8539 } 8540 } else { 8541 if (o >= 0) { 8542 for (d = 0; d < dof; ++d, ++offsets[0]) { 8543 array[offsets[0]] = varr[d]; 8544 } 8545 } else { 8546 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8547 array[offsets[0]] = varr[d]; 8548 } 8549 } 8550 } 8551 } 8552 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8553 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8554 if (csize) *csize = size; 8555 *values = array; 8556 PetscFunctionReturn(0); 8557 } 8558 8559 #undef __FUNCT__ 8560 #define __FUNCT__ "DMPlexVecRestoreClosure" 8561 /*@C 8562 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8563 8564 Not collective 8565 8566 Input Parameters: 8567 + dm - The DM 8568 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8569 . v - The local vector 8570 . point - The sieve point in the DM 8571 . csize - The number of values in the closure, or PETSC_NULL 8572 - values - The array of values, which is a borrowed array and should not be freed 8573 8574 Level: intermediate 8575 8576 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8577 @*/ 8578 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8579 { 8580 PetscInt size = 0; 8581 PetscErrorCode ierr; 8582 8583 PetscFunctionBegin; 8584 /* Should work without recalculating size */ 8585 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 8586 PetscFunctionReturn(0); 8587 } 8588 8589 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8590 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8591 8592 #undef __FUNCT__ 8593 #define __FUNCT__ "updatePoint_private" 8594 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8595 { 8596 PetscInt cdof; /* The number of constraints on this point */ 8597 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8598 PetscScalar *a; 8599 PetscInt off, cind = 0, k; 8600 PetscErrorCode ierr; 8601 8602 PetscFunctionBegin; 8603 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8604 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8605 a = &array[off]; 8606 if (!cdof || setBC) { 8607 if (orientation >= 0) { 8608 for (k = 0; k < dof; ++k) { 8609 fuse(&a[k], values[k]); 8610 } 8611 } else { 8612 for (k = 0; k < dof; ++k) { 8613 fuse(&a[k], values[dof-k-1]); 8614 } 8615 } 8616 } else { 8617 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8618 if (orientation >= 0) { 8619 for (k = 0; k < dof; ++k) { 8620 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8621 fuse(&a[k], values[k]); 8622 } 8623 } else { 8624 for (k = 0; k < dof; ++k) { 8625 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8626 fuse(&a[k], values[dof-k-1]); 8627 } 8628 } 8629 } 8630 PetscFunctionReturn(0); 8631 } 8632 8633 #undef __FUNCT__ 8634 #define __FUNCT__ "updatePointFields_private" 8635 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8636 { 8637 PetscScalar *a; 8638 PetscInt numFields, off, foff, f; 8639 PetscErrorCode ierr; 8640 8641 PetscFunctionBegin; 8642 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8643 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8644 a = &array[off]; 8645 for (f = 0, foff = 0; f < numFields; ++f) { 8646 PetscInt fdof, fcomp, fcdof; 8647 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8648 PetscInt cind = 0, k, c; 8649 8650 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8651 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8652 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8653 if (!fcdof || setBC) { 8654 if (orientation >= 0) { 8655 for (k = 0; k < fdof; ++k) { 8656 fuse(&a[foff+k], values[foffs[f]+k]); 8657 } 8658 } else { 8659 for (k = fdof/fcomp-1; k >= 0; --k) { 8660 for (c = 0; c < fcomp; ++c) { 8661 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8662 } 8663 } 8664 } 8665 } else { 8666 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8667 if (orientation >= 0) { 8668 for (k = 0; k < fdof; ++k) { 8669 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8670 fuse(&a[foff+k], values[foffs[f]+k]); 8671 } 8672 } else { 8673 for (k = fdof/fcomp-1; k >= 0; --k) { 8674 for (c = 0; c < fcomp; ++c) { 8675 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8676 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8677 } 8678 } 8679 } 8680 } 8681 foff += fdof; 8682 foffs[f] += fdof; 8683 } 8684 PetscFunctionReturn(0); 8685 } 8686 8687 #undef __FUNCT__ 8688 #define __FUNCT__ "DMPlexVecSetClosure" 8689 /*@C 8690 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8691 8692 Not collective 8693 8694 Input Parameters: 8695 + dm - The DM 8696 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8697 . v - The local vector 8698 . point - The sieve point in the DM 8699 . values - The array of values, which is a borrowed array and should not be freed 8700 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8701 8702 Level: intermediate 8703 8704 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8705 @*/ 8706 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8707 { 8708 PetscScalar *array; 8709 PetscInt *points = PETSC_NULL; 8710 PetscInt offsets[32]; 8711 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8712 PetscErrorCode ierr; 8713 8714 PetscFunctionBegin; 8715 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8716 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8717 if (!section) { 8718 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8719 } 8720 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8721 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8722 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8723 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8724 /* Compress out points not in the section */ 8725 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8726 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8727 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8728 points[q*2] = points[p]; 8729 points[q*2+1] = points[p+1]; 8730 ++q; 8731 } 8732 } 8733 numPoints = q; 8734 for (p = 0; p < numPoints*2; p += 2) { 8735 PetscInt fdof; 8736 8737 for (f = 0; f < numFields; ++f) { 8738 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8739 offsets[f+1] += fdof; 8740 } 8741 } 8742 for (f = 1; f < numFields; ++f) { 8743 offsets[f+1] += offsets[f]; 8744 } 8745 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8746 if (numFields) { 8747 switch (mode) { 8748 case INSERT_VALUES: 8749 for (p = 0; p < numPoints*2; p += 2) { 8750 PetscInt o = points[p+1]; 8751 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8752 } break; 8753 case INSERT_ALL_VALUES: 8754 for (p = 0; p < numPoints*2; p += 2) { 8755 PetscInt o = points[p+1]; 8756 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8757 } break; 8758 case ADD_VALUES: 8759 for (p = 0; p < numPoints*2; p += 2) { 8760 PetscInt o = points[p+1]; 8761 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8762 } break; 8763 case ADD_ALL_VALUES: 8764 for (p = 0; p < numPoints*2; p += 2) { 8765 PetscInt o = points[p+1]; 8766 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8767 } break; 8768 default: 8769 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8770 } 8771 } else { 8772 switch (mode) { 8773 case INSERT_VALUES: 8774 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8775 PetscInt o = points[p+1]; 8776 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8777 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8778 } break; 8779 case INSERT_ALL_VALUES: 8780 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8781 PetscInt o = points[p+1]; 8782 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8783 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8784 } break; 8785 case ADD_VALUES: 8786 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8787 PetscInt o = points[p+1]; 8788 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8789 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8790 } break; 8791 case ADD_ALL_VALUES: 8792 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8793 PetscInt o = points[p+1]; 8794 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8795 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8796 } break; 8797 default: 8798 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8799 } 8800 } 8801 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8802 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8803 PetscFunctionReturn(0); 8804 } 8805 8806 #undef __FUNCT__ 8807 #define __FUNCT__ "DMPlexPrintMatSetValues" 8808 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8809 { 8810 PetscMPIInt rank; 8811 PetscInt i, j; 8812 PetscErrorCode ierr; 8813 8814 PetscFunctionBegin; 8815 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8816 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8817 for (i = 0; i < numIndices; i++) { 8818 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8819 } 8820 for (i = 0; i < numIndices; i++) { 8821 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8822 for (j = 0; j < numIndices; j++) { 8823 #if defined(PETSC_USE_COMPLEX) 8824 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8825 #else 8826 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8827 #endif 8828 } 8829 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8830 } 8831 PetscFunctionReturn(0); 8832 } 8833 8834 #undef __FUNCT__ 8835 #define __FUNCT__ "indicesPoint_private" 8836 /* . off - The global offset of this point */ 8837 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8838 { 8839 PetscInt cdof; /* The number of constraints on this point */ 8840 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8841 PetscInt cind = 0, k; 8842 PetscErrorCode ierr; 8843 8844 PetscFunctionBegin; 8845 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8846 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8847 if (!cdof || setBC) { 8848 if (orientation >= 0) { 8849 for (k = 0; k < dof; ++k) { 8850 indices[k] = off+k; 8851 } 8852 } else { 8853 for (k = 0; k < dof; ++k) { 8854 indices[dof-k-1] = off+k; 8855 } 8856 } 8857 } else { 8858 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8859 if (orientation >= 0) { 8860 for (k = 0; k < dof; ++k) { 8861 if ((cind < cdof) && (k == cdofs[cind])) { 8862 /* Insert check for returning constrained indices */ 8863 indices[k] = -(off+k+1); 8864 ++cind; 8865 } else { 8866 indices[k] = off+k-cind; 8867 } 8868 } 8869 } else { 8870 for (k = 0; k < dof; ++k) { 8871 if ((cind < cdof) && (k == cdofs[cind])) { 8872 /* Insert check for returning constrained indices */ 8873 indices[dof-k-1] = -(off+k+1); 8874 ++cind; 8875 } else { 8876 indices[dof-k-1] = off+k-cind; 8877 } 8878 } 8879 } 8880 } 8881 PetscFunctionReturn(0); 8882 } 8883 8884 #undef __FUNCT__ 8885 #define __FUNCT__ "indicesPointFields_private" 8886 /* . off - The global offset of this point */ 8887 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8888 { 8889 PetscInt numFields, foff, f; 8890 PetscErrorCode ierr; 8891 8892 PetscFunctionBegin; 8893 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8894 for (f = 0, foff = 0; f < numFields; ++f) { 8895 PetscInt fdof, fcomp, cfdof; 8896 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8897 PetscInt cind = 0, k, c; 8898 8899 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8900 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8901 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8902 if (!cfdof || setBC) { 8903 if (orientation >= 0) { 8904 for (k = 0; k < fdof; ++k) { 8905 indices[foffs[f]+k] = off+foff+k; 8906 } 8907 } else { 8908 for (k = fdof/fcomp-1; k >= 0; --k) { 8909 for (c = 0; c < fcomp; ++c) { 8910 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8911 } 8912 } 8913 } 8914 } else { 8915 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8916 if (orientation >= 0) { 8917 for (k = 0; k < fdof; ++k) { 8918 if ((cind < cfdof) && (k == fcdofs[cind])) { 8919 indices[foffs[f]+k] = -(off+foff+k+1); 8920 ++cind; 8921 } else { 8922 indices[foffs[f]+k] = off+foff+k-cind; 8923 } 8924 } 8925 } else { 8926 for (k = fdof/fcomp-1; k >= 0; --k) { 8927 for (c = 0; c < fcomp; ++c) { 8928 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8929 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8930 ++cind; 8931 } else { 8932 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8933 } 8934 } 8935 } 8936 } 8937 } 8938 foff += fdof - cfdof; 8939 foffs[f] += fdof; 8940 } 8941 PetscFunctionReturn(0); 8942 } 8943 8944 #undef __FUNCT__ 8945 #define __FUNCT__ "DMPlexMatSetClosure" 8946 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8947 { 8948 DM_Plex *mesh = (DM_Plex *) dm->data; 8949 PetscInt *points = PETSC_NULL; 8950 PetscInt *indices; 8951 PetscInt offsets[32]; 8952 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8953 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8954 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8955 PetscErrorCode ierr; 8956 8957 PetscFunctionBegin; 8958 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8959 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8960 if (useDefault) { 8961 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8962 } 8963 if (useGlobalDefault) { 8964 if (useDefault) { 8965 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8966 } else { 8967 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8968 } 8969 } 8970 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8971 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8972 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8973 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8974 /* Compress out points not in the section */ 8975 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8976 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8977 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8978 points[q*2] = points[p]; 8979 points[q*2+1] = points[p+1]; 8980 ++q; 8981 } 8982 } 8983 numPoints = q; 8984 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8985 PetscInt fdof; 8986 8987 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8988 for (f = 0; f < numFields; ++f) { 8989 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8990 offsets[f+1] += fdof; 8991 } 8992 numIndices += dof; 8993 } 8994 for (f = 1; f < numFields; ++f) { 8995 offsets[f+1] += offsets[f]; 8996 } 8997 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8998 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8999 if (numFields) { 9000 for (p = 0; p < numPoints*2; p += 2) { 9001 PetscInt o = points[p+1]; 9002 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9003 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 9004 } 9005 } else { 9006 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 9007 PetscInt o = points[p+1]; 9008 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9009 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 9010 } 9011 } 9012 if (useGlobalDefault && !useDefault) { 9013 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9014 } 9015 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 9016 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 9017 if (ierr) { 9018 PetscMPIInt rank; 9019 PetscErrorCode ierr2; 9020 9021 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 9022 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 9023 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 9024 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 9025 CHKERRQ(ierr); 9026 } 9027 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9028 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9029 PetscFunctionReturn(0); 9030 } 9031 9032 #undef __FUNCT__ 9033 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 9034 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9035 { 9036 PetscSection coordSection; 9037 Vec coordinates; 9038 const PetscScalar *coords; 9039 const PetscInt dim = 2; 9040 PetscInt d, f; 9041 PetscErrorCode ierr; 9042 9043 PetscFunctionBegin; 9044 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9045 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9046 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9047 if (v0) { 9048 for (d = 0; d < dim; d++) { 9049 v0[d] = PetscRealPart(coords[d]); 9050 } 9051 } 9052 if (J) { 9053 for (d = 0; d < dim; d++) { 9054 for (f = 0; f < dim; f++) { 9055 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9056 } 9057 } 9058 *detJ = J[0]*J[3] - J[1]*J[2]; 9059 #if 0 9060 if (detJ < 0.0) { 9061 const PetscReal xLength = mesh->periodicity[0]; 9062 9063 if (xLength != 0.0) { 9064 PetscReal v0x = coords[0*dim+0]; 9065 9066 if (v0x == 0.0) { 9067 v0x = v0[0] = xLength; 9068 } 9069 for (f = 0; f < dim; f++) { 9070 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 9071 9072 J[0*dim+f] = 0.5*(px - v0x); 9073 } 9074 } 9075 detJ = J[0]*J[3] - J[1]*J[2]; 9076 } 9077 #endif 9078 PetscLogFlops(8.0 + 3.0); 9079 } 9080 if (invJ) { 9081 const PetscReal invDet = 1.0/(*detJ); 9082 9083 invJ[0] = invDet*J[3]; 9084 invJ[1] = -invDet*J[1]; 9085 invJ[2] = -invDet*J[2]; 9086 invJ[3] = invDet*J[0]; 9087 PetscLogFlops(5.0); 9088 } 9089 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9090 PetscFunctionReturn(0); 9091 } 9092 9093 #undef __FUNCT__ 9094 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9095 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9096 { 9097 PetscSection coordSection; 9098 Vec coordinates; 9099 const PetscScalar *coords; 9100 const PetscInt dim = 2; 9101 PetscInt d, f; 9102 PetscErrorCode ierr; 9103 9104 PetscFunctionBegin; 9105 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9106 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9107 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9108 if (v0) { 9109 for (d = 0; d < dim; d++) { 9110 v0[d] = PetscRealPart(coords[d]); 9111 } 9112 } 9113 if (J) { 9114 for (d = 0; d < dim; d++) { 9115 for (f = 0; f < dim; f++) { 9116 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9117 } 9118 } 9119 *detJ = J[0]*J[3] - J[1]*J[2]; 9120 PetscLogFlops(8.0 + 3.0); 9121 } 9122 if (invJ) { 9123 const PetscReal invDet = 1.0/(*detJ); 9124 9125 invJ[0] = invDet*J[3]; 9126 invJ[1] = -invDet*J[1]; 9127 invJ[2] = -invDet*J[2]; 9128 invJ[3] = invDet*J[0]; 9129 PetscLogFlops(5.0); 9130 } 9131 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9132 PetscFunctionReturn(0); 9133 } 9134 9135 #undef __FUNCT__ 9136 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9137 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9138 { 9139 PetscSection coordSection; 9140 Vec coordinates; 9141 const PetscScalar *coords; 9142 const PetscInt dim = 3; 9143 PetscInt d, f; 9144 PetscErrorCode ierr; 9145 9146 PetscFunctionBegin; 9147 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9148 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9149 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9150 if (v0) { 9151 for (d = 0; d < dim; d++) { 9152 v0[d] = PetscRealPart(coords[d]); 9153 } 9154 } 9155 if (J) { 9156 for (d = 0; d < dim; d++) { 9157 for (f = 0; f < dim; f++) { 9158 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9159 } 9160 } 9161 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9162 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9163 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9164 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9165 PetscLogFlops(18.0 + 12.0); 9166 } 9167 if (invJ) { 9168 const PetscReal invDet = 1.0/(*detJ); 9169 9170 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9171 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9172 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9173 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9174 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9175 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9176 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9177 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9178 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9179 PetscLogFlops(37.0); 9180 } 9181 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9182 PetscFunctionReturn(0); 9183 } 9184 9185 #undef __FUNCT__ 9186 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9187 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9188 { 9189 PetscSection coordSection; 9190 Vec coordinates; 9191 const PetscScalar *coords; 9192 const PetscInt dim = 3; 9193 PetscInt d; 9194 PetscErrorCode ierr; 9195 9196 PetscFunctionBegin; 9197 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9198 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9199 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9200 if (v0) { 9201 for (d = 0; d < dim; d++) { 9202 v0[d] = PetscRealPart(coords[d]); 9203 } 9204 } 9205 if (J) { 9206 for (d = 0; d < dim; d++) { 9207 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9208 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9209 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9210 } 9211 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9212 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9213 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9214 PetscLogFlops(18.0 + 12.0); 9215 } 9216 if (invJ) { 9217 const PetscReal invDet = -1.0/(*detJ); 9218 9219 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9220 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9221 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9222 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9223 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9224 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9225 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9226 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9227 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9228 PetscLogFlops(37.0); 9229 } 9230 *detJ *= 8.0; 9231 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9232 PetscFunctionReturn(0); 9233 } 9234 9235 #undef __FUNCT__ 9236 #define __FUNCT__ "DMPlexComputeCellGeometry" 9237 /*@C 9238 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9239 9240 Collective on DM 9241 9242 Input Arguments: 9243 + dm - the DM 9244 - cell - the cell 9245 9246 Output Arguments: 9247 + v0 - the translation part of this affine transform 9248 . J - the Jacobian of the transform to the reference element 9249 . invJ - the inverse of the Jacobian 9250 - detJ - the Jacobian determinant 9251 9252 Level: advanced 9253 9254 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9255 @*/ 9256 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9257 { 9258 PetscInt dim, coneSize; 9259 PetscErrorCode ierr; 9260 9261 PetscFunctionBegin; 9262 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9263 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9264 switch (dim) { 9265 case 2: 9266 switch (coneSize) { 9267 case 3: 9268 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9269 break; 9270 case 4: 9271 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9272 break; 9273 default: 9274 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9275 } 9276 break; 9277 case 3: 9278 switch (coneSize) { 9279 case 4: 9280 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9281 break; 9282 case 8: 9283 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9284 break; 9285 default: 9286 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9287 } 9288 break; 9289 default: 9290 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9291 } 9292 PetscFunctionReturn(0); 9293 } 9294 9295 #undef __FUNCT__ 9296 #define __FUNCT__ "DMPlexGetFaceOrientation" 9297 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9298 { 9299 MPI_Comm comm = ((PetscObject) dm)->comm; 9300 PetscBool posOrient = PETSC_FALSE; 9301 const PetscInt debug = 0; 9302 PetscInt cellDim, faceSize, f; 9303 PetscErrorCode ierr; 9304 9305 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9306 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9307 9308 if (cellDim == numCorners-1) { 9309 /* Simplices */ 9310 faceSize = numCorners-1; 9311 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9312 } else if (cellDim == 1 && numCorners == 3) { 9313 /* Quadratic line */ 9314 faceSize = 1; 9315 posOrient = PETSC_TRUE; 9316 } else if (cellDim == 2 && numCorners == 4) { 9317 /* Quads */ 9318 faceSize = 2; 9319 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9320 posOrient = PETSC_TRUE; 9321 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9322 posOrient = PETSC_TRUE; 9323 } else { 9324 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9325 posOrient = PETSC_FALSE; 9326 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9327 } 9328 } else if (cellDim == 2 && numCorners == 6) { 9329 /* Quadratic triangle (I hate this) */ 9330 /* Edges are determined by the first 2 vertices (corners of edges) */ 9331 const PetscInt faceSizeTri = 3; 9332 PetscInt sortedIndices[3], i, iFace; 9333 PetscBool found = PETSC_FALSE; 9334 PetscInt faceVerticesTriSorted[9] = { 9335 0, 3, 4, /* bottom */ 9336 1, 4, 5, /* right */ 9337 2, 3, 5, /* left */ 9338 }; 9339 PetscInt faceVerticesTri[9] = { 9340 0, 3, 4, /* bottom */ 9341 1, 4, 5, /* right */ 9342 2, 5, 3, /* left */ 9343 }; 9344 9345 faceSize = faceSizeTri; 9346 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9347 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9348 for (iFace = 0; iFace < 3; ++iFace) { 9349 const PetscInt ii = iFace*faceSizeTri; 9350 PetscInt fVertex, cVertex; 9351 9352 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9353 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9354 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9355 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9356 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9357 faceVertices[fVertex] = origVertices[cVertex]; 9358 break; 9359 } 9360 } 9361 } 9362 found = PETSC_TRUE; 9363 break; 9364 } 9365 } 9366 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9367 if (posOriented) {*posOriented = PETSC_TRUE;} 9368 PetscFunctionReturn(0); 9369 } else if (cellDim == 2 && numCorners == 9) { 9370 /* Quadratic quad (I hate this) */ 9371 /* Edges are determined by the first 2 vertices (corners of edges) */ 9372 const PetscInt faceSizeQuad = 3; 9373 PetscInt sortedIndices[3], i, iFace; 9374 PetscBool found = PETSC_FALSE; 9375 PetscInt faceVerticesQuadSorted[12] = { 9376 0, 1, 4, /* bottom */ 9377 1, 2, 5, /* right */ 9378 2, 3, 6, /* top */ 9379 0, 3, 7, /* left */ 9380 }; 9381 PetscInt faceVerticesQuad[12] = { 9382 0, 1, 4, /* bottom */ 9383 1, 2, 5, /* right */ 9384 2, 3, 6, /* top */ 9385 3, 0, 7, /* left */ 9386 }; 9387 9388 faceSize = faceSizeQuad; 9389 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9390 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9391 for (iFace = 0; iFace < 4; ++iFace) { 9392 const PetscInt ii = iFace*faceSizeQuad; 9393 PetscInt fVertex, cVertex; 9394 9395 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9396 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9397 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9398 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9399 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9400 faceVertices[fVertex] = origVertices[cVertex]; 9401 break; 9402 } 9403 } 9404 } 9405 found = PETSC_TRUE; 9406 break; 9407 } 9408 } 9409 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9410 if (posOriented) {*posOriented = PETSC_TRUE;} 9411 PetscFunctionReturn(0); 9412 } else if (cellDim == 3 && numCorners == 8) { 9413 /* Hexes 9414 A hex is two oriented quads with the normal of the first 9415 pointing up at the second. 9416 9417 7---6 9418 /| /| 9419 4---5 | 9420 | 3-|-2 9421 |/ |/ 9422 0---1 9423 9424 Faces are determined by the first 4 vertices (corners of faces) */ 9425 const PetscInt faceSizeHex = 4; 9426 PetscInt sortedIndices[4], i, iFace; 9427 PetscBool found = PETSC_FALSE; 9428 PetscInt faceVerticesHexSorted[24] = { 9429 0, 1, 2, 3, /* bottom */ 9430 4, 5, 6, 7, /* top */ 9431 0, 1, 4, 5, /* front */ 9432 1, 2, 5, 6, /* right */ 9433 2, 3, 6, 7, /* back */ 9434 0, 3, 4, 7, /* left */ 9435 }; 9436 PetscInt faceVerticesHex[24] = { 9437 3, 2, 1, 0, /* bottom */ 9438 4, 5, 6, 7, /* top */ 9439 0, 1, 5, 4, /* front */ 9440 1, 2, 6, 5, /* right */ 9441 2, 3, 7, 6, /* back */ 9442 3, 0, 4, 7, /* left */ 9443 }; 9444 9445 faceSize = faceSizeHex; 9446 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9447 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9448 for (iFace = 0; iFace < 6; ++iFace) { 9449 const PetscInt ii = iFace*faceSizeHex; 9450 PetscInt fVertex, cVertex; 9451 9452 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9453 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9454 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9455 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9456 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9457 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9458 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9459 faceVertices[fVertex] = origVertices[cVertex]; 9460 break; 9461 } 9462 } 9463 } 9464 found = PETSC_TRUE; 9465 break; 9466 } 9467 } 9468 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9469 if (posOriented) {*posOriented = PETSC_TRUE;} 9470 PetscFunctionReturn(0); 9471 } else if (cellDim == 3 && numCorners == 10) { 9472 /* Quadratic tet */ 9473 /* Faces are determined by the first 3 vertices (corners of faces) */ 9474 const PetscInt faceSizeTet = 6; 9475 PetscInt sortedIndices[6], i, iFace; 9476 PetscBool found = PETSC_FALSE; 9477 PetscInt faceVerticesTetSorted[24] = { 9478 0, 1, 2, 6, 7, 8, /* bottom */ 9479 0, 3, 4, 6, 7, 9, /* front */ 9480 1, 4, 5, 7, 8, 9, /* right */ 9481 2, 3, 5, 6, 8, 9, /* left */ 9482 }; 9483 PetscInt faceVerticesTet[24] = { 9484 0, 1, 2, 6, 7, 8, /* bottom */ 9485 0, 4, 3, 6, 7, 9, /* front */ 9486 1, 5, 4, 7, 8, 9, /* right */ 9487 2, 3, 5, 8, 6, 9, /* left */ 9488 }; 9489 9490 faceSize = faceSizeTet; 9491 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9492 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9493 for (iFace=0; iFace < 4; ++iFace) { 9494 const PetscInt ii = iFace*faceSizeTet; 9495 PetscInt fVertex, cVertex; 9496 9497 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9498 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9499 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9500 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9501 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9502 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9503 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9504 faceVertices[fVertex] = origVertices[cVertex]; 9505 break; 9506 } 9507 } 9508 } 9509 found = PETSC_TRUE; 9510 break; 9511 } 9512 } 9513 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9514 if (posOriented) {*posOriented = PETSC_TRUE;} 9515 PetscFunctionReturn(0); 9516 } else if (cellDim == 3 && numCorners == 27) { 9517 /* Quadratic hexes (I hate this) 9518 A hex is two oriented quads with the normal of the first 9519 pointing up at the second. 9520 9521 7---6 9522 /| /| 9523 4---5 | 9524 | 3-|-2 9525 |/ |/ 9526 0---1 9527 9528 Faces are determined by the first 4 vertices (corners of faces) */ 9529 const PetscInt faceSizeQuadHex = 9; 9530 PetscInt sortedIndices[9], i, iFace; 9531 PetscBool found = PETSC_FALSE; 9532 PetscInt faceVerticesQuadHexSorted[54] = { 9533 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9534 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9535 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9536 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9537 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9538 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9539 }; 9540 PetscInt faceVerticesQuadHex[54] = { 9541 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9542 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9543 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9544 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9545 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9546 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9547 }; 9548 9549 faceSize = faceSizeQuadHex; 9550 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9551 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9552 for (iFace = 0; iFace < 6; ++iFace) { 9553 const PetscInt ii = iFace*faceSizeQuadHex; 9554 PetscInt fVertex, cVertex; 9555 9556 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9557 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9558 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9559 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9560 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9561 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9562 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9563 faceVertices[fVertex] = origVertices[cVertex]; 9564 break; 9565 } 9566 } 9567 } 9568 found = PETSC_TRUE; 9569 break; 9570 } 9571 } 9572 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9573 if (posOriented) {*posOriented = PETSC_TRUE;} 9574 PetscFunctionReturn(0); 9575 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9576 if (!posOrient) { 9577 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9578 for (f = 0; f < faceSize; ++f) { 9579 faceVertices[f] = origVertices[faceSize-1 - f]; 9580 } 9581 } else { 9582 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9583 for (f = 0; f < faceSize; ++f) { 9584 faceVertices[f] = origVertices[f]; 9585 } 9586 } 9587 if (posOriented) {*posOriented = posOrient;} 9588 PetscFunctionReturn(0); 9589 } 9590 9591 #undef __FUNCT__ 9592 #define __FUNCT__ "DMPlexGetOrientedFace" 9593 /* 9594 Given a cell and a face, as a set of vertices, 9595 return the oriented face, as a set of vertices, in faceVertices 9596 The orientation is such that the face normal points out of the cell 9597 */ 9598 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9599 { 9600 const PetscInt *cone = PETSC_NULL; 9601 PetscInt coneSize, v, f, v2; 9602 PetscInt oppositeVertex = -1; 9603 PetscErrorCode ierr; 9604 9605 PetscFunctionBegin; 9606 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9607 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9608 for (v = 0, v2 = 0; v < coneSize; ++v) { 9609 PetscBool found = PETSC_FALSE; 9610 9611 for (f = 0; f < faceSize; ++f) { 9612 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 9613 } 9614 if (found) { 9615 indices[v2] = v; 9616 origVertices[v2] = cone[v]; 9617 ++v2; 9618 } else { 9619 oppositeVertex = v; 9620 } 9621 } 9622 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9623 PetscFunctionReturn(0); 9624 } 9625 9626 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9627 { 9628 switch (i) { 9629 case 0: 9630 switch (j) { 9631 case 0: return 0; 9632 case 1: 9633 switch (k) { 9634 case 0: return 0; 9635 case 1: return 0; 9636 case 2: return 1; 9637 } 9638 case 2: 9639 switch (k) { 9640 case 0: return 0; 9641 case 1: return -1; 9642 case 2: return 0; 9643 } 9644 } 9645 case 1: 9646 switch (j) { 9647 case 0: 9648 switch (k) { 9649 case 0: return 0; 9650 case 1: return 0; 9651 case 2: return -1; 9652 } 9653 case 1: return 0; 9654 case 2: 9655 switch (k) { 9656 case 0: return 1; 9657 case 1: return 0; 9658 case 2: return 0; 9659 } 9660 } 9661 case 2: 9662 switch (j) { 9663 case 0: 9664 switch (k) { 9665 case 0: return 0; 9666 case 1: return 1; 9667 case 2: return 0; 9668 } 9669 case 1: 9670 switch (k) { 9671 case 0: return -1; 9672 case 1: return 0; 9673 case 2: return 0; 9674 } 9675 case 2: return 0; 9676 } 9677 } 9678 return 0; 9679 } 9680 9681 #undef __FUNCT__ 9682 #define __FUNCT__ "DMPlexCreateRigidBody" 9683 /*@C 9684 DMPlexCreateRigidBody - create rigid body modes from coordinates 9685 9686 Collective on DM 9687 9688 Input Arguments: 9689 + dm - the DM 9690 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9691 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9692 9693 Output Argument: 9694 . sp - the null space 9695 9696 Note: This is necessary to take account of Dirichlet conditions on the displacements 9697 9698 Level: advanced 9699 9700 .seealso: MatNullSpaceCreate() 9701 @*/ 9702 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9703 { 9704 MPI_Comm comm = ((PetscObject) dm)->comm; 9705 Vec coordinates, localMode, mode[6]; 9706 PetscSection coordSection; 9707 PetscScalar *coords; 9708 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9709 PetscErrorCode ierr; 9710 9711 PetscFunctionBegin; 9712 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9713 if (dim == 1) { 9714 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9715 PetscFunctionReturn(0); 9716 } 9717 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9718 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9719 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9720 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9721 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9722 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9723 m = (dim*(dim+1))/2; 9724 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9725 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9726 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9727 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9728 /* Assume P1 */ 9729 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9730 for (d = 0; d < dim; ++d) { 9731 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9732 9733 values[d] = 1.0; 9734 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9735 for (v = vStart; v < vEnd; ++v) { 9736 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9737 } 9738 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9739 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9740 } 9741 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9742 for (d = dim; d < dim*(dim+1)/2; ++d) { 9743 PetscInt i, j, k = dim > 2 ? d - dim : d; 9744 9745 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9746 for (v = vStart; v < vEnd; ++v) { 9747 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9748 PetscInt off; 9749 9750 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9751 for (i = 0; i < dim; ++i) { 9752 for (j = 0; j < dim; ++j) { 9753 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9754 } 9755 } 9756 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9757 } 9758 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9759 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9760 } 9761 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9762 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9763 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9764 /* Orthonormalize system */ 9765 for (i = dim; i < m; ++i) { 9766 PetscScalar dots[6]; 9767 9768 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9769 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9770 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9771 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9772 } 9773 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9774 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9775 PetscFunctionReturn(0); 9776 } 9777 9778 #undef __FUNCT__ 9779 #define __FUNCT__ "DMPlexGetHybridBounds" 9780 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9781 { 9782 DM_Plex *mesh = (DM_Plex *) dm->data; 9783 PetscInt dim; 9784 PetscErrorCode ierr; 9785 9786 PetscFunctionBegin; 9787 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9788 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9789 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9790 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9791 if (eMax) *eMax = mesh->hybridPointMax[1]; 9792 if (vMax) *vMax = mesh->hybridPointMax[0]; 9793 PetscFunctionReturn(0); 9794 } 9795 9796 #undef __FUNCT__ 9797 #define __FUNCT__ "DMPlexSetHybridBounds" 9798 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9799 { 9800 DM_Plex *mesh = (DM_Plex *) dm->data; 9801 PetscInt dim; 9802 PetscErrorCode ierr; 9803 9804 PetscFunctionBegin; 9805 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9806 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9807 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9808 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9809 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9810 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9811 PetscFunctionReturn(0); 9812 } 9813 9814 #undef __FUNCT__ 9815 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9816 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9817 { 9818 DM_Plex *mesh = (DM_Plex *) dm->data; 9819 9820 PetscFunctionBegin; 9821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9822 PetscValidPointer(cellHeight, 2); 9823 *cellHeight = mesh->vtkCellHeight; 9824 PetscFunctionReturn(0); 9825 } 9826 9827 #undef __FUNCT__ 9828 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9829 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9830 { 9831 DM_Plex *mesh = (DM_Plex *) dm->data; 9832 9833 PetscFunctionBegin; 9834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9835 mesh->vtkCellHeight = cellHeight; 9836 PetscFunctionReturn(0); 9837 } 9838 9839 #undef __FUNCT__ 9840 #define __FUNCT__ "DMPlexInsertFace_Private" 9841 /* 9842 DMPlexInsertFace_Private - Puts a face into the mesh 9843 9844 Not collective 9845 9846 Input Parameters: 9847 + dm - The DMPlex 9848 . numFaceVertex - The number of vertices in the face 9849 . faceVertices - The vertices in the face for dm 9850 . subfaceVertices - The vertices in the face for subdm 9851 . numCorners - The number of vertices in the cell 9852 . cell - A cell in dm containing the face 9853 . subcell - A cell in subdm containing the face 9854 . firstFace - First face in the mesh 9855 - newFacePoint - Next face in the mesh 9856 9857 Output Parameters: 9858 . newFacePoint - Contains next face point number on input, updated on output 9859 9860 Level: developer 9861 */ 9862 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) 9863 { 9864 MPI_Comm comm = ((PetscObject) dm)->comm; 9865 DM_Plex *submesh = (DM_Plex *) subdm->data; 9866 const PetscInt *faces; 9867 PetscInt numFaces, coneSize; 9868 PetscErrorCode ierr; 9869 9870 PetscFunctionBegin; 9871 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9872 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9873 #if 0 9874 /* Cannot use this because support() has not been constructed yet */ 9875 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9876 #else 9877 { 9878 PetscInt f; 9879 9880 numFaces = 0; 9881 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 9882 for (f = firstFace; f < *newFacePoint; ++f) { 9883 PetscInt dof, off, d; 9884 9885 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9886 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9887 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9888 for (d = 0; d < dof; ++d) { 9889 const PetscInt p = submesh->cones[off+d]; 9890 PetscInt v; 9891 9892 for (v = 0; v < numFaceVertices; ++v) { 9893 if (subfaceVertices[v] == p) break; 9894 } 9895 if (v == numFaceVertices) break; 9896 } 9897 if (d == dof) { 9898 numFaces = 1; 9899 ((PetscInt *) faces)[0] = f; 9900 } 9901 } 9902 } 9903 #endif 9904 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 9905 else if (numFaces == 1) { 9906 /* Add the other cell neighbor for this face */ 9907 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 9908 } else { 9909 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 9910 PetscBool posOriented; 9911 9912 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9913 origVertices = &orientedVertices[numFaceVertices]; 9914 indices = &orientedVertices[numFaceVertices*2]; 9915 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 9916 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 9917 /* TODO: I know that routine should return a permutation, not the indices */ 9918 for (v = 0; v < numFaceVertices; ++v) { 9919 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 9920 for (ov = 0; ov < numFaceVertices; ++ov) { 9921 if (orientedVertices[ov] == vertex) { 9922 orientedSubVertices[ov] = subvertex; 9923 break; 9924 } 9925 } 9926 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 9927 } 9928 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 9929 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 9930 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9931 ++(*newFacePoint); 9932 } 9933 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9934 PetscFunctionReturn(0); 9935 } 9936 9937 #undef __FUNCT__ 9938 #define __FUNCT__ "DMPlexCreateSubmesh" 9939 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 9940 { 9941 MPI_Comm comm = ((PetscObject) dm)->comm; 9942 DM_Plex *submesh; 9943 PetscBool boundaryFaces = PETSC_FALSE; 9944 PetscSection coordSection, subCoordSection; 9945 Vec coordinates, subCoordinates; 9946 PetscScalar *coords, *subCoords; 9947 IS labelIS; 9948 const PetscInt *subVertices; 9949 PetscInt *subVerticesActive, *tmpPoints; 9950 PetscInt *subCells = PETSC_NULL; 9951 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 9952 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 9953 PetscInt dim; /* Right now, do not specify dimension */ 9954 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 9955 PetscErrorCode ierr; 9956 9957 PetscFunctionBegin; 9958 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9959 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9960 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9961 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 9962 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9963 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9964 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9965 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9966 subface = &face[maxConeSize]; 9967 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 9968 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 9969 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 9970 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 9971 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 9972 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 9973 maxSubCells = numSubVertices; 9974 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 9975 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 9976 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 9977 for (v = 0; v < numSubVertices; ++v) { 9978 const PetscInt vertex = subVertices[v]; 9979 PetscInt *star = PETSC_NULL; 9980 PetscInt starSize, numCells = 0; 9981 9982 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9983 for (p = 0; p < starSize*2; p += 2) { 9984 const PetscInt point = star[p]; 9985 if ((point >= cStart) && (point < cEnd)) { 9986 star[numCells++] = point; 9987 } 9988 } 9989 numOldSubCells = numSubCells; 9990 for (c = 0; c < numCells; ++c) { 9991 const PetscInt cell = star[c]; 9992 PetscInt *closure = PETSC_NULL; 9993 PetscInt closureSize, numCorners = 0, faceSize = 0; 9994 PetscInt cellLoc; 9995 9996 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 9997 if (cellLoc >= 0) continue; 9998 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9999 for (p = 0; p < closureSize*2; p += 2) { 10000 const PetscInt point = closure[p]; 10001 if ((point >= vStart) && (point < vEnd)) { 10002 closure[numCorners++] = point; 10003 } 10004 } 10005 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 10006 for (corner = 0; corner < numCorners; ++corner) { 10007 const PetscInt cellVertex = closure[corner]; 10008 PetscInt subVertex; 10009 10010 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 10011 if (subVertex >= 0) { /* contains submesh vertex */ 10012 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 10013 if (i == faceSize) { 10014 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 10015 face[faceSize] = cellVertex; 10016 subface[faceSize] = subVertex; 10017 ++faceSize; 10018 } 10019 } 10020 } 10021 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10022 if (faceSize >= nFV) { 10023 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10024 if (numSubCells >= maxSubCells) { 10025 PetscInt *tmpCells; 10026 maxSubCells *= 2; 10027 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 10028 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 10029 ierr = PetscFree(subCells);CHKERRQ(ierr); 10030 subCells = tmpCells; 10031 } 10032 /* TOOD: Maybe overestimate then squeeze out empty faces */ 10033 if (faceSize > nFV) { 10034 /* TODO: This is tricky. Maybe just add all faces */ 10035 numSubFaces++; 10036 } else { 10037 numSubFaces++; 10038 } 10039 for (f = 0; f < faceSize; ++f) { 10040 subVerticesActive[subface[f]] = 1; 10041 } 10042 subCells[numSubCells++] = cell; 10043 } 10044 } 10045 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10046 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 10047 } 10048 /* Pick out active subvertices */ 10049 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 10050 if (subVerticesActive[v]) { 10051 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 10052 } 10053 } 10054 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 10055 /* Set cone sizes */ 10056 firstSubVertex = numSubCells; 10057 firstSubFace = numSubCells+numSubVerticesActive; 10058 newFacePoint = firstSubFace; 10059 for (c = 0; c < numSubCells; ++c) { 10060 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 10061 } 10062 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 10063 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 10064 } 10065 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 10066 /* Create face cones */ 10067 for (c = 0; c < numSubCells; ++c) { 10068 const PetscInt cell = subCells[c]; 10069 PetscInt *closure = PETSC_NULL; 10070 PetscInt closureSize, numCorners = 0, faceSize = 0; 10071 10072 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10073 for (p = 0; p < closureSize*2; p += 2) { 10074 const PetscInt point = closure[p]; 10075 if ((point >= vStart) && (point < vEnd)) { 10076 closure[numCorners++] = point; 10077 } 10078 } 10079 for (corner = 0; corner < numCorners; ++corner) { 10080 const PetscInt cellVertex = closure[corner]; 10081 PetscInt subVertex; 10082 10083 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 10084 if (subVertex >= 0) { /* contains submesh vertex */ 10085 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 10086 if (i == faceSize) { 10087 face[faceSize] = cellVertex; 10088 subface[faceSize] = numSubCells+subVertex; 10089 ++faceSize; 10090 } 10091 } 10092 } 10093 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10094 if (faceSize >= nFV) { 10095 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10096 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 10097 /* We have to take all the faces, and discard those in the interior */ 10098 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 10099 #if 0 10100 /* This object just calls insert on each face that comes from subsets() */ 10101 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 10102 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 10103 PointArray faceVec(face->begin(), face->end()); 10104 10105 subsets(faceVec, nFV, inserter); 10106 #endif 10107 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 10108 } 10109 } 10110 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 10111 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 10112 /* Build coordinates */ 10113 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10114 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10115 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 10116 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 10117 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 10118 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 10119 } 10120 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10121 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10122 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 10123 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10124 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10125 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10126 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10127 for (v = 0; v < numSubVerticesActive; ++v) { 10128 const PetscInt vertex = subVerticesActive[v]; 10129 const PetscInt subVertex = firstSubVertex+v; 10130 PetscInt dof, off, sdof, soff; 10131 10132 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10133 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10134 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10135 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10136 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10137 for (d = 0; d < dof; ++d) { 10138 subCoords[soff+d] = coords[off+d]; 10139 } 10140 } 10141 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10142 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10143 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 10144 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10145 10146 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 10147 /* Create map from submesh points to original mesh points */ 10148 submesh = (DM_Plex *) (*subdm)->data; 10149 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 10150 for (c = 0; c < numSubCells; ++c) { 10151 tmpPoints[c] = subCells[c]; 10152 } 10153 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 10154 tmpPoints[v] = subVerticesActive[v-numSubCells]; 10155 } 10156 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 10157 10158 ierr = PetscFree(subCells);CHKERRQ(ierr); 10159 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10160 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10161 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10162 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10163 PetscFunctionReturn(0); 10164 } 10165 10166 #undef __FUNCT__ 10167 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10168 /* We can easily have a form that takes an IS instead */ 10169 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10170 { 10171 PetscSection section, globalSection; 10172 PetscInt *numbers, p; 10173 PetscErrorCode ierr; 10174 10175 PetscFunctionBegin; 10176 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10177 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10178 for (p = pStart; p < pEnd; ++p) { 10179 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10180 } 10181 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10182 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10183 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10184 for (p = pStart; p < pEnd; ++p) { 10185 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10186 } 10187 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10188 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10189 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10190 PetscFunctionReturn(0); 10191 } 10192 10193 #undef __FUNCT__ 10194 #define __FUNCT__ "DMPlexGetCellNumbering" 10195 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10196 { 10197 DM_Plex *mesh = (DM_Plex *) dm->data; 10198 PetscInt cellHeight, cStart, cEnd, cMax; 10199 PetscErrorCode ierr; 10200 10201 PetscFunctionBegin; 10202 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10203 if (!mesh->globalCellNumbers) { 10204 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10205 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10206 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10207 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 10208 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10209 } 10210 *globalCellNumbers = mesh->globalCellNumbers; 10211 PetscFunctionReturn(0); 10212 } 10213 10214 #undef __FUNCT__ 10215 #define __FUNCT__ "DMPlexGetVertexNumbering" 10216 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10217 { 10218 DM_Plex *mesh = (DM_Plex *) dm->data; 10219 PetscInt vStart, vEnd, vMax; 10220 PetscErrorCode ierr; 10221 10222 PetscFunctionBegin; 10223 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10224 if (!mesh->globalVertexNumbers) { 10225 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10226 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10227 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 10228 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10229 } 10230 *globalVertexNumbers = mesh->globalVertexNumbers; 10231 PetscFunctionReturn(0); 10232 } 10233 10234 #undef __FUNCT__ 10235 #define __FUNCT__ "DMPlexGetSubpointMap" 10236 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 10237 { 10238 DM_Plex *mesh = (DM_Plex *) dm->data; 10239 10240 PetscFunctionBegin; 10241 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10242 PetscValidPointer(subpointMap, 2); 10243 *subpointMap = mesh->subpointMap; 10244 PetscFunctionReturn(0); 10245 } 10246 10247 #undef __FUNCT__ 10248 #define __FUNCT__ "DMPlexSetSubpointMap" 10249 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10250 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 10251 { 10252 DM_Plex *mesh = (DM_Plex *) dm->data; 10253 10254 PetscFunctionBegin; 10255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10256 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 10257 mesh->subpointMap = subpointMap; 10258 PetscFunctionReturn(0); 10259 } 10260 10261 #undef __FUNCT__ 10262 #define __FUNCT__ "DMPlexGetScale" 10263 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10264 { 10265 DM_Plex *mesh = (DM_Plex *) dm->data; 10266 10267 PetscFunctionBegin; 10268 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10269 PetscValidPointer(scale, 3); 10270 *scale = mesh->scale[unit]; 10271 PetscFunctionReturn(0); 10272 } 10273 10274 #undef __FUNCT__ 10275 #define __FUNCT__ "DMPlexSetScale" 10276 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10277 { 10278 DM_Plex *mesh = (DM_Plex *) dm->data; 10279 10280 PetscFunctionBegin; 10281 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10282 mesh->scale[unit] = scale; 10283 PetscFunctionReturn(0); 10284 } 10285 10286 10287 /******************************************************************************* 10288 This should be in a separate Discretization object, but I am not sure how to lay 10289 it out yet, so I am stuffing things here while I experiment. 10290 *******************************************************************************/ 10291 #undef __FUNCT__ 10292 #define __FUNCT__ "DMPlexSetFEMIntegration" 10293 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10294 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10295 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10296 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10297 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10298 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10299 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10300 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10301 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10302 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10303 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10304 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10305 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10306 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10307 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10308 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10309 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 10310 { 10311 DM_Plex *mesh = (DM_Plex *) dm->data; 10312 10313 PetscFunctionBegin; 10314 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10315 mesh->integrateResidualFEM = integrateResidualFEM; 10316 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10317 mesh->integrateJacobianFEM = integrateJacobianFEM; 10318 PetscFunctionReturn(0); 10319 } 10320 10321 #undef __FUNCT__ 10322 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10323 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10324 { 10325 Vec coordinates; 10326 PetscSection section, cSection; 10327 PetscInt dim, vStart, vEnd, v, c, d; 10328 PetscScalar *values, *cArray; 10329 PetscReal *coords; 10330 PetscErrorCode ierr; 10331 10332 PetscFunctionBegin; 10333 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10334 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10335 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10336 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10337 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10338 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10339 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10340 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10341 for (v = vStart; v < vEnd; ++v) { 10342 PetscInt dof, off; 10343 10344 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10345 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10346 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10347 for (d = 0; d < dof; ++d) { 10348 coords[d] = PetscRealPart(cArray[off+d]); 10349 } 10350 for (c = 0; c < numComp; ++c) { 10351 values[c] = (*funcs[c])(coords); 10352 } 10353 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10354 } 10355 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10356 /* Temporary, must be replaced by a projection on the finite element basis */ 10357 { 10358 PetscInt eStart = 0, eEnd = 0, e, depth; 10359 10360 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10361 --depth; 10362 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10363 for (e = eStart; e < eEnd; ++e) { 10364 const PetscInt *cone = PETSC_NULL; 10365 PetscInt coneSize, d; 10366 PetscScalar *coordsA, *coordsB; 10367 10368 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10369 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10370 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10371 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10372 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10373 for (d = 0; d < dim; ++d) { 10374 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10375 } 10376 for (c = 0; c < numComp; ++c) { 10377 values[c] = (*funcs[c])(coords); 10378 } 10379 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10380 } 10381 } 10382 10383 ierr = PetscFree(coords);CHKERRQ(ierr); 10384 ierr = PetscFree(values);CHKERRQ(ierr); 10385 #if 0 10386 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10387 PetscReal detJ; 10388 10389 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10390 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10391 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10392 10393 for (PetscInt c = cStart; c < cEnd; ++c) { 10394 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10395 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10396 const int oSize = pV.getSize(); 10397 int v = 0; 10398 10399 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10400 for (PetscInt cl = 0; cl < oSize; ++cl) { 10401 const PetscInt fDim; 10402 10403 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10404 if (pointDim) { 10405 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10406 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10407 } 10408 } 10409 } 10410 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10411 pV.clear(); 10412 } 10413 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10414 ierr = PetscFree(values);CHKERRQ(ierr); 10415 #endif 10416 PetscFunctionReturn(0); 10417 } 10418 10419 #undef __FUNCT__ 10420 #define __FUNCT__ "DMPlexProjectFunction" 10421 /*@C 10422 DMPlexProjectFunction - This projects the given function into the function space provided. 10423 10424 Input Parameters: 10425 + dm - The DM 10426 . numComp - The number of components (functions) 10427 . funcs - The coordinate functions to evaluate 10428 - mode - The insertion mode for values 10429 10430 Output Parameter: 10431 . X - vector 10432 10433 Level: developer 10434 10435 Note: 10436 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10437 We will eventually fix it. 10438 10439 ,seealso: DMPlexComputeL2Diff() 10440 */ 10441 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10442 { 10443 Vec localX; 10444 PetscErrorCode ierr; 10445 10446 PetscFunctionBegin; 10447 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10448 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10449 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10450 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10451 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10452 PetscFunctionReturn(0); 10453 } 10454 10455 #undef __FUNCT__ 10456 #define __FUNCT__ "DMPlexComputeL2Diff" 10457 /*@C 10458 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10459 10460 Input Parameters: 10461 + dm - The DM 10462 . quad - The PetscQuadrature object for each field 10463 . funcs - The functions to evaluate for each field component 10464 - X - The coefficient vector u_h 10465 10466 Output Parameter: 10467 . diff - The diff ||u - u_h||_2 10468 10469 Level: developer 10470 10471 .seealso: DMPlexProjectFunction() 10472 */ 10473 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10474 { 10475 const PetscInt debug = 0; 10476 PetscSection section; 10477 Vec localX; 10478 PetscReal *coords, *v0, *J, *invJ, detJ; 10479 PetscReal localDiff = 0.0; 10480 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10481 PetscErrorCode ierr; 10482 10483 PetscFunctionBegin; 10484 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10485 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10486 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10487 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10488 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10489 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10490 for (field = 0; field < numFields; ++field) { 10491 numComponents += quad[field].numComponents; 10492 } 10493 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10494 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10495 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10496 for (c = cStart; c < cEnd; ++c) { 10497 const PetscScalar *x; 10498 PetscReal elemDiff = 0.0; 10499 10500 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10501 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10502 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10503 10504 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10505 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10506 const PetscReal *quadPoints = quad[field].quadPoints; 10507 const PetscReal *quadWeights = quad[field].quadWeights; 10508 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10509 const PetscInt numBasisComps = quad[field].numComponents; 10510 const PetscReal *basis = quad[field].basis; 10511 PetscInt q, d, e, fc, f; 10512 10513 if (debug) { 10514 char title[1024]; 10515 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10516 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10517 } 10518 for (q = 0; q < numQuadPoints; ++q) { 10519 for (d = 0; d < dim; d++) { 10520 coords[d] = v0[d]; 10521 for (e = 0; e < dim; e++) { 10522 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10523 } 10524 } 10525 for (fc = 0; fc < numBasisComps; ++fc) { 10526 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10527 PetscReal interpolant = 0.0; 10528 for (f = 0; f < numBasisFuncs; ++f) { 10529 const PetscInt fidx = f*numBasisComps+fc; 10530 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10531 } 10532 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10533 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10534 } 10535 } 10536 comp += numBasisComps; 10537 fieldOffset += numBasisFuncs*numBasisComps; 10538 } 10539 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10540 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10541 localDiff += elemDiff; 10542 } 10543 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10544 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10545 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10546 *diff = PetscSqrtReal(*diff); 10547 PetscFunctionReturn(0); 10548 } 10549 10550 #undef __FUNCT__ 10551 #define __FUNCT__ "DMPlexComputeResidualFEM" 10552 /*@ 10553 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10554 10555 Input Parameters: 10556 + dm - The mesh 10557 . X - Local input vector 10558 - user - The user context 10559 10560 Output Parameter: 10561 . F - Local output vector 10562 10563 Note: 10564 The second member of the user context must be an FEMContext. 10565 10566 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10567 like a GPU, or vectorize on a multicore machine. 10568 10569 .seealso: DMPlexComputeJacobianActionFEM() 10570 */ 10571 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10572 { 10573 DM_Plex *mesh = (DM_Plex *) dm->data; 10574 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10575 PetscQuadrature *quad = fem->quad; 10576 PetscSection section; 10577 PetscReal *v0, *J, *invJ, *detJ; 10578 PetscScalar *elemVec, *u; 10579 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10580 PetscInt cellDof = 0, numComponents = 0; 10581 PetscErrorCode ierr; 10582 10583 PetscFunctionBegin; 10584 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10585 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10586 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10587 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10588 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10589 numCells = cEnd - cStart; 10590 for (field = 0; field < numFields; ++field) { 10591 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10592 numComponents += quad[field].numComponents; 10593 } 10594 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10595 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10596 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); 10597 for (c = cStart; c < cEnd; ++c) { 10598 const PetscScalar *x; 10599 PetscInt i; 10600 10601 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10602 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10603 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10604 10605 for (i = 0; i < cellDof; ++i) { 10606 u[c*cellDof+i] = x[i]; 10607 } 10608 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10609 } 10610 for (field = 0; field < numFields; ++field) { 10611 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10612 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10613 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10614 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10615 /* Conforming batches */ 10616 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10617 PetscInt numBlocks = 1; 10618 PetscInt batchSize = numBlocks * blockSize; 10619 PetscInt numBatches = numBatchesTmp; 10620 PetscInt numChunks = numCells / (numBatches*batchSize); 10621 /* Remainder */ 10622 PetscInt numRemainder = numCells % (numBatches * batchSize); 10623 PetscInt offset = numCells - numRemainder; 10624 10625 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10626 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10627 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10628 } 10629 for (c = cStart; c < cEnd; ++c) { 10630 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10631 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10632 } 10633 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10634 if (mesh->printFEM) { 10635 PetscMPIInt rank, numProcs; 10636 PetscInt p; 10637 10638 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10639 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10640 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10641 for (p = 0; p < numProcs; ++p) { 10642 if (p == rank) { 10643 Vec f; 10644 10645 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10646 ierr = VecCopy(F, f);CHKERRQ(ierr); 10647 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10648 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10649 ierr = VecDestroy(&f);CHKERRQ(ierr); 10650 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10651 } 10652 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10653 } 10654 } 10655 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10656 PetscFunctionReturn(0); 10657 } 10658 10659 #undef __FUNCT__ 10660 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10661 /*@C 10662 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10663 10664 Input Parameters: 10665 + dm - The mesh 10666 . J - The Jacobian shell matrix 10667 . X - Local input vector 10668 - user - The user context 10669 10670 Output Parameter: 10671 . F - Local output vector 10672 10673 Note: 10674 The second member of the user context must be an FEMContext. 10675 10676 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10677 like a GPU, or vectorize on a multicore machine. 10678 10679 .seealso: DMPlexComputeResidualFEM() 10680 */ 10681 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10682 { 10683 DM_Plex *mesh = (DM_Plex *) dm->data; 10684 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10685 PetscQuadrature *quad = fem->quad; 10686 PetscSection section; 10687 JacActionCtx *jctx; 10688 PetscReal *v0, *J, *invJ, *detJ; 10689 PetscScalar *elemVec, *u, *a; 10690 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10691 PetscInt cellDof = 0; 10692 PetscErrorCode ierr; 10693 10694 PetscFunctionBegin; 10695 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10696 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10697 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10698 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10699 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10700 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10701 numCells = cEnd - cStart; 10702 for (field = 0; field < numFields; ++field) { 10703 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10704 } 10705 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10706 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); 10707 for (c = cStart; c < cEnd; ++c) { 10708 const PetscScalar *x; 10709 PetscInt i; 10710 10711 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10712 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10713 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10714 for (i = 0; i < cellDof; ++i) { 10715 u[c*cellDof+i] = x[i]; 10716 } 10717 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10718 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10719 for (i = 0; i < cellDof; ++i) { 10720 a[c*cellDof+i] = x[i]; 10721 } 10722 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10723 } 10724 for (field = 0; field < numFields; ++field) { 10725 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10726 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10727 /* Conforming batches */ 10728 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10729 PetscInt numBlocks = 1; 10730 PetscInt batchSize = numBlocks * blockSize; 10731 PetscInt numBatches = numBatchesTmp; 10732 PetscInt numChunks = numCells / (numBatches*batchSize); 10733 /* Remainder */ 10734 PetscInt numRemainder = numCells % (numBatches * batchSize); 10735 PetscInt offset = numCells - numRemainder; 10736 10737 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); 10738 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], 10739 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10740 } 10741 for (c = cStart; c < cEnd; ++c) { 10742 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10743 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10744 } 10745 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10746 if (mesh->printFEM) { 10747 PetscMPIInt rank, numProcs; 10748 PetscInt p; 10749 10750 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10751 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10752 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10753 for (p = 0; p < numProcs; ++p) { 10754 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10755 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10756 } 10757 } 10758 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10759 PetscFunctionReturn(0); 10760 } 10761 10762 #undef __FUNCT__ 10763 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10764 /*@ 10765 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10766 10767 Input Parameters: 10768 + dm - The mesh 10769 . X - Local input vector 10770 - user - The user context 10771 10772 Output Parameter: 10773 . Jac - Jacobian matrix 10774 10775 Note: 10776 The second member of the user context must be an FEMContext. 10777 10778 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10779 like a GPU, or vectorize on a multicore machine. 10780 10781 .seealso: FormFunctionLocal() 10782 */ 10783 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10784 { 10785 DM_Plex *mesh = (DM_Plex *) dm->data; 10786 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10787 PetscQuadrature *quad = fem->quad; 10788 PetscSection section; 10789 PetscReal *v0, *J, *invJ, *detJ; 10790 PetscScalar *elemMat, *u; 10791 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10792 PetscInt cellDof = 0, numComponents = 0; 10793 PetscBool isShell; 10794 PetscErrorCode ierr; 10795 10796 PetscFunctionBegin; 10797 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10798 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10799 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10800 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10801 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10802 numCells = cEnd - cStart; 10803 for (field = 0; field < numFields; ++field) { 10804 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10805 numComponents += quad[field].numComponents; 10806 } 10807 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10808 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10809 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); 10810 for (c = cStart; c < cEnd; ++c) { 10811 const PetscScalar *x; 10812 PetscInt i; 10813 10814 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10815 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10816 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10817 10818 for (i = 0; i < cellDof; ++i) { 10819 u[c*cellDof+i] = x[i]; 10820 } 10821 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10822 } 10823 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10824 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10825 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10826 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10827 PetscInt fieldJ; 10828 10829 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10830 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10831 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10832 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10833 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10834 /* Conforming batches */ 10835 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10836 PetscInt numBlocks = 1; 10837 PetscInt batchSize = numBlocks * blockSize; 10838 PetscInt numBatches = numBatchesTmp; 10839 PetscInt numChunks = numCells / (numBatches*batchSize); 10840 /* Remainder */ 10841 PetscInt numRemainder = numCells % (numBatches * batchSize); 10842 PetscInt offset = numCells - numRemainder; 10843 10844 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10845 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10846 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10847 } 10848 } 10849 for (c = cStart; c < cEnd; ++c) { 10850 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10851 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10852 } 10853 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10854 10855 /* Assemble matrix, using the 2-step process: 10856 MatAssemblyBegin(), MatAssemblyEnd(). */ 10857 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10858 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10859 10860 if (mesh->printFEM) { 10861 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10862 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10863 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10864 } 10865 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10866 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10867 if (isShell) { 10868 JacActionCtx *jctx; 10869 10870 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10871 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10872 } 10873 *str = SAME_NONZERO_PATTERN; 10874 PetscFunctionReturn(0); 10875 } 10876 10877 10878 #undef __FUNCT__ 10879 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10880 /*@C 10881 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10882 the local section and an SF describing the section point overlap. 10883 10884 Input Parameters: 10885 + s - The PetscSection for the local field layout 10886 . sf - The SF describing parallel layout of the section points 10887 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10888 . label - The label specifying the points 10889 - labelValue - The label stratum specifying the points 10890 10891 Output Parameter: 10892 . gsection - The PetscSection for the global field layout 10893 10894 Note: This gives negative sizes and offsets to points not owned by this process 10895 10896 Level: developer 10897 10898 .seealso: PetscSectionCreate() 10899 @*/ 10900 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10901 { 10902 PetscInt *neg; 10903 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10904 PetscErrorCode ierr; 10905 10906 PetscFunctionBegin; 10907 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10908 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10909 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10910 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10911 /* Mark ghost points with negative dof */ 10912 for (p = pStart; p < pEnd; ++p) { 10913 PetscInt value; 10914 10915 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10916 if (value != labelValue) continue; 10917 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10918 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10919 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10920 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10921 neg[p-pStart] = -(dof+1); 10922 } 10923 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10924 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10925 if (nroots >= 0) { 10926 if (nroots > pEnd - pStart) { 10927 PetscInt *tmpDof; 10928 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10929 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10930 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10931 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10932 for (p = pStart; p < pEnd; ++p) { 10933 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 10934 } 10935 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10936 } else { 10937 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10938 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10939 } 10940 } 10941 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10942 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10943 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10944 (*gsection)->atlasOff[p] = off; 10945 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10946 } 10947 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10948 globalOff -= off; 10949 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10950 (*gsection)->atlasOff[p] += globalOff; 10951 neg[p] = -((*gsection)->atlasOff[p]+1); 10952 } 10953 /* Put in negative offsets for ghost points */ 10954 if (nroots >= 0) { 10955 if (nroots > pEnd - pStart) { 10956 PetscInt *tmpOff; 10957 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10958 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10959 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10960 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10961 for (p = pStart; p < pEnd; ++p) { 10962 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 10963 } 10964 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10965 } else { 10966 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10967 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10968 } 10969 } 10970 ierr = PetscFree(neg);CHKERRQ(ierr); 10971 PetscFunctionReturn(0); 10972 } 10973