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