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