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