1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/vecimpl.h> 4 #include <petsc-private/isimpl.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 8 9 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "VecView_Plex_Local" 14 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 15 { 16 DM dm; 17 PetscBool isvtk; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 22 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 23 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 24 if (isvtk) { 25 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 26 PetscSection section; 27 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 28 29 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 30 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 33 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 34 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 35 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 36 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 37 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 38 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 39 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 40 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 41 } else if (cdof && vdof) { 42 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 43 } else if (cdof) { 44 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 45 * vector or just happens to have the same number of dofs as the dimension. */ 46 if (cdof == dim) { 47 ft = PETSC_VTK_CELL_VECTOR_FIELD; 48 } else { 49 ft = PETSC_VTK_CELL_FIELD; 50 } 51 } else if (vdof) { 52 if (vdof == dim) { 53 ft = PETSC_VTK_POINT_VECTOR_FIELD; 54 } else { 55 ft = PETSC_VTK_POINT_FIELD; 56 } 57 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 58 59 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 61 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 62 } else { 63 PetscBool isseq; 64 65 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 66 if (isseq) { 67 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 68 } else { 69 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "VecView_Plex" 77 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 78 { 79 DM dm; 80 PetscBool isvtk; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 85 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 86 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 87 if (isvtk) { 88 Vec locv; 89 const char *name; 90 91 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 92 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 93 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 96 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 97 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 98 } else { 99 PetscBool isseq; 100 101 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 102 if (isseq) { 103 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 104 } else { 105 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexView_Ascii" 113 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 114 { 115 DM_Plex *mesh = (DM_Plex*) dm->data; 116 DM cdm; 117 DMLabel markers; 118 PetscSection coordSection; 119 Vec coordinates; 120 PetscViewerFormat format; 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 125 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 126 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 127 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 128 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 129 const char *name; 130 PetscInt maxConeSize, maxSupportSize; 131 PetscInt pStart, pEnd, p; 132 PetscMPIInt rank, size; 133 134 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 135 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 136 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 137 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 138 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 143 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 144 for (p = pStart; p < pEnd; ++p) { 145 PetscInt dof, off, s; 146 147 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 148 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 149 for (s = off; s < off+dof; ++s) { 150 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 151 } 152 } 153 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 154 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 155 for (p = pStart; p < pEnd; ++p) { 156 PetscInt dof, off, c; 157 158 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 159 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 160 for (c = off; c < off+dof; ++c) { 161 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 162 } 163 } 164 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 165 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 166 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 167 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 168 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 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 = 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 = DMLabelDestroy(&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 = 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 = 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 = 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 = 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(NULL, "-dm_view_preallocation", &debug, 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, 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, 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, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 512 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 513 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 514 515 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 516 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 517 518 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 519 520 /* 521 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 522 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 523 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 524 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 525 Create sfAdj connecting rootSectionAdj and leafSectionAdj 526 3. Visit unowned points on interface, write adjacencies to adj 527 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 528 4. Visit owned points on interface, write adjacencies to rootAdj 529 Remove redundancy in rootAdj 530 ** The last two traversals use transitive closure 531 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 532 Allocate memory addressed by sectionAdj (cols) 533 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 534 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 535 */ 536 537 for (l = 0; l < nleaves; ++l) { 538 PetscInt dof, off, d, q; 539 PetscInt p = leaves[l], numAdj = maxAdjSize; 540 541 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 542 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 543 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 544 for (q = 0; q < numAdj; ++q) { 545 PetscInt ndof, ncdof; 546 547 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 548 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 549 for (d = off; d < off+dof; ++d) { 550 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 551 } 552 } 553 } 554 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 555 if (debug) { 556 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 557 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 558 } 559 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 560 if (size > 1) { 561 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 562 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 563 } 564 if (debug) { 565 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 566 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 567 } 568 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 569 for (p = pStart; p < pEnd; ++p) { 570 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 571 572 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 573 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 574 if (!dof) continue; 575 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 576 if (adof <= 0) continue; 577 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 578 for (q = 0; q < numAdj; ++q) { 579 PetscInt ndof, ncdof; 580 581 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 582 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 583 for (d = off; d < off+dof; ++d) { 584 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 585 } 586 } 587 } 588 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 589 if (debug) { 590 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 591 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 592 } 593 /* Create adj SF based on dof SF */ 594 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 595 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 596 if (debug) { 597 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 598 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 599 } 600 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 601 /* Create leaf adjacency */ 602 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 603 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 604 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 605 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 606 for (l = 0; l < nleaves; ++l) { 607 PetscInt dof, off, d, q; 608 PetscInt p = leaves[l], numAdj = maxAdjSize; 609 610 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 611 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 612 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 613 for (d = off; d < off+dof; ++d) { 614 PetscInt aoff, i = 0; 615 616 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 617 for (q = 0; q < numAdj; ++q) { 618 PetscInt ndof, ncdof, ngoff, nd; 619 620 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 621 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 622 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 623 for (nd = 0; nd < ndof-ncdof; ++nd) { 624 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 625 ++i; 626 } 627 } 628 } 629 } 630 /* Debugging */ 631 if (debug) { 632 IS tmp; 633 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 634 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 635 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 636 } 637 /* Gather adjacenct indices to root */ 638 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 639 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 640 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 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, 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, 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, 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, NULL);CHKERRQ(ierr); 827 } 828 /* Create allocation vectors from adjacency graph */ 829 ierr = MatGetLocalSize(A, &locRows, 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 PetscInt *tmpClosure,*tmpAdj,*visits; 900 PetscInt c,cStart,cEnd,pStart,pEnd; 901 PetscErrorCode ierr; 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 908 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 909 910 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 911 npoints = pEnd - pStart; 912 913 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 914 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 915 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 916 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 917 for (c=cStart; c<cEnd; c++) { 918 PetscInt *support = tmpClosure; 919 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 920 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 921 } 922 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 923 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 924 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 925 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 926 927 ierr = PetscSFGetRanks();CHKERRQ(ierr); 928 929 930 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 931 for (c=cStart; c<cEnd; c++) { 932 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 933 /* 934 Depth-first walk of transitive closure. 935 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. 936 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 937 */ 938 } 939 940 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 941 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 942 PetscFunctionReturn(0); 943 } 944 #endif 945 946 #undef __FUNCT__ 947 #define __FUNCT__ "DMCreateMatrix_Plex" 948 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 949 { 950 PetscSection section, sectionGlobal; 951 PetscInt bs = -1; 952 PetscInt localSize; 953 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 954 PetscErrorCode ierr; 955 956 PetscFunctionBegin; 957 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 958 ierr = MatInitializePackage(NULL);CHKERRQ(ierr); 959 #endif 960 if (!mtype) mtype = MATAIJ; 961 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 962 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 963 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 964 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 965 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 966 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 967 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 968 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 974 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 975 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 976 /* Check for symmetric storage */ 977 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 978 if (isSymmetric) { 979 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 980 } 981 if (!isShell) { 982 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 983 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 984 985 if (bs < 0) { 986 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 987 PetscInt pStart, pEnd, p, dof, cdof; 988 989 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 990 for (p = pStart; p < pEnd; ++p) { 991 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 992 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 993 if (dof-cdof) { 994 if (bs < 0) { 995 bs = dof-cdof; 996 } else if (bs != dof-cdof) { 997 /* Layout does not admit a pointwise block size */ 998 bs = 1; 999 break; 1000 } 1001 } 1002 } 1003 /* Must have same blocksize on all procs (some might have no points) */ 1004 bsLocal = bs; 1005 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1006 bsLocal = bs < 0 ? bsMax : bs; 1007 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1008 if (bsMin != bsMax) { 1009 bs = 1; 1010 } else { 1011 bs = bsMax; 1012 } 1013 } else { 1014 bs = 1; 1015 } 1016 } 1017 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1018 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1019 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1020 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1021 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1022 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1023 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1024 } 1025 PetscFunctionReturn(0); 1026 } 1027 1028 #undef __FUNCT__ 1029 #define __FUNCT__ "DMPlexGetDimension" 1030 /*@ 1031 DMPlexGetDimension - Return the topological mesh dimension 1032 1033 Not collective 1034 1035 Input Parameter: 1036 . mesh - The DMPlex 1037 1038 Output Parameter: 1039 . dim - The topological mesh dimension 1040 1041 Level: beginner 1042 1043 .seealso: DMPlexCreate() 1044 @*/ 1045 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1046 { 1047 DM_Plex *mesh = (DM_Plex*) dm->data; 1048 1049 PetscFunctionBegin; 1050 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1051 PetscValidPointer(dim, 2); 1052 *dim = mesh->dim; 1053 PetscFunctionReturn(0); 1054 } 1055 1056 #undef __FUNCT__ 1057 #define __FUNCT__ "DMPlexSetDimension" 1058 /*@ 1059 DMPlexSetDimension - Set the topological mesh dimension 1060 1061 Collective on mesh 1062 1063 Input Parameters: 1064 + mesh - The DMPlex 1065 - dim - The topological mesh dimension 1066 1067 Level: beginner 1068 1069 .seealso: DMPlexCreate() 1070 @*/ 1071 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1072 { 1073 DM_Plex *mesh = (DM_Plex*) dm->data; 1074 1075 PetscFunctionBegin; 1076 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1077 PetscValidLogicalCollectiveInt(dm, dim, 2); 1078 mesh->dim = dim; 1079 mesh->preallocCenterDim = dim; 1080 PetscFunctionReturn(0); 1081 } 1082 1083 #undef __FUNCT__ 1084 #define __FUNCT__ "DMPlexGetChart" 1085 /*@ 1086 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1087 1088 Not collective 1089 1090 Input Parameter: 1091 . mesh - The DMPlex 1092 1093 Output Parameters: 1094 + pStart - The first mesh point 1095 - pEnd - The upper bound for mesh points 1096 1097 Level: beginner 1098 1099 .seealso: DMPlexCreate(), DMPlexSetChart() 1100 @*/ 1101 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1102 { 1103 DM_Plex *mesh = (DM_Plex*) dm->data; 1104 PetscErrorCode ierr; 1105 1106 PetscFunctionBegin; 1107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1108 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1109 PetscFunctionReturn(0); 1110 } 1111 1112 #undef __FUNCT__ 1113 #define __FUNCT__ "DMPlexSetChart" 1114 /*@ 1115 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1116 1117 Not collective 1118 1119 Input Parameters: 1120 + mesh - The DMPlex 1121 . pStart - The first mesh point 1122 - pEnd - The upper bound for mesh points 1123 1124 Output Parameters: 1125 1126 Level: beginner 1127 1128 .seealso: DMPlexCreate(), DMPlexGetChart() 1129 @*/ 1130 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1131 { 1132 DM_Plex *mesh = (DM_Plex*) dm->data; 1133 PetscErrorCode ierr; 1134 1135 PetscFunctionBegin; 1136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1137 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1138 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1139 PetscFunctionReturn(0); 1140 } 1141 1142 #undef __FUNCT__ 1143 #define __FUNCT__ "DMPlexGetConeSize" 1144 /*@ 1145 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1146 1147 Not collective 1148 1149 Input Parameters: 1150 + mesh - The DMPlex 1151 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1152 1153 Output Parameter: 1154 . size - The cone size for point p 1155 1156 Level: beginner 1157 1158 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1159 @*/ 1160 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1161 { 1162 DM_Plex *mesh = (DM_Plex*) dm->data; 1163 PetscErrorCode ierr; 1164 1165 PetscFunctionBegin; 1166 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1167 PetscValidPointer(size, 3); 1168 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1169 PetscFunctionReturn(0); 1170 } 1171 1172 #undef __FUNCT__ 1173 #define __FUNCT__ "DMPlexSetConeSize" 1174 /*@ 1175 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1176 1177 Not collective 1178 1179 Input Parameters: 1180 + mesh - The DMPlex 1181 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1182 - size - The cone size for point p 1183 1184 Output Parameter: 1185 1186 Note: 1187 This should be called after DMPlexSetChart(). 1188 1189 Level: beginner 1190 1191 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1192 @*/ 1193 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1194 { 1195 DM_Plex *mesh = (DM_Plex*) dm->data; 1196 PetscErrorCode ierr; 1197 1198 PetscFunctionBegin; 1199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1200 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1201 1202 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1203 PetscFunctionReturn(0); 1204 } 1205 1206 #undef __FUNCT__ 1207 #define __FUNCT__ "DMPlexGetCone" 1208 /*@C 1209 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1210 1211 Not collective 1212 1213 Input Parameters: 1214 + mesh - The DMPlex 1215 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1216 1217 Output Parameter: 1218 . cone - An array of points which are on the in-edges for point p 1219 1220 Level: beginner 1221 1222 Note: 1223 This routine is not available in Fortran. 1224 1225 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1226 @*/ 1227 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1228 { 1229 DM_Plex *mesh = (DM_Plex*) dm->data; 1230 PetscInt off; 1231 PetscErrorCode ierr; 1232 1233 PetscFunctionBegin; 1234 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1235 PetscValidPointer(cone, 3); 1236 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1237 *cone = &mesh->cones[off]; 1238 PetscFunctionReturn(0); 1239 } 1240 1241 #undef __FUNCT__ 1242 #define __FUNCT__ "DMPlexSetCone" 1243 /*@ 1244 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1245 1246 Not collective 1247 1248 Input Parameters: 1249 + mesh - The DMPlex 1250 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1251 - cone - An array of points which are on the in-edges for point p 1252 1253 Output Parameter: 1254 1255 Note: 1256 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1257 1258 Level: beginner 1259 1260 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1261 @*/ 1262 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1263 { 1264 DM_Plex *mesh = (DM_Plex*) dm->data; 1265 PetscInt pStart, pEnd; 1266 PetscInt dof, off, c; 1267 PetscErrorCode ierr; 1268 1269 PetscFunctionBegin; 1270 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1271 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1272 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1273 if (dof) PetscValidPointer(cone, 3); 1274 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1275 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); 1276 for (c = 0; c < dof; ++c) { 1277 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); 1278 mesh->cones[off+c] = cone[c]; 1279 } 1280 PetscFunctionReturn(0); 1281 } 1282 1283 #undef __FUNCT__ 1284 #define __FUNCT__ "DMPlexGetConeOrientation" 1285 /*@C 1286 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1287 1288 Not collective 1289 1290 Input Parameters: 1291 + mesh - The DMPlex 1292 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1293 1294 Output Parameter: 1295 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1296 integer giving the prescription for cone traversal. If it is negative, the cone is 1297 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1298 the index of the cone point on which to start. 1299 1300 Level: beginner 1301 1302 Note: 1303 This routine is not available in Fortran. 1304 1305 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1306 @*/ 1307 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1308 { 1309 DM_Plex *mesh = (DM_Plex*) dm->data; 1310 PetscInt off; 1311 PetscErrorCode ierr; 1312 1313 PetscFunctionBegin; 1314 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1315 #if defined(PETSC_USE_DEBUG) 1316 { 1317 PetscInt dof; 1318 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1319 if (dof) PetscValidPointer(coneOrientation, 3); 1320 } 1321 #endif 1322 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1323 1324 *coneOrientation = &mesh->coneOrientations[off]; 1325 PetscFunctionReturn(0); 1326 } 1327 1328 #undef __FUNCT__ 1329 #define __FUNCT__ "DMPlexSetConeOrientation" 1330 /*@ 1331 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1332 1333 Not collective 1334 1335 Input Parameters: 1336 + mesh - The DMPlex 1337 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1338 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1339 integer giving the prescription for cone traversal. If it is negative, the cone is 1340 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1341 the index of the cone point on which to start. 1342 1343 Output Parameter: 1344 1345 Note: 1346 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1347 1348 Level: beginner 1349 1350 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1351 @*/ 1352 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1353 { 1354 DM_Plex *mesh = (DM_Plex*) dm->data; 1355 PetscInt pStart, pEnd; 1356 PetscInt dof, off, c; 1357 PetscErrorCode ierr; 1358 1359 PetscFunctionBegin; 1360 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1361 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1362 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1363 if (dof) PetscValidPointer(coneOrientation, 3); 1364 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1365 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); 1366 for (c = 0; c < dof; ++c) { 1367 PetscInt cdof, o = coneOrientation[c]; 1368 1369 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1370 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); 1371 mesh->coneOrientations[off+c] = o; 1372 } 1373 PetscFunctionReturn(0); 1374 } 1375 1376 #undef __FUNCT__ 1377 #define __FUNCT__ "DMPlexInsertCone" 1378 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1379 { 1380 DM_Plex *mesh = (DM_Plex*) dm->data; 1381 PetscInt pStart, pEnd; 1382 PetscInt dof, off; 1383 PetscErrorCode ierr; 1384 1385 PetscFunctionBegin; 1386 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1387 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1388 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1389 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1390 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); 1391 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); 1392 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); 1393 mesh->cones[off+conePos] = conePoint; 1394 PetscFunctionReturn(0); 1395 } 1396 1397 #undef __FUNCT__ 1398 #define __FUNCT__ "DMPlexGetSupportSize" 1399 /*@ 1400 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1401 1402 Not collective 1403 1404 Input Parameters: 1405 + mesh - The DMPlex 1406 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1407 1408 Output Parameter: 1409 . size - The support size for point p 1410 1411 Level: beginner 1412 1413 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1414 @*/ 1415 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1416 { 1417 DM_Plex *mesh = (DM_Plex*) dm->data; 1418 PetscErrorCode ierr; 1419 1420 PetscFunctionBegin; 1421 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1422 PetscValidPointer(size, 3); 1423 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1424 PetscFunctionReturn(0); 1425 } 1426 1427 #undef __FUNCT__ 1428 #define __FUNCT__ "DMPlexSetSupportSize" 1429 /*@ 1430 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1431 1432 Not collective 1433 1434 Input Parameters: 1435 + mesh - The DMPlex 1436 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1437 - size - The support size for point p 1438 1439 Output Parameter: 1440 1441 Note: 1442 This should be called after DMPlexSetChart(). 1443 1444 Level: beginner 1445 1446 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1447 @*/ 1448 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1449 { 1450 DM_Plex *mesh = (DM_Plex*) dm->data; 1451 PetscErrorCode ierr; 1452 1453 PetscFunctionBegin; 1454 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1455 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1456 1457 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1458 PetscFunctionReturn(0); 1459 } 1460 1461 #undef __FUNCT__ 1462 #define __FUNCT__ "DMPlexGetSupport" 1463 /*@C 1464 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1465 1466 Not collective 1467 1468 Input Parameters: 1469 + mesh - The DMPlex 1470 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1471 1472 Output Parameter: 1473 . support - An array of points which are on the out-edges for point p 1474 1475 Level: beginner 1476 1477 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1478 @*/ 1479 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1480 { 1481 DM_Plex *mesh = (DM_Plex*) dm->data; 1482 PetscInt off; 1483 PetscErrorCode ierr; 1484 1485 PetscFunctionBegin; 1486 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1487 PetscValidPointer(support, 3); 1488 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1489 *support = &mesh->supports[off]; 1490 PetscFunctionReturn(0); 1491 } 1492 1493 #undef __FUNCT__ 1494 #define __FUNCT__ "DMPlexSetSupport" 1495 /*@ 1496 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1497 1498 Not collective 1499 1500 Input Parameters: 1501 + mesh - The DMPlex 1502 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1503 - support - An array of points which are on the in-edges for point p 1504 1505 Output Parameter: 1506 1507 Note: 1508 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1509 1510 Level: beginner 1511 1512 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1513 @*/ 1514 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1515 { 1516 DM_Plex *mesh = (DM_Plex*) dm->data; 1517 PetscInt pStart, pEnd; 1518 PetscInt dof, off, c; 1519 PetscErrorCode ierr; 1520 1521 PetscFunctionBegin; 1522 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1523 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1524 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1525 if (dof) PetscValidPointer(support, 3); 1526 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1527 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); 1528 for (c = 0; c < dof; ++c) { 1529 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); 1530 mesh->supports[off+c] = support[c]; 1531 } 1532 PetscFunctionReturn(0); 1533 } 1534 1535 #undef __FUNCT__ 1536 #define __FUNCT__ "DMPlexInsertSupport" 1537 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1538 { 1539 DM_Plex *mesh = (DM_Plex*) dm->data; 1540 PetscInt pStart, pEnd; 1541 PetscInt dof, off; 1542 PetscErrorCode ierr; 1543 1544 PetscFunctionBegin; 1545 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1546 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1547 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1548 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1549 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); 1550 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); 1551 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); 1552 mesh->supports[off+supportPos] = supportPoint; 1553 PetscFunctionReturn(0); 1554 } 1555 1556 #undef __FUNCT__ 1557 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1558 /*@C 1559 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1560 1561 Not collective 1562 1563 Input Parameters: 1564 + mesh - The DMPlex 1565 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1566 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1567 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1568 1569 Output Parameters: 1570 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1571 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1572 1573 Note: 1574 If using internal storage (points is NULL on input), each call overwrites the last output. 1575 1576 Level: beginner 1577 1578 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1579 @*/ 1580 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1581 { 1582 DM_Plex *mesh = (DM_Plex*) dm->data; 1583 PetscInt *closure, *fifo; 1584 const PetscInt *tmp = NULL, *tmpO = NULL; 1585 PetscInt tmpSize, t; 1586 PetscInt depth = 0, maxSize; 1587 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1588 PetscErrorCode ierr; 1589 1590 PetscFunctionBegin; 1591 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1592 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1593 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1594 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1595 if (*points) { 1596 closure = *points; 1597 } else { 1598 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1599 } 1600 closure[0] = p; closure[1] = 0; 1601 /* This is only 1-level */ 1602 if (useCone) { 1603 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1604 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1605 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1606 } else { 1607 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1608 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1609 } 1610 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1611 const PetscInt cp = tmp[t]; 1612 const PetscInt co = tmpO ? tmpO[t] : 0; 1613 1614 closure[closureSize] = cp; 1615 closure[closureSize+1] = co; 1616 fifo[fifoSize] = cp; 1617 fifo[fifoSize+1] = co; 1618 } 1619 while (fifoSize - fifoStart) { 1620 const PetscInt q = fifo[fifoStart]; 1621 const PetscInt o = fifo[fifoStart+1]; 1622 const PetscInt rev = o >= 0 ? 0 : 1; 1623 const PetscInt off = rev ? -(o+1) : o; 1624 1625 if (useCone) { 1626 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1627 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1628 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1629 } else { 1630 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1631 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1632 tmpO = NULL; 1633 } 1634 for (t = 0; t < tmpSize; ++t) { 1635 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1636 const PetscInt cp = tmp[i]; 1637 /* Must propogate orientation */ 1638 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1639 PetscInt c; 1640 1641 /* Check for duplicate */ 1642 for (c = 0; c < closureSize; c += 2) { 1643 if (closure[c] == cp) break; 1644 } 1645 if (c == closureSize) { 1646 closure[closureSize] = cp; 1647 closure[closureSize+1] = co; 1648 fifo[fifoSize] = cp; 1649 fifo[fifoSize+1] = co; 1650 closureSize += 2; 1651 fifoSize += 2; 1652 } 1653 } 1654 fifoStart += 2; 1655 } 1656 if (numPoints) *numPoints = closureSize/2; 1657 if (points) *points = closure; 1658 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1659 PetscFunctionReturn(0); 1660 } 1661 1662 #undef __FUNCT__ 1663 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1664 /*@C 1665 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1666 1667 Not collective 1668 1669 Input Parameters: 1670 + mesh - The DMPlex 1671 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1672 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1673 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1674 1675 Output Parameters: 1676 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1677 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1678 1679 Note: 1680 If not using internal storage (points is not NULL on input), this call is unnecessary 1681 1682 Level: beginner 1683 1684 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1685 @*/ 1686 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1687 { 1688 PetscErrorCode ierr; 1689 1690 PetscFunctionBegin; 1691 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1692 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1693 PetscFunctionReturn(0); 1694 } 1695 1696 #undef __FUNCT__ 1697 #define __FUNCT__ "DMPlexGetFaces" 1698 /* 1699 DMPlexGetFaces - 1700 1701 Note: This will only work for cell-vertex meshes. 1702 */ 1703 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1704 { 1705 DM_Plex *mesh = (DM_Plex*) dm->data; 1706 const PetscInt *cone = NULL; 1707 PetscInt depth = 0, dim, coneSize; 1708 PetscErrorCode ierr; 1709 1710 PetscFunctionBegin; 1711 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1712 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1713 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1714 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1715 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1716 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1717 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1718 switch (dim) { 1719 case 2: 1720 switch (coneSize) { 1721 case 3: 1722 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1723 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1724 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1725 *numFaces = 3; 1726 *faceSize = 2; 1727 *faces = mesh->facesTmp; 1728 break; 1729 case 4: 1730 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1731 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1732 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1733 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1734 *numFaces = 4; 1735 *faceSize = 2; 1736 *faces = mesh->facesTmp; 1737 break; 1738 default: 1739 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1740 } 1741 break; 1742 case 3: 1743 switch (coneSize) { 1744 case 3: 1745 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1746 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1747 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1748 *numFaces = 3; 1749 *faceSize = 2; 1750 *faces = mesh->facesTmp; 1751 break; 1752 case 4: 1753 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1754 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1755 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1756 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1757 *numFaces = 4; 1758 *faceSize = 3; 1759 *faces = mesh->facesTmp; 1760 break; 1761 default: 1762 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1763 } 1764 break; 1765 default: 1766 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1767 } 1768 PetscFunctionReturn(0); 1769 } 1770 1771 #undef __FUNCT__ 1772 #define __FUNCT__ "DMPlexGetMaxSizes" 1773 /*@ 1774 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1775 1776 Not collective 1777 1778 Input Parameter: 1779 . mesh - The DMPlex 1780 1781 Output Parameters: 1782 + maxConeSize - The maximum number of in-edges 1783 - maxSupportSize - The maximum number of out-edges 1784 1785 Level: beginner 1786 1787 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1788 @*/ 1789 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1790 { 1791 DM_Plex *mesh = (DM_Plex*) dm->data; 1792 1793 PetscFunctionBegin; 1794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1795 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1796 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1797 PetscFunctionReturn(0); 1798 } 1799 1800 #undef __FUNCT__ 1801 #define __FUNCT__ "DMSetUp_Plex" 1802 PetscErrorCode DMSetUp_Plex(DM dm) 1803 { 1804 DM_Plex *mesh = (DM_Plex*) dm->data; 1805 PetscInt size; 1806 PetscErrorCode ierr; 1807 1808 PetscFunctionBegin; 1809 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1810 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1811 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1812 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1813 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1814 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1815 if (mesh->maxSupportSize) { 1816 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1817 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1818 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1819 } 1820 PetscFunctionReturn(0); 1821 } 1822 1823 #undef __FUNCT__ 1824 #define __FUNCT__ "DMCreateSubDM_Plex" 1825 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1826 { 1827 PetscSection section, sectionGlobal; 1828 PetscInt *subIndices; 1829 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1830 PetscErrorCode ierr; 1831 1832 PetscFunctionBegin; 1833 if (!numFields) PetscFunctionReturn(0); 1834 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1835 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1836 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1837 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1838 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1839 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); 1840 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1841 for (p = pStart; p < pEnd; ++p) { 1842 PetscInt gdof; 1843 1844 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1845 if (gdof > 0) { 1846 for (f = 0; f < numFields; ++f) { 1847 PetscInt fdof, fcdof; 1848 1849 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1850 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1851 subSize += fdof-fcdof; 1852 } 1853 } 1854 } 1855 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1856 for (p = pStart; p < pEnd; ++p) { 1857 PetscInt gdof, goff; 1858 1859 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1860 if (gdof > 0) { 1861 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1862 for (f = 0; f < numFields; ++f) { 1863 PetscInt fdof, fcdof, fc, f2, poff = 0; 1864 1865 /* Can get rid of this loop by storing field information in the global section */ 1866 for (f2 = 0; f2 < fields[f]; ++f2) { 1867 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1868 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1869 poff += fdof-fcdof; 1870 } 1871 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1872 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1873 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1874 subIndices[subOff] = goff+poff+fc; 1875 } 1876 } 1877 } 1878 } 1879 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1880 if (subdm) { 1881 PetscSection subsection; 1882 PetscBool haveNull = PETSC_FALSE; 1883 PetscInt f, nf = 0; 1884 1885 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1886 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1887 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1888 for (f = 0; f < numFields; ++f) { 1889 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1890 if ((*subdm)->nullspaceConstructors[f]) { 1891 haveNull = PETSC_TRUE; 1892 nf = f; 1893 } 1894 } 1895 if (haveNull) { 1896 MatNullSpace nullSpace; 1897 1898 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1899 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1900 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1901 } 1902 if (dm->fields) { 1903 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); 1904 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1905 for (f = 0; f < numFields; ++f) { 1906 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1907 } 1908 if (numFields == 1) { 1909 MatNullSpace space; 1910 Mat pmat; 1911 1912 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1913 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1914 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1915 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1916 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1917 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1918 } 1919 } 1920 } 1921 PetscFunctionReturn(0); 1922 } 1923 1924 #undef __FUNCT__ 1925 #define __FUNCT__ "DMPlexSymmetrize" 1926 /*@ 1927 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1928 1929 Not collective 1930 1931 Input Parameter: 1932 . mesh - The DMPlex 1933 1934 Output Parameter: 1935 1936 Note: 1937 This should be called after all calls to DMPlexSetCone() 1938 1939 Level: beginner 1940 1941 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1942 @*/ 1943 PetscErrorCode DMPlexSymmetrize(DM dm) 1944 { 1945 DM_Plex *mesh = (DM_Plex*) dm->data; 1946 PetscInt *offsets; 1947 PetscInt supportSize; 1948 PetscInt pStart, pEnd, p; 1949 PetscErrorCode ierr; 1950 1951 PetscFunctionBegin; 1952 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1953 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1954 /* Calculate support sizes */ 1955 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1956 for (p = pStart; p < pEnd; ++p) { 1957 PetscInt dof, off, c; 1958 1959 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1960 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1961 for (c = off; c < off+dof; ++c) { 1962 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1963 } 1964 } 1965 for (p = pStart; p < pEnd; ++p) { 1966 PetscInt dof; 1967 1968 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1969 1970 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1971 } 1972 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1973 /* Calculate supports */ 1974 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1975 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1976 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1977 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1978 for (p = pStart; p < pEnd; ++p) { 1979 PetscInt dof, off, c; 1980 1981 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1982 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1983 for (c = off; c < off+dof; ++c) { 1984 const PetscInt q = mesh->cones[c]; 1985 PetscInt offS; 1986 1987 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1988 1989 mesh->supports[offS+offsets[q]] = p; 1990 ++offsets[q]; 1991 } 1992 } 1993 ierr = PetscFree(offsets);CHKERRQ(ierr); 1994 PetscFunctionReturn(0); 1995 } 1996 1997 #undef __FUNCT__ 1998 #define __FUNCT__ "DMPlexSetDepth_Private" 1999 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 2000 { 2001 PetscInt d; 2002 PetscErrorCode ierr; 2003 2004 PetscFunctionBegin; 2005 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 2006 if (d < 0) { 2007 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2008 const PetscInt *cone = NULL; 2009 PetscInt dCone; 2010 2011 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2012 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2013 d = dCone+1; 2014 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2015 } 2016 *depth = d; 2017 PetscFunctionReturn(0); 2018 } 2019 2020 #undef __FUNCT__ 2021 #define __FUNCT__ "DMPlexStratify" 2022 /*@ 2023 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2024 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2025 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2026 the DAG. 2027 2028 Not collective 2029 2030 Input Parameter: 2031 . mesh - The DMPlex 2032 2033 Output Parameter: 2034 2035 Notes: 2036 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2037 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2038 2039 This should be called after all calls to DMPlexSymmetrize() 2040 2041 Level: beginner 2042 2043 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2044 @*/ 2045 PetscErrorCode DMPlexStratify(DM dm) 2046 { 2047 DM_Plex *mesh = (DM_Plex*) dm->data; 2048 PetscInt pStart, pEnd, p; 2049 PetscInt numRoots = 0, numLeaves = 0; 2050 PetscErrorCode ierr; 2051 2052 PetscFunctionBegin; 2053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2054 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2055 /* Calculate depth */ 2056 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2057 /* Initialize roots and count leaves */ 2058 for (p = pStart; p < pEnd; ++p) { 2059 PetscInt coneSize, supportSize; 2060 2061 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2062 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2063 if (!coneSize && supportSize) { 2064 ++numRoots; 2065 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2066 } else if (!supportSize && coneSize) { 2067 ++numLeaves; 2068 } else if (!supportSize && !coneSize) { 2069 /* Isolated points */ 2070 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2071 } 2072 } 2073 if (numRoots + numLeaves == (pEnd - pStart)) { 2074 for (p = pStart; p < pEnd; ++p) { 2075 PetscInt coneSize, supportSize; 2076 2077 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2078 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2079 if (!supportSize && coneSize) { 2080 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2081 } 2082 } 2083 } else { 2084 /* This might be slow since lookup is not fast */ 2085 for (p = pStart; p < pEnd; ++p) { 2086 PetscInt depth; 2087 2088 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2089 } 2090 } 2091 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2092 PetscFunctionReturn(0); 2093 } 2094 2095 #undef __FUNCT__ 2096 #define __FUNCT__ "DMPlexGetJoin" 2097 /*@C 2098 DMPlexGetJoin - Get an array for the join of the set of points 2099 2100 Not Collective 2101 2102 Input Parameters: 2103 + dm - The DMPlex object 2104 . numPoints - The number of input points for the join 2105 - points - The input points 2106 2107 Output Parameters: 2108 + numCoveredPoints - The number of points in the join 2109 - coveredPoints - The points in the join 2110 2111 Level: intermediate 2112 2113 Note: Currently, this is restricted to a single level join 2114 2115 .keywords: mesh 2116 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2117 @*/ 2118 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2119 { 2120 DM_Plex *mesh = (DM_Plex*) dm->data; 2121 PetscInt *join[2]; 2122 PetscInt joinSize, i = 0; 2123 PetscInt dof, off, p, c, m; 2124 PetscErrorCode ierr; 2125 2126 PetscFunctionBegin; 2127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2128 PetscValidPointer(points, 2); 2129 PetscValidPointer(numCoveredPoints, 3); 2130 PetscValidPointer(coveredPoints, 4); 2131 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2132 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2133 /* Copy in support of first point */ 2134 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2135 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2136 for (joinSize = 0; joinSize < dof; ++joinSize) { 2137 join[i][joinSize] = mesh->supports[off+joinSize]; 2138 } 2139 /* Check each successive support */ 2140 for (p = 1; p < numPoints; ++p) { 2141 PetscInt newJoinSize = 0; 2142 2143 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2144 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2145 for (c = 0; c < dof; ++c) { 2146 const PetscInt point = mesh->supports[off+c]; 2147 2148 for (m = 0; m < joinSize; ++m) { 2149 if (point == join[i][m]) { 2150 join[1-i][newJoinSize++] = point; 2151 break; 2152 } 2153 } 2154 } 2155 joinSize = newJoinSize; 2156 i = 1-i; 2157 } 2158 *numCoveredPoints = joinSize; 2159 *coveredPoints = join[i]; 2160 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2161 PetscFunctionReturn(0); 2162 } 2163 2164 #undef __FUNCT__ 2165 #define __FUNCT__ "DMPlexRestoreJoin" 2166 /*@C 2167 DMPlexRestoreJoin - Restore an array for the join of the set of points 2168 2169 Not Collective 2170 2171 Input Parameters: 2172 + dm - The DMPlex object 2173 . numPoints - The number of input points for the join 2174 - points - The input points 2175 2176 Output Parameters: 2177 + numCoveredPoints - The number of points in the join 2178 - coveredPoints - The points in the join 2179 2180 Level: intermediate 2181 2182 .keywords: mesh 2183 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2184 @*/ 2185 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2186 { 2187 PetscErrorCode ierr; 2188 2189 PetscFunctionBegin; 2190 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2191 PetscValidPointer(coveredPoints, 4); 2192 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2193 PetscFunctionReturn(0); 2194 } 2195 2196 #undef __FUNCT__ 2197 #define __FUNCT__ "DMPlexGetFullJoin" 2198 /*@C 2199 DMPlexGetFullJoin - Get an array for the join of the set of points 2200 2201 Not Collective 2202 2203 Input Parameters: 2204 + dm - The DMPlex object 2205 . numPoints - The number of input points for the join 2206 - points - The input points 2207 2208 Output Parameters: 2209 + numCoveredPoints - The number of points in the join 2210 - coveredPoints - The points in the join 2211 2212 Level: intermediate 2213 2214 .keywords: mesh 2215 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2216 @*/ 2217 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2218 { 2219 DM_Plex *mesh = (DM_Plex*) dm->data; 2220 PetscInt *offsets, **closures; 2221 PetscInt *join[2]; 2222 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2223 PetscInt p, d, c, m; 2224 PetscErrorCode ierr; 2225 2226 PetscFunctionBegin; 2227 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2228 PetscValidPointer(points, 2); 2229 PetscValidPointer(numCoveredPoints, 3); 2230 PetscValidPointer(coveredPoints, 4); 2231 2232 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2233 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2234 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2235 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2236 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2237 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2238 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2239 2240 for (p = 0; p < numPoints; ++p) { 2241 PetscInt closureSize; 2242 2243 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2244 2245 offsets[p*(depth+2)+0] = 0; 2246 for (d = 0; d < depth+1; ++d) { 2247 PetscInt pStart, pEnd, i; 2248 2249 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2250 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2251 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2252 offsets[p*(depth+2)+d+1] = i; 2253 break; 2254 } 2255 } 2256 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2257 } 2258 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); 2259 } 2260 for (d = 0; d < depth+1; ++d) { 2261 PetscInt dof; 2262 2263 /* Copy in support of first point */ 2264 dof = offsets[d+1] - offsets[d]; 2265 for (joinSize = 0; joinSize < dof; ++joinSize) { 2266 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2267 } 2268 /* Check each successive cone */ 2269 for (p = 1; p < numPoints && joinSize; ++p) { 2270 PetscInt newJoinSize = 0; 2271 2272 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2273 for (c = 0; c < dof; ++c) { 2274 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2275 2276 for (m = 0; m < joinSize; ++m) { 2277 if (point == join[i][m]) { 2278 join[1-i][newJoinSize++] = point; 2279 break; 2280 } 2281 } 2282 } 2283 joinSize = newJoinSize; 2284 i = 1-i; 2285 } 2286 if (joinSize) break; 2287 } 2288 *numCoveredPoints = joinSize; 2289 *coveredPoints = join[i]; 2290 for (p = 0; p < numPoints; ++p) { 2291 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2292 } 2293 ierr = PetscFree(closures);CHKERRQ(ierr); 2294 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2295 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2296 PetscFunctionReturn(0); 2297 } 2298 2299 #undef __FUNCT__ 2300 #define __FUNCT__ "DMPlexGetMeet" 2301 /*@C 2302 DMPlexGetMeet - Get an array for the meet of the set of points 2303 2304 Not Collective 2305 2306 Input Parameters: 2307 + dm - The DMPlex object 2308 . numPoints - The number of input points for the meet 2309 - points - The input points 2310 2311 Output Parameters: 2312 + numCoveredPoints - The number of points in the meet 2313 - coveredPoints - The points in the meet 2314 2315 Level: intermediate 2316 2317 Note: Currently, this is restricted to a single level meet 2318 2319 .keywords: mesh 2320 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2321 @*/ 2322 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2323 { 2324 DM_Plex *mesh = (DM_Plex*) dm->data; 2325 PetscInt *meet[2]; 2326 PetscInt meetSize, i = 0; 2327 PetscInt dof, off, p, c, m; 2328 PetscErrorCode ierr; 2329 2330 PetscFunctionBegin; 2331 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2332 PetscValidPointer(points, 2); 2333 PetscValidPointer(numCoveringPoints, 3); 2334 PetscValidPointer(coveringPoints, 4); 2335 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2336 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2337 /* Copy in cone of first point */ 2338 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2339 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2340 for (meetSize = 0; meetSize < dof; ++meetSize) { 2341 meet[i][meetSize] = mesh->cones[off+meetSize]; 2342 } 2343 /* Check each successive cone */ 2344 for (p = 1; p < numPoints; ++p) { 2345 PetscInt newMeetSize = 0; 2346 2347 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2348 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2349 for (c = 0; c < dof; ++c) { 2350 const PetscInt point = mesh->cones[off+c]; 2351 2352 for (m = 0; m < meetSize; ++m) { 2353 if (point == meet[i][m]) { 2354 meet[1-i][newMeetSize++] = point; 2355 break; 2356 } 2357 } 2358 } 2359 meetSize = newMeetSize; 2360 i = 1-i; 2361 } 2362 *numCoveringPoints = meetSize; 2363 *coveringPoints = meet[i]; 2364 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2365 PetscFunctionReturn(0); 2366 } 2367 2368 #undef __FUNCT__ 2369 #define __FUNCT__ "DMPlexRestoreMeet" 2370 /*@C 2371 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2372 2373 Not Collective 2374 2375 Input Parameters: 2376 + dm - The DMPlex object 2377 . numPoints - The number of input points for the meet 2378 - points - The input points 2379 2380 Output Parameters: 2381 + numCoveredPoints - The number of points in the meet 2382 - coveredPoints - The points in the meet 2383 2384 Level: intermediate 2385 2386 .keywords: mesh 2387 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2388 @*/ 2389 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2390 { 2391 PetscErrorCode ierr; 2392 2393 PetscFunctionBegin; 2394 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2395 PetscValidPointer(coveredPoints, 4); 2396 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2397 PetscFunctionReturn(0); 2398 } 2399 2400 #undef __FUNCT__ 2401 #define __FUNCT__ "DMPlexGetFullMeet" 2402 /*@C 2403 DMPlexGetFullMeet - Get an array for the meet of the set of points 2404 2405 Not Collective 2406 2407 Input Parameters: 2408 + dm - The DMPlex object 2409 . numPoints - The number of input points for the meet 2410 - points - The input points 2411 2412 Output Parameters: 2413 + numCoveredPoints - The number of points in the meet 2414 - coveredPoints - The points in the meet 2415 2416 Level: intermediate 2417 2418 .keywords: mesh 2419 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2420 @*/ 2421 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2422 { 2423 DM_Plex *mesh = (DM_Plex*) dm->data; 2424 PetscInt *offsets, **closures; 2425 PetscInt *meet[2]; 2426 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2427 PetscInt p, h, c, m; 2428 PetscErrorCode ierr; 2429 2430 PetscFunctionBegin; 2431 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2432 PetscValidPointer(points, 2); 2433 PetscValidPointer(numCoveredPoints, 3); 2434 PetscValidPointer(coveredPoints, 4); 2435 2436 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2437 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2438 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2439 maxSize = PetscPowInt(mesh->maxConeSize,height); 2440 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2441 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2442 2443 for (p = 0; p < numPoints; ++p) { 2444 PetscInt closureSize; 2445 2446 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2447 2448 offsets[p*(height+2)+0] = 0; 2449 for (h = 0; h < height+1; ++h) { 2450 PetscInt pStart, pEnd, i; 2451 2452 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2453 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2454 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2455 offsets[p*(height+2)+h+1] = i; 2456 break; 2457 } 2458 } 2459 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2460 } 2461 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); 2462 } 2463 for (h = 0; h < height+1; ++h) { 2464 PetscInt dof; 2465 2466 /* Copy in cone of first point */ 2467 dof = offsets[h+1] - offsets[h]; 2468 for (meetSize = 0; meetSize < dof; ++meetSize) { 2469 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2470 } 2471 /* Check each successive cone */ 2472 for (p = 1; p < numPoints && meetSize; ++p) { 2473 PetscInt newMeetSize = 0; 2474 2475 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2476 for (c = 0; c < dof; ++c) { 2477 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2478 2479 for (m = 0; m < meetSize; ++m) { 2480 if (point == meet[i][m]) { 2481 meet[1-i][newMeetSize++] = point; 2482 break; 2483 } 2484 } 2485 } 2486 meetSize = newMeetSize; 2487 i = 1-i; 2488 } 2489 if (meetSize) break; 2490 } 2491 *numCoveredPoints = meetSize; 2492 *coveredPoints = meet[i]; 2493 for (p = 0; p < numPoints; ++p) { 2494 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2495 } 2496 ierr = PetscFree(closures);CHKERRQ(ierr); 2497 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2498 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2499 PetscFunctionReturn(0); 2500 } 2501 2502 #undef __FUNCT__ 2503 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2504 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2505 { 2506 MPI_Comm comm = ((PetscObject) dm)->comm; 2507 PetscInt cellDim; 2508 PetscErrorCode ierr; 2509 2510 PetscFunctionBegin; 2511 PetscValidPointer(numFaceVertices,3); 2512 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2513 switch (cellDim) { 2514 case 0: 2515 *numFaceVertices = 0; 2516 break; 2517 case 1: 2518 *numFaceVertices = 1; 2519 break; 2520 case 2: 2521 switch (numCorners) { 2522 case 3: /* triangle */ 2523 *numFaceVertices = 2; /* Edge has 2 vertices */ 2524 break; 2525 case 4: /* quadrilateral */ 2526 *numFaceVertices = 2; /* Edge has 2 vertices */ 2527 break; 2528 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2529 *numFaceVertices = 3; /* Edge has 3 vertices */ 2530 break; 2531 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2532 *numFaceVertices = 3; /* Edge has 3 vertices */ 2533 break; 2534 default: 2535 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2536 } 2537 break; 2538 case 3: 2539 switch (numCorners) { 2540 case 4: /* tetradehdron */ 2541 *numFaceVertices = 3; /* Face has 3 vertices */ 2542 break; 2543 case 6: /* tet cohesive cells */ 2544 *numFaceVertices = 4; /* Face has 4 vertices */ 2545 break; 2546 case 8: /* hexahedron */ 2547 *numFaceVertices = 4; /* Face has 4 vertices */ 2548 break; 2549 case 9: /* tet cohesive Lagrange cells */ 2550 *numFaceVertices = 6; /* Face has 6 vertices */ 2551 break; 2552 case 10: /* quadratic tetrahedron */ 2553 *numFaceVertices = 6; /* Face has 6 vertices */ 2554 break; 2555 case 12: /* hex cohesive Lagrange cells */ 2556 *numFaceVertices = 6; /* Face has 6 vertices */ 2557 break; 2558 case 18: /* quadratic tet cohesive Lagrange cells */ 2559 *numFaceVertices = 6; /* Face has 6 vertices */ 2560 break; 2561 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2562 *numFaceVertices = 9; /* Face has 9 vertices */ 2563 break; 2564 default: 2565 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2566 } 2567 break; 2568 default: 2569 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2570 } 2571 PetscFunctionReturn(0); 2572 } 2573 2574 #undef __FUNCT__ 2575 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2576 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2577 { 2578 const PetscInt maxFaceCases = 30; 2579 PetscInt numFaceCases = 0; 2580 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2581 PetscInt *off, *adj; 2582 PetscInt *neighborCells, *tmpClosure; 2583 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2584 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2585 PetscErrorCode ierr; 2586 2587 PetscFunctionBegin; 2588 /* For parallel partitioning, I think you have to communicate supports */ 2589 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2590 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2591 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2592 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2593 if (cEnd - cStart == 0) { 2594 if (numVertices) *numVertices = 0; 2595 if (offsets) *offsets = NULL; 2596 if (adjacency) *adjacency = NULL; 2597 PetscFunctionReturn(0); 2598 } 2599 numCells = cEnd - cStart; 2600 /* Setup face recognition */ 2601 if (depth == 1) { 2602 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 */ 2603 2604 for (c = cStart; c < cEnd; ++c) { 2605 PetscInt corners; 2606 2607 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2608 if (!cornersSeen[corners]) { 2609 PetscInt nFV; 2610 2611 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2612 cornersSeen[corners] = 1; 2613 2614 ierr = DMPlexGetNumFaceVertices_Internal(dm, corners, &nFV);CHKERRQ(ierr); 2615 2616 numFaceVertices[numFaceCases++] = nFV; 2617 } 2618 } 2619 } 2620 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2621 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2622 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2623 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2624 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2625 /* Count neighboring cells */ 2626 for (cell = cStart; cell < cEnd; ++cell) { 2627 PetscInt numNeighbors = maxNeighbors, n; 2628 2629 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2630 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2631 for (n = 0; n < numNeighbors; ++n) { 2632 PetscInt cellPair[2]; 2633 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2634 PetscInt meetSize = 0; 2635 const PetscInt *meet = NULL; 2636 2637 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2638 if (cellPair[0] == cellPair[1]) continue; 2639 if (!found) { 2640 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2641 if (meetSize) { 2642 PetscInt f; 2643 2644 for (f = 0; f < numFaceCases; ++f) { 2645 if (numFaceVertices[f] == meetSize) { 2646 found = PETSC_TRUE; 2647 break; 2648 } 2649 } 2650 } 2651 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2652 } 2653 if (found) ++off[cell-cStart+1]; 2654 } 2655 } 2656 /* Prefix sum */ 2657 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2658 2659 if (adjacency) { 2660 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2661 /* Get neighboring cells */ 2662 for (cell = cStart; cell < cEnd; ++cell) { 2663 PetscInt numNeighbors = maxNeighbors, n; 2664 PetscInt cellOffset = 0; 2665 2666 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2667 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2668 for (n = 0; n < numNeighbors; ++n) { 2669 PetscInt cellPair[2]; 2670 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2671 PetscInt meetSize = 0; 2672 const PetscInt *meet = NULL; 2673 2674 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2675 if (cellPair[0] == cellPair[1]) continue; 2676 if (!found) { 2677 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2678 if (meetSize) { 2679 PetscInt f; 2680 2681 for (f = 0; f < numFaceCases; ++f) { 2682 if (numFaceVertices[f] == meetSize) { 2683 found = PETSC_TRUE; 2684 break; 2685 } 2686 } 2687 } 2688 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2689 } 2690 if (found) { 2691 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2692 ++cellOffset; 2693 } 2694 } 2695 } 2696 } 2697 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2698 if (numVertices) *numVertices = numCells; 2699 if (offsets) *offsets = off; 2700 if (adjacency) *adjacency = adj; 2701 PetscFunctionReturn(0); 2702 } 2703 2704 #if defined(PETSC_HAVE_CHACO) 2705 #if defined(PETSC_HAVE_UNISTD_H) 2706 #include <unistd.h> 2707 #endif 2708 /* Chaco does not have an include file */ 2709 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2710 float *ewgts, float *x, float *y, float *z, char *outassignname, 2711 char *outfilename, short *assignment, int architecture, int ndims_tot, 2712 int mesh_dims[3], double *goal, int global_method, int local_method, 2713 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2714 2715 extern int FREE_GRAPH; 2716 2717 #undef __FUNCT__ 2718 #define __FUNCT__ "DMPlexPartition_Chaco" 2719 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2720 { 2721 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2722 MPI_Comm comm = ((PetscObject) dm)->comm; 2723 int nvtxs = numVertices; /* number of vertices in full graph */ 2724 int *vwgts = NULL; /* weights for all vertices */ 2725 float *ewgts = NULL; /* weights for all edges */ 2726 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2727 char *outassignname = NULL; /* name of assignment output file */ 2728 char *outfilename = NULL; /* output file name */ 2729 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2730 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2731 int mesh_dims[3]; /* dimensions of mesh of processors */ 2732 double *goal = NULL; /* desired set sizes for each set */ 2733 int global_method = 1; /* global partitioning algorithm */ 2734 int local_method = 1; /* local partitioning algorithm */ 2735 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2736 int vmax = 200; /* how many vertices to coarsen down to? */ 2737 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2738 double eigtol = 0.001; /* tolerance on eigenvectors */ 2739 long seed = 123636512; /* for random graph mutations */ 2740 short int *assignment; /* Output partition */ 2741 int fd_stdout, fd_pipe[2]; 2742 PetscInt *points; 2743 PetscMPIInt commSize; 2744 int i, v, p; 2745 PetscErrorCode ierr; 2746 2747 PetscFunctionBegin; 2748 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2749 if (!numVertices) { 2750 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2751 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2752 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2753 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2754 PetscFunctionReturn(0); 2755 } 2756 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2757 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2758 2759 if (global_method == INERTIAL_METHOD) { 2760 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2761 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2762 } 2763 mesh_dims[0] = commSize; 2764 mesh_dims[1] = 1; 2765 mesh_dims[2] = 1; 2766 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2767 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2768 /* TODO: check error codes for UNIX calls */ 2769 #if defined(PETSC_HAVE_UNISTD_H) 2770 { 2771 int piperet; 2772 piperet = pipe(fd_pipe); 2773 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2774 fd_stdout = dup(1); 2775 close(1); 2776 dup2(fd_pipe[1], 1); 2777 } 2778 #endif 2779 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2780 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2781 vmax, ndims, eigtol, seed); 2782 #if defined(PETSC_HAVE_UNISTD_H) 2783 { 2784 char msgLog[10000]; 2785 int count; 2786 2787 fflush(stdout); 2788 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2789 if (count < 0) count = 0; 2790 msgLog[count] = 0; 2791 close(1); 2792 dup2(fd_stdout, 1); 2793 close(fd_stdout); 2794 close(fd_pipe[0]); 2795 close(fd_pipe[1]); 2796 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2797 } 2798 #endif 2799 /* Convert to PetscSection+IS */ 2800 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2801 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2802 for (v = 0; v < nvtxs; ++v) { 2803 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2804 } 2805 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2806 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2807 for (p = 0, i = 0; p < commSize; ++p) { 2808 for (v = 0; v < nvtxs; ++v) { 2809 if (assignment[v] == p) points[i++] = v; 2810 } 2811 } 2812 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2813 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2814 if (global_method == INERTIAL_METHOD) { 2815 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2816 } 2817 ierr = PetscFree(assignment);CHKERRQ(ierr); 2818 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2819 PetscFunctionReturn(0); 2820 } 2821 #endif 2822 2823 #if defined(PETSC_HAVE_PARMETIS) 2824 #undef __FUNCT__ 2825 #define __FUNCT__ "DMPlexPartition_ParMetis" 2826 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2827 { 2828 PetscFunctionBegin; 2829 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2830 PetscFunctionReturn(0); 2831 } 2832 #endif 2833 2834 #undef __FUNCT__ 2835 #define __FUNCT__ "DMPlexEnlargePartition" 2836 /* Expand the partition by BFS on the adjacency graph */ 2837 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2838 { 2839 PetscHashI h; 2840 const PetscInt *points; 2841 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2842 PetscInt pStart, pEnd, part, q; 2843 PetscErrorCode ierr; 2844 2845 PetscFunctionBegin; 2846 PetscHashICreate(h); 2847 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2848 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2849 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2850 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2851 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2852 for (part = pStart; part < pEnd; ++part) { 2853 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2854 2855 PetscHashIClear(h); 2856 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2857 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2858 /* Add all existing points to h */ 2859 for (p = 0; p < numPoints; ++p) { 2860 const PetscInt point = points[off+p]; 2861 PetscHashIAdd(h, point, 1); 2862 } 2863 PetscHashISize(h, nP); 2864 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2865 /* Add all points in next BFS level */ 2866 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2867 for (p = 0; p < numPoints; ++p) { 2868 const PetscInt point = points[off+p]; 2869 PetscInt s = start[point], e = start[point+1], a; 2870 2871 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2872 } 2873 PetscHashISize(h, numNewPoints); 2874 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2875 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2876 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2877 totPoints += numNewPoints; 2878 } 2879 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2880 PetscHashIDestroy(h); 2881 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2882 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2883 for (part = pStart, q = 0; part < pEnd; ++part) { 2884 PetscInt numPoints, p; 2885 2886 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2887 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2888 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2889 } 2890 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2891 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2892 PetscFunctionReturn(0); 2893 } 2894 2895 #undef __FUNCT__ 2896 #define __FUNCT__ "DMPlexCreatePartition" 2897 /* 2898 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2899 2900 Collective on DM 2901 2902 Input Parameters: 2903 + dm - The DM 2904 . height - The height for points in the partition 2905 - enlarge - Expand each partition with neighbors 2906 2907 Output Parameters: 2908 + partSection - The PetscSection giving the division of points by partition 2909 . partition - The list of points by partition 2910 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2911 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2912 2913 Level: developer 2914 2915 .seealso DMPlexDistribute() 2916 */ 2917 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2918 { 2919 PetscMPIInt size; 2920 PetscErrorCode ierr; 2921 2922 PetscFunctionBegin; 2923 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2924 2925 *origPartSection = NULL; 2926 *origPartition = NULL; 2927 if (size == 1) { 2928 PetscInt *points; 2929 PetscInt cStart, cEnd, c; 2930 2931 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2932 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2933 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2934 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2935 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2936 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2937 for (c = cStart; c < cEnd; ++c) points[c] = c; 2938 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2939 PetscFunctionReturn(0); 2940 } 2941 if (height == 0) { 2942 PetscInt numVertices; 2943 PetscInt *start = NULL; 2944 PetscInt *adjacency = NULL; 2945 2946 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2947 if (1) { 2948 #if defined(PETSC_HAVE_CHACO) 2949 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2950 #endif 2951 } else { 2952 #if defined(PETSC_HAVE_PARMETIS) 2953 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2954 #endif 2955 } 2956 if (enlarge) { 2957 *origPartSection = *partSection; 2958 *origPartition = *partition; 2959 2960 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2961 } 2962 ierr = PetscFree(start);CHKERRQ(ierr); 2963 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2964 # if 0 2965 } else if (height == 1) { 2966 /* Build the dual graph for faces and partition the hypergraph */ 2967 PetscInt numEdges; 2968 2969 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2970 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2971 destroyCSR(numEdges, start, adjacency); 2972 #endif 2973 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2974 PetscFunctionReturn(0); 2975 } 2976 2977 #undef __FUNCT__ 2978 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2979 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2980 { 2981 /* const PetscInt height = 0; */ 2982 const PetscInt *partArray; 2983 PetscInt *allPoints, *partPoints = NULL; 2984 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2985 PetscErrorCode ierr; 2986 2987 PetscFunctionBegin; 2988 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2989 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2990 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2991 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2992 for (rank = rStart; rank < rEnd; ++rank) { 2993 PetscInt partSize = 0; 2994 PetscInt numPoints, offset, p; 2995 2996 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2997 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2998 for (p = 0; p < numPoints; ++p) { 2999 PetscInt point = partArray[offset+p], closureSize, c; 3000 PetscInt *closure = NULL; 3001 3002 /* TODO Include support for height > 0 case */ 3003 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3004 /* Merge into existing points */ 3005 if (partSize+closureSize > maxPartSize) { 3006 PetscInt *tmpPoints; 3007 3008 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 3009 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 3010 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3011 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3012 3013 partPoints = tmpPoints; 3014 } 3015 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3016 partSize += closureSize; 3017 3018 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3019 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3020 } 3021 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3022 } 3023 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3024 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3025 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3026 3027 for (rank = rStart; rank < rEnd; ++rank) { 3028 PetscInt partSize = 0, newOffset; 3029 PetscInt numPoints, offset, p; 3030 3031 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3032 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3033 for (p = 0; p < numPoints; ++p) { 3034 PetscInt point = partArray[offset+p], closureSize, c; 3035 PetscInt *closure = NULL; 3036 3037 /* TODO Include support for height > 0 case */ 3038 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3039 /* Merge into existing points */ 3040 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3041 partSize += closureSize; 3042 3043 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3044 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3045 } 3046 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3047 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3048 } 3049 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3050 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3051 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3052 PetscFunctionReturn(0); 3053 } 3054 3055 #undef __FUNCT__ 3056 #define __FUNCT__ "DMPlexDistributeField" 3057 /* 3058 Input Parameters: 3059 . originalSection 3060 , originalVec 3061 3062 Output Parameters: 3063 . newSection 3064 . newVec 3065 */ 3066 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3067 { 3068 PetscSF fieldSF; 3069 PetscInt *remoteOffsets, fieldSize; 3070 PetscScalar *originalValues, *newValues; 3071 PetscErrorCode ierr; 3072 3073 PetscFunctionBegin; 3074 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3075 3076 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3077 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3078 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3079 3080 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3081 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3082 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3083 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3084 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3085 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3086 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3087 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3088 PetscFunctionReturn(0); 3089 } 3090 3091 #undef __FUNCT__ 3092 #define __FUNCT__ "DMPlexDistribute" 3093 /*@C 3094 DMPlexDistribute - Distributes the mesh and any associated sections. 3095 3096 Not Collective 3097 3098 Input Parameter: 3099 + dm - The original DMPlex object 3100 . partitioner - The partitioning package, or NULL for the default 3101 - overlap - The overlap of partitions, 0 is the default 3102 3103 Output Parameter: 3104 . parallelMesh - The distributed DMPlex object, or NULL 3105 3106 Note: If the mesh was not distributed, the return value is NULL 3107 3108 Level: intermediate 3109 3110 .keywords: mesh, elements 3111 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3112 @*/ 3113 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3114 { 3115 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3116 MPI_Comm comm = ((PetscObject) dm)->comm; 3117 const PetscInt height = 0; 3118 PetscInt dim, numRemoteRanks; 3119 IS origCellPart, cellPart, part; 3120 PetscSection origCellPartSection, cellPartSection, partSection; 3121 PetscSFNode *remoteRanks; 3122 PetscSF partSF, pointSF, coneSF; 3123 ISLocalToGlobalMapping renumbering; 3124 PetscSection originalConeSection, newConeSection; 3125 PetscInt *remoteOffsets; 3126 PetscInt *cones, *newCones, newConesSize; 3127 PetscBool flg; 3128 PetscMPIInt rank, numProcs, p; 3129 PetscErrorCode ierr; 3130 3131 PetscFunctionBegin; 3132 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3133 PetscValidPointer(dmParallel,4); 3134 3135 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3136 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3137 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3138 3139 *dmParallel = NULL; 3140 if (numProcs == 1) PetscFunctionReturn(0); 3141 3142 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3143 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3144 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3145 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3146 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3147 if (!rank) numRemoteRanks = numProcs; 3148 else numRemoteRanks = 0; 3149 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3150 for (p = 0; p < numRemoteRanks; ++p) { 3151 remoteRanks[p].rank = p; 3152 remoteRanks[p].index = 0; 3153 } 3154 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3155 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3156 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3157 if (flg) { 3158 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3159 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3160 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3161 if (origCellPart) { 3162 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3163 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3164 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3165 } 3166 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3167 } 3168 /* Close the partition over the mesh */ 3169 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3170 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3171 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3172 /* Create new mesh */ 3173 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3174 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3175 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3176 pmesh = (DM_Plex*) (*dmParallel)->data; 3177 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3178 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3179 if (flg) { 3180 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3181 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3182 ierr = ISView(part, NULL);CHKERRQ(ierr); 3183 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3184 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3185 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3186 } 3187 /* Distribute cone section */ 3188 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3189 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3190 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3191 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3192 { 3193 PetscInt pStart, pEnd, p; 3194 3195 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3196 for (p = pStart; p < pEnd; ++p) { 3197 PetscInt coneSize; 3198 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3199 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3200 } 3201 } 3202 /* Communicate and renumber cones */ 3203 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3204 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3205 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3206 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3207 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3208 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3209 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3210 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3211 if (flg) { 3212 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3213 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3214 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3215 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3216 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3217 } 3218 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3219 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3220 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3221 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3222 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3223 /* Create supports and stratify sieve */ 3224 { 3225 PetscInt pStart, pEnd; 3226 3227 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3228 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3229 } 3230 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3231 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3232 /* Distribute Coordinates */ 3233 { 3234 PetscSection originalCoordSection, newCoordSection; 3235 Vec originalCoordinates, newCoordinates; 3236 const char *name; 3237 3238 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3239 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3240 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3241 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3242 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3243 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3244 3245 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3246 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3247 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3248 } 3249 /* Distribute labels */ 3250 { 3251 DMLabel next = mesh->labels, newNext = pmesh->labels; 3252 PetscInt numLabels = 0, l; 3253 3254 /* Bcast number of labels */ 3255 while (next) { 3256 ++numLabels; next = next->next; 3257 } 3258 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3259 next = mesh->labels; 3260 for (l = 0; l < numLabels; ++l) { 3261 DMLabel newLabel; 3262 const PetscInt *partArray; 3263 char *name; 3264 PetscInt *stratumSizes = NULL, *points = NULL; 3265 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3266 PetscInt nameSize, s, p; 3267 PetscBool isdepth; 3268 size_t len = 0; 3269 3270 /* Bcast name (could filter for no points) */ 3271 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3272 nameSize = len; 3273 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3274 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3275 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3276 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3277 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3278 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3279 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3280 newLabel->name = name; 3281 /* Bcast numStrata (could filter for no points in stratum) */ 3282 if (!rank) newLabel->numStrata = next->numStrata; 3283 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3284 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3285 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3286 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3287 /* Bcast stratumValues (could filter for no points in stratum) */ 3288 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3289 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3290 /* Find size on each process and Scatter */ 3291 if (!rank) { 3292 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3293 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3294 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3295 for (s = 0; s < next->numStrata; ++s) { 3296 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3297 const PetscInt point = next->points[p]; 3298 PetscInt proc; 3299 3300 for (proc = 0; proc < numProcs; ++proc) { 3301 PetscInt dof, off, pPart; 3302 3303 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3304 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3305 for (pPart = off; pPart < off+dof; ++pPart) { 3306 if (partArray[pPart] == point) { 3307 ++stratumSizes[proc*next->numStrata+s]; 3308 break; 3309 } 3310 } 3311 } 3312 } 3313 } 3314 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3315 } 3316 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3317 /* Calculate stratumOffsets */ 3318 newLabel->stratumOffsets[0] = 0; 3319 for (s = 0; s < newLabel->numStrata; ++s) { 3320 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3321 } 3322 /* Pack points and Scatter */ 3323 if (!rank) { 3324 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3325 displs[0] = 0; 3326 for (p = 0; p < numProcs; ++p) { 3327 sendcnts[p] = 0; 3328 for (s = 0; s < next->numStrata; ++s) { 3329 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3330 } 3331 offsets[p] = displs[p]; 3332 displs[p+1] = displs[p] + sendcnts[p]; 3333 } 3334 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3335 for (s = 0; s < next->numStrata; ++s) { 3336 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3337 const PetscInt point = next->points[p]; 3338 PetscInt proc; 3339 3340 for (proc = 0; proc < numProcs; ++proc) { 3341 PetscInt dof, off, pPart; 3342 3343 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3344 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3345 for (pPart = off; pPart < off+dof; ++pPart) { 3346 if (partArray[pPart] == point) { 3347 points[offsets[proc]++] = point; 3348 break; 3349 } 3350 } 3351 } 3352 } 3353 } 3354 } 3355 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3356 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3357 ierr = PetscFree(points);CHKERRQ(ierr); 3358 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3359 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3360 /* Renumber points */ 3361 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3362 /* Sort points */ 3363 for (s = 0; s < newLabel->numStrata; ++s) { 3364 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3365 } 3366 /* Insert into list */ 3367 if (newNext) newNext->next = newLabel; 3368 else pmesh->labels = newLabel; 3369 newNext = newLabel; 3370 if (!rank) next = next->next; 3371 } 3372 } 3373 /* Cleanup Partition */ 3374 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3375 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3376 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3377 ierr = ISDestroy(&part);CHKERRQ(ierr); 3378 /* Create point SF for parallel mesh */ 3379 { 3380 const PetscInt *leaves; 3381 PetscSFNode *remotePoints, *rowners, *lowners; 3382 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3383 PetscInt pStart, pEnd; 3384 3385 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3386 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3387 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3388 for (p=0; p<numRoots; p++) { 3389 rowners[p].rank = -1; 3390 rowners[p].index = -1; 3391 } 3392 if (origCellPart) { 3393 /* Make sure cells in the original partition are not assigned to other procs */ 3394 const PetscInt *origCells; 3395 3396 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3397 for (p = 0; p < numProcs; ++p) { 3398 PetscInt dof, off, d; 3399 3400 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3401 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3402 for (d = off; d < off+dof; ++d) { 3403 rowners[origCells[d]].rank = p; 3404 } 3405 } 3406 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3407 } 3408 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3409 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3410 3411 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3412 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3413 for (p = 0; p < numLeaves; ++p) { 3414 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3415 lowners[p].rank = rank; 3416 lowners[p].index = leaves ? leaves[p] : p; 3417 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3418 lowners[p].rank = -2; 3419 lowners[p].index = -2; 3420 } 3421 } 3422 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3423 rowners[p].rank = -3; 3424 rowners[p].index = -3; 3425 } 3426 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3427 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3428 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3429 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3430 for (p = 0; p < numLeaves; ++p) { 3431 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3432 if (lowners[p].rank != rank) ++numGhostPoints; 3433 } 3434 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3435 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3436 for (p = 0, gp = 0; p < numLeaves; ++p) { 3437 if (lowners[p].rank != rank) { 3438 ghostPoints[gp] = leaves ? leaves[p] : p; 3439 remotePoints[gp].rank = lowners[p].rank; 3440 remotePoints[gp].index = lowners[p].index; 3441 ++gp; 3442 } 3443 } 3444 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3445 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3446 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3447 } 3448 /* Cleanup */ 3449 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3450 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3451 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3452 PetscFunctionReturn(0); 3453 } 3454 3455 #undef __FUNCT__ 3456 #define __FUNCT__ "DMPlexRenumber_Private" 3457 /* 3458 Reasons to renumber: 3459 3460 1) Permute points, e.g. bandwidth reduction (Renumber) 3461 3462 a) Must not mix strata 3463 3464 2) Shift numbers for point insertion (Shift) 3465 3466 a) Want operation brken into parts so that insertion can be interleaved 3467 3468 renumbering - An IS which provides the new numbering 3469 */ 3470 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3471 { 3472 PetscFunctionBegin; 3473 PetscFunctionReturn(0); 3474 } 3475 3476 #undef __FUNCT__ 3477 #define __FUNCT__ "DMPlexShiftPoint_Private" 3478 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3479 { 3480 if (depth < 0) return p; 3481 /* Cells */ if (p < depthEnd[depth]) return p; 3482 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3483 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3484 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3485 } 3486 3487 #undef __FUNCT__ 3488 #define __FUNCT__ "DMPlexShiftSizes_Private" 3489 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3490 { 3491 PetscInt *depthEnd; 3492 PetscInt depth = 0, d, pStart, pEnd, p; 3493 PetscErrorCode ierr; 3494 3495 PetscFunctionBegin; 3496 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3497 if (depth < 0) PetscFunctionReturn(0); 3498 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3499 /* Step 1: Expand chart */ 3500 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3501 for (d = 0; d <= depth; ++d) { 3502 pEnd += depthShift[d]; 3503 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3504 } 3505 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3506 /* Step 2: Set cone and support sizes */ 3507 for (d = 0; d <= depth; ++d) { 3508 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3509 for (p = pStart; p < pEnd; ++p) { 3510 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3511 PetscInt size; 3512 3513 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3514 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3515 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3516 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3517 } 3518 } 3519 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3520 PetscFunctionReturn(0); 3521 } 3522 3523 #undef __FUNCT__ 3524 #define __FUNCT__ "DMPlexShiftPoints_Private" 3525 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3526 { 3527 PetscInt *depthEnd, *newpoints; 3528 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3529 PetscErrorCode ierr; 3530 3531 PetscFunctionBegin; 3532 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3533 if (depth < 0) PetscFunctionReturn(0); 3534 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3535 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3536 for (d = 0; d <= depth; ++d) { 3537 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3538 } 3539 /* Step 5: Set cones and supports */ 3540 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3541 for (p = pStart; p < pEnd; ++p) { 3542 const PetscInt *points = NULL, *orientations = NULL; 3543 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3544 3545 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3546 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3547 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3548 for (i = 0; i < size; ++i) { 3549 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3550 } 3551 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3552 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3553 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3554 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3555 for (i = 0; i < size; ++i) { 3556 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3557 } 3558 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3559 } 3560 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3561 PetscFunctionReturn(0); 3562 } 3563 3564 #undef __FUNCT__ 3565 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3566 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3567 { 3568 PetscSection coordSection, newCoordSection; 3569 Vec coordinates, newCoordinates; 3570 PetscScalar *coords, *newCoords; 3571 PetscInt *depthEnd, coordSize; 3572 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3573 PetscErrorCode ierr; 3574 3575 PetscFunctionBegin; 3576 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3577 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3578 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3579 for (d = 0; d <= depth; ++d) { 3580 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3581 } 3582 /* Step 8: Convert coordinates */ 3583 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3584 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3585 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3586 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3587 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3588 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3589 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3590 for (v = vStartNew; v < vEndNew; ++v) { 3591 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3592 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3593 } 3594 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3595 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3596 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3597 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3598 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3599 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3600 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3601 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3602 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3603 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3604 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3605 for (v = vStart; v < vEnd; ++v) { 3606 PetscInt dof, off, noff, d; 3607 3608 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3609 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3610 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3611 for (d = 0; d < dof; ++d) { 3612 newCoords[noff+d] = coords[off+d]; 3613 } 3614 } 3615 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3616 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3617 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3618 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3619 PetscFunctionReturn(0); 3620 } 3621 3622 #undef __FUNCT__ 3623 #define __FUNCT__ "DMPlexShiftSF_Private" 3624 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3625 { 3626 PetscInt *depthEnd; 3627 PetscInt depth = 0, d; 3628 PetscSF sfPoint, sfPointNew; 3629 const PetscSFNode *remotePoints; 3630 PetscSFNode *gremotePoints; 3631 const PetscInt *localPoints; 3632 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3633 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3634 PetscMPIInt numProcs; 3635 PetscErrorCode ierr; 3636 3637 PetscFunctionBegin; 3638 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3639 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3640 for (d = 0; d <= depth; ++d) { 3641 totShift += depthShift[d]; 3642 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3643 } 3644 /* Step 9: Convert pointSF */ 3645 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3646 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3647 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3648 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3649 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3650 if (numRoots >= 0) { 3651 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3652 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3653 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3654 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3655 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3656 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3657 for (l = 0; l < numLeaves; ++l) { 3658 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3659 gremotePoints[l].rank = remotePoints[l].rank; 3660 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3661 } 3662 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3663 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3664 } 3665 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3666 PetscFunctionReturn(0); 3667 } 3668 3669 #undef __FUNCT__ 3670 #define __FUNCT__ "DMPlexShiftLabels_Private" 3671 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3672 { 3673 PetscSF sfPoint; 3674 DMLabel vtkLabel, ghostLabel; 3675 PetscInt *depthEnd; 3676 const PetscSFNode *leafRemote; 3677 const PetscInt *leafLocal; 3678 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3679 PetscMPIInt rank; 3680 PetscErrorCode ierr; 3681 3682 PetscFunctionBegin; 3683 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3684 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3685 for (d = 0; d <= depth; ++d) { 3686 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3687 } 3688 /* Step 10: Convert labels */ 3689 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3690 for (l = 0; l < numLabels; ++l) { 3691 DMLabel label, newlabel; 3692 const char *lname; 3693 PetscBool isDepth; 3694 IS valueIS; 3695 const PetscInt *values; 3696 PetscInt numValues, val; 3697 3698 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3699 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3700 if (isDepth) continue; 3701 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3702 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3703 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3704 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3705 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3706 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3707 for (val = 0; val < numValues; ++val) { 3708 IS pointIS; 3709 const PetscInt *points; 3710 PetscInt numPoints, p; 3711 3712 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3713 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3714 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3715 for (p = 0; p < numPoints; ++p) { 3716 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3717 3718 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3719 } 3720 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3721 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3722 } 3723 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3724 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3725 } 3726 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3727 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3728 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3729 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3730 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3731 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3732 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3733 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3734 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3735 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3736 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3737 for (; c < leafLocal[l] && c < cEnd; ++c) { 3738 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3739 } 3740 if (leafLocal[l] >= cEnd) break; 3741 if (leafRemote[l].rank == rank) { 3742 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3743 } else { 3744 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3745 } 3746 } 3747 for (; c < cEnd; ++c) { 3748 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3749 } 3750 if (0) { 3751 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3752 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3753 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3754 } 3755 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3756 for (f = fStart; f < fEnd; ++f) { 3757 PetscInt numCells; 3758 3759 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3760 if (numCells < 2) { 3761 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3762 } else { 3763 const PetscInt *cells = NULL; 3764 PetscInt vA, vB; 3765 3766 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3767 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3768 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3769 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3770 } 3771 } 3772 if (0) { 3773 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3774 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3775 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3776 } 3777 PetscFunctionReturn(0); 3778 } 3779 3780 #undef __FUNCT__ 3781 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3782 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3783 { 3784 DMLabel label; 3785 IS valueIS; 3786 const PetscInt *values; 3787 PetscInt *depthShift; 3788 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3789 PetscErrorCode ierr; 3790 3791 PetscFunctionBegin; 3792 /* Count ghost cells */ 3793 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3794 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3795 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3796 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3797 3798 *numGhostCells = 0; 3799 for (fs = 0; fs < numFS; ++fs) { 3800 PetscInt numBdFaces; 3801 3802 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3803 3804 *numGhostCells += numBdFaces; 3805 } 3806 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3807 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3808 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3809 if (depth >= 0) depthShift[depth] = *numGhostCells; 3810 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3811 /* Step 3: Set cone/support sizes for new points */ 3812 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3813 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3814 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3815 } 3816 for (fs = 0; fs < numFS; ++fs) { 3817 IS faceIS; 3818 const PetscInt *faces; 3819 PetscInt numFaces, f; 3820 3821 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3822 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3823 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3824 for (f = 0; f < numFaces; ++f) { 3825 PetscInt size; 3826 3827 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3828 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3829 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3830 } 3831 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3832 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3833 } 3834 /* Step 4: Setup ghosted DM */ 3835 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3836 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3837 /* Step 6: Set cones and supports for new points */ 3838 ghostCell = cEnd; 3839 for (fs = 0; fs < numFS; ++fs) { 3840 IS faceIS; 3841 const PetscInt *faces; 3842 PetscInt numFaces, f; 3843 3844 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3845 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3846 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3847 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3848 PetscInt newFace = faces[f] + *numGhostCells; 3849 3850 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3851 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3852 } 3853 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3854 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3855 } 3856 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3857 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3858 /* Step 7: Stratify */ 3859 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3860 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3861 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3862 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3863 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3864 PetscFunctionReturn(0); 3865 } 3866 3867 #undef __FUNCT__ 3868 #define __FUNCT__ "DMPlexConstructGhostCells" 3869 /*@C 3870 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3871 3872 Collective on dm 3873 3874 Input Parameters: 3875 + dm - The original DM 3876 - labelName - The label specifying the boundary faces (this could be auto-generated) 3877 3878 Output Parameters: 3879 + numGhostCells - The number of ghost cells added to the DM 3880 - dmGhosted - The new DM 3881 3882 Level: developer 3883 3884 .seealso: DMCreate() 3885 */ 3886 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3887 { 3888 DM gdm; 3889 PetscInt dim; 3890 PetscErrorCode ierr; 3891 3892 PetscFunctionBegin; 3893 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3894 PetscValidPointer(numGhostCells, 3); 3895 PetscValidPointer(dmGhosted, 4); 3896 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3897 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3898 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3899 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3900 switch (dim) { 3901 case 2: 3902 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3903 break; 3904 default: 3905 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3906 } 3907 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3908 *dmGhosted = gdm; 3909 PetscFunctionReturn(0); 3910 } 3911 3912 #undef __FUNCT__ 3913 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3914 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3915 { 3916 MPI_Comm comm = ((PetscObject) dm)->comm; 3917 IS valueIS, *pointIS; 3918 const PetscInt *values, **splitPoints; 3919 PetscSection coordSection; 3920 Vec coordinates; 3921 PetscScalar *coords; 3922 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3923 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3924 PetscErrorCode ierr; 3925 3926 PetscFunctionBegin; 3927 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3928 /* Count split points and add cohesive cells */ 3929 if (label) { 3930 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3931 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3932 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3933 } 3934 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3935 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3936 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3937 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3938 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3939 for (d = 0; d <= depth; ++d) { 3940 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3941 numSplitPoints[d] = 0; 3942 splitPoints[d] = NULL; 3943 pointIS[d] = NULL; 3944 } 3945 for (sp = 0; sp < numSP; ++sp) { 3946 const PetscInt dep = values[sp]; 3947 3948 if ((dep < 0) || (dep > depth)) continue; 3949 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3950 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3951 if (pointIS[dep]) { 3952 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3953 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3954 } 3955 } 3956 if (depth >= 0) { 3957 /* Calculate number of additional points */ 3958 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3959 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3960 /* Calculate hybrid bound for each dimension */ 3961 pMaxNew[0] += depthShift[depth]; 3962 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3963 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3964 3965 /* Calculate point offset for each dimension */ 3966 depthOffset[depth] = 0; 3967 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3968 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3969 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3970 } 3971 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3972 /* Step 3: Set cone/support sizes for new points */ 3973 for (dep = 0; dep <= depth; ++dep) { 3974 for (p = 0; p < numSplitPoints[dep]; ++p) { 3975 const PetscInt oldp = splitPoints[dep][p]; 3976 const PetscInt newp = depthOffset[dep] + oldp; 3977 const PetscInt splitp = pMaxNew[dep] + p; 3978 const PetscInt *support; 3979 PetscInt coneSize, supportSize, q, e; 3980 3981 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3982 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3983 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3984 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3985 if (dep == depth-1) { 3986 const PetscInt ccell = pMaxNew[depth] + p; 3987 /* Add cohesive cells, they are prisms */ 3988 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3989 } else if (dep == 0) { 3990 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3991 3992 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3993 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3994 for (e = 0, q = 0; e < supportSize; ++e) { 3995 PetscInt val; 3996 3997 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3998 if ((val == 1) || (val == (shift + 1))) ++q; 3999 } 4000 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 4001 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4002 for (e = 0, q = 0; e < supportSize; ++e) { 4003 PetscInt val; 4004 4005 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4006 if ((val == 1) || (val == -(shift + 1))) ++q; 4007 } 4008 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 4009 /* Add cohesive edges */ 4010 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 4011 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4012 } else if (dep == dim-2) { 4013 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4014 /* Split old edge: Faces in positive side cells and old split faces */ 4015 for (e = 0, q = 0; e < supportSize; ++e) { 4016 PetscInt val; 4017 4018 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4019 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4020 } 4021 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4022 /* Split new edge: Faces in negative side cells and new split faces */ 4023 for (e = 0, q = 0; e < supportSize; ++e) { 4024 PetscInt val; 4025 4026 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4027 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4028 } 4029 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4030 } 4031 } 4032 } 4033 /* Step 4: Setup split DM */ 4034 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4035 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4036 /* Step 6: Set cones and supports for new points */ 4037 for (dep = 0; dep <= depth; ++dep) { 4038 for (p = 0; p < numSplitPoints[dep]; ++p) { 4039 const PetscInt oldp = splitPoints[dep][p]; 4040 const PetscInt newp = depthOffset[dep] + oldp; 4041 const PetscInt splitp = pMaxNew[dep] + p; 4042 const PetscInt *cone, *support, *ornt; 4043 PetscInt coneSize, supportSize, q, v, e, s; 4044 4045 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4046 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4047 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4048 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4049 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4050 if (dep == depth-1) { 4051 const PetscInt ccell = pMaxNew[depth] + p; 4052 const PetscInt *supportF; 4053 4054 /* Split face: copy in old face to new face to start */ 4055 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4056 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4057 /* Split old face: old vertices/edges in cone so no change */ 4058 /* Split new face: new vertices/edges in cone */ 4059 for (q = 0; q < coneSize; ++q) { 4060 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4061 4062 coneNew[2+q] = pMaxNew[dim-2] + v; 4063 } 4064 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4065 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4066 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4067 coneNew[0] = newp; 4068 coneNew[1] = splitp; 4069 for (q = 0; q < coneSize; ++q) { 4070 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4071 } 4072 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4073 4074 4075 for (s = 0; s < supportSize; ++s) { 4076 PetscInt val; 4077 4078 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4079 if (val < 0) { 4080 /* Split old face: Replace negative side cell with cohesive cell */ 4081 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4082 } else { 4083 /* Split new face: Replace positive side cell with cohesive cell */ 4084 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4085 } 4086 } 4087 } else if (dep == 0) { 4088 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4089 4090 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4091 for (e = 0, q = 0; e < supportSize; ++e) { 4092 PetscInt val; 4093 4094 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4095 if ((val == 1) || (val == (shift + 1))) { 4096 supportNew[q++] = depthOffset[1] + support[e]; 4097 } 4098 } 4099 supportNew[q] = cedge; 4100 4101 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4102 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4103 for (e = 0, q = 0; e < supportSize; ++e) { 4104 PetscInt val, edge; 4105 4106 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4107 if (val == 1) { 4108 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4109 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4110 supportNew[q++] = pMaxNew[1] + edge; 4111 } else if (val == -(shift + 1)) { 4112 supportNew[q++] = depthOffset[1] + support[e]; 4113 } 4114 } 4115 supportNew[q] = cedge; 4116 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4117 /* Cohesive edge: Old and new split vertex, punting on support */ 4118 coneNew[0] = newp; 4119 coneNew[1] = splitp; 4120 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4121 } else if (dep == dim-2) { 4122 /* Split old edge: old vertices in cone so no change */ 4123 /* Split new edge: new vertices in cone */ 4124 for (q = 0; q < coneSize; ++q) { 4125 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4126 4127 coneNew[q] = pMaxNew[dim-3] + v; 4128 } 4129 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4130 /* Split old edge: Faces in positive side cells and old split faces */ 4131 for (e = 0, q = 0; e < supportSize; ++e) { 4132 PetscInt val; 4133 4134 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4135 if ((val == dim-1) || (val == (shift + dim-1))) { 4136 supportNew[q++] = depthOffset[dim-1] + support[e]; 4137 } 4138 } 4139 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4140 /* Split new edge: Faces in negative side cells and new split faces */ 4141 for (e = 0, q = 0; e < supportSize; ++e) { 4142 PetscInt val, face; 4143 4144 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4145 if (val == dim-1) { 4146 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4147 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4148 supportNew[q++] = pMaxNew[dim-1] + face; 4149 } else if (val == -(shift + dim-1)) { 4150 supportNew[q++] = depthOffset[dim-1] + support[e]; 4151 } 4152 } 4153 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4154 } 4155 } 4156 } 4157 /* Step 6b: Replace split points in negative side cones */ 4158 for (sp = 0; sp < numSP; ++sp) { 4159 PetscInt dep = values[sp]; 4160 IS pIS; 4161 PetscInt numPoints; 4162 const PetscInt *points; 4163 4164 if (dep >= 0) continue; 4165 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4166 if (!pIS) continue; 4167 dep = -dep - shift; 4168 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4169 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4170 for (p = 0; p < numPoints; ++p) { 4171 const PetscInt oldp = points[p]; 4172 const PetscInt newp = depthOffset[dep] + oldp; 4173 const PetscInt *cone; 4174 PetscInt coneSize, c; 4175 PetscBool replaced = PETSC_FALSE; 4176 4177 /* Negative edge: replace split vertex */ 4178 /* Negative cell: replace split face */ 4179 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4180 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4181 for (c = 0; c < coneSize; ++c) { 4182 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4183 PetscInt csplitp, cp, val; 4184 4185 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4186 if (val == dep-1) { 4187 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4188 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4189 csplitp = pMaxNew[dep-1] + cp; 4190 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4191 replaced = PETSC_TRUE; 4192 } 4193 } 4194 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4195 } 4196 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4197 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4198 } 4199 /* Step 7: Stratify */ 4200 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4201 /* Step 8: Coordinates */ 4202 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4203 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4204 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4205 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4206 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4207 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4208 const PetscInt splitp = pMaxNew[0] + v; 4209 PetscInt dof, off, soff, d; 4210 4211 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4212 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4213 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4214 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4215 } 4216 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4217 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4218 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4219 /* Step 10: Labels */ 4220 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4221 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4222 for (dep = 0; dep <= depth; ++dep) { 4223 for (p = 0; p < numSplitPoints[dep]; ++p) { 4224 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4225 const PetscInt splitp = pMaxNew[dep] + p; 4226 PetscInt l; 4227 4228 for (l = 0; l < numLabels; ++l) { 4229 DMLabel mlabel; 4230 const char *lname; 4231 PetscInt val; 4232 4233 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4234 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4235 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4236 if (val >= 0) { 4237 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4238 if (dep == 0) { 4239 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4240 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4241 } 4242 } 4243 } 4244 } 4245 } 4246 for (sp = 0; sp < numSP; ++sp) { 4247 const PetscInt dep = values[sp]; 4248 4249 if ((dep < 0) || (dep > depth)) continue; 4250 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4251 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4252 } 4253 if (label) { 4254 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4255 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4256 } 4257 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4258 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4259 PetscFunctionReturn(0); 4260 } 4261 4262 #undef __FUNCT__ 4263 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4264 /*@C 4265 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4266 4267 Collective on dm 4268 4269 Input Parameters: 4270 + dm - The original DM 4271 - labelName - The label specifying the boundary faces (this could be auto-generated) 4272 4273 Output Parameters: 4274 - dmSplit - The new DM 4275 4276 Level: developer 4277 4278 .seealso: DMCreate() 4279 */ 4280 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4281 { 4282 DM sdm; 4283 PetscInt dim; 4284 PetscErrorCode ierr; 4285 4286 PetscFunctionBegin; 4287 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4288 PetscValidPointer(dmSplit, 4); 4289 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4290 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4291 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4292 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4293 switch (dim) { 4294 case 2: 4295 case 3: 4296 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4297 break; 4298 default: 4299 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4300 } 4301 *dmSplit = sdm; 4302 PetscFunctionReturn(0); 4303 } 4304 4305 #undef __FUNCT__ 4306 #define __FUNCT__ "DMLabelCohesiveComplete" 4307 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4308 { 4309 IS dimIS; 4310 const PetscInt *points; 4311 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4312 PetscErrorCode ierr; 4313 4314 PetscFunctionBegin; 4315 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4316 /* Cell orientation for face gives the side of the fault */ 4317 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4318 if (!dimIS) PetscFunctionReturn(0); 4319 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4320 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4321 for (p = 0; p < numPoints; ++p) { 4322 const PetscInt *support; 4323 PetscInt supportSize, s; 4324 4325 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4326 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4327 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4328 for (s = 0; s < supportSize; ++s) { 4329 const PetscInt *cone, *ornt; 4330 PetscInt coneSize, c; 4331 PetscBool pos = PETSC_TRUE; 4332 4333 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4334 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4335 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4336 for (c = 0; c < coneSize; ++c) { 4337 if (cone[c] == points[p]) { 4338 if (ornt[c] >= 0) { 4339 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4340 } else { 4341 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4342 pos = PETSC_FALSE; 4343 } 4344 break; 4345 } 4346 } 4347 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]); 4348 /* Put faces touching the fault in the label */ 4349 for (c = 0; c < coneSize; ++c) { 4350 const PetscInt point = cone[c]; 4351 4352 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4353 if (val == -1) { 4354 PetscInt *closure = NULL; 4355 PetscInt closureSize, cl; 4356 4357 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4358 for (cl = 0; cl < closureSize*2; cl += 2) { 4359 const PetscInt clp = closure[cl]; 4360 4361 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4362 if ((val >= 0) && (val < dim-1)) { 4363 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4364 break; 4365 } 4366 } 4367 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4368 } 4369 } 4370 } 4371 } 4372 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4373 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4374 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4375 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4376 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4377 if (!dimIS) PetscFunctionReturn(0); 4378 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4379 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4380 for (p = 0; p < numPoints; ++p) { 4381 PetscInt *star = NULL; 4382 PetscInt starSize, s; 4383 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4384 4385 /* First mark cells connected to the fault */ 4386 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4387 while (again) { 4388 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4389 again = 0; 4390 for (s = 0; s < starSize*2; s += 2) { 4391 const PetscInt point = star[s]; 4392 const PetscInt *cone; 4393 PetscInt coneSize, c; 4394 4395 if ((point < cStart) || (point >= cEnd)) continue; 4396 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4397 if (val != -1) continue; 4398 again = 2; 4399 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4400 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4401 for (c = 0; c < coneSize; ++c) { 4402 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4403 if (val != -1) { 4404 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); 4405 if (val > 0) { 4406 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4407 } else { 4408 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4409 } 4410 again = 1; 4411 break; 4412 } 4413 } 4414 } 4415 } 4416 /* Classify the rest by cell membership */ 4417 for (s = 0; s < starSize*2; s += 2) { 4418 const PetscInt point = star[s]; 4419 4420 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4421 if (val == -1) { 4422 PetscInt *sstar = NULL; 4423 PetscInt sstarSize, ss; 4424 PetscBool marked = PETSC_FALSE; 4425 4426 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4427 for (ss = 0; ss < sstarSize*2; ss += 2) { 4428 const PetscInt spoint = sstar[ss]; 4429 4430 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4431 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4432 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4433 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4434 if (val > 0) { 4435 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4436 } else { 4437 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4438 } 4439 marked = PETSC_TRUE; 4440 break; 4441 } 4442 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4443 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4444 } 4445 } 4446 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4447 } 4448 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4449 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4450 PetscFunctionReturn(0); 4451 } 4452 4453 #undef __FUNCT__ 4454 #define __FUNCT__ "DMPlexInterpolate_2D" 4455 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4456 { 4457 DM idm; 4458 DM_Plex *mesh; 4459 PetscHashIJ edgeTable; 4460 PetscInt *off; 4461 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4462 PetscInt numEdges, firstEdge, edge, e; 4463 PetscErrorCode ierr; 4464 4465 PetscFunctionBegin; 4466 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4467 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4468 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4469 numCells = cEnd - cStart; 4470 numVertices = vEnd - vStart; 4471 firstEdge = numCells + numVertices; 4472 numEdges = 0; 4473 /* Count edges using algorithm from CreateNeighborCSR */ 4474 ierr = DMPlexCreateNeighborCSR(dm, NULL, &off, NULL);CHKERRQ(ierr); 4475 if (off) { 4476 PetscInt numCorners = 0; 4477 4478 numEdges = off[numCells]/2; 4479 #if 0 4480 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4481 numEdges += 3*numCells - off[numCells]; 4482 #else 4483 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4484 for (c = cStart; c < cEnd; ++c) { 4485 PetscInt coneSize; 4486 4487 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4488 numCorners += coneSize; 4489 } 4490 numEdges += numCorners - off[numCells]; 4491 #endif 4492 } 4493 #if 0 4494 /* Check Euler characteristic V - E + F = 1 */ 4495 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4496 #endif 4497 /* Create interpolated mesh */ 4498 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4499 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4500 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4501 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4502 for (c = 0; c < numCells; ++c) { 4503 PetscInt numCorners; 4504 4505 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4506 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4507 } 4508 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4509 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4510 } 4511 ierr = DMSetUp(idm);CHKERRQ(ierr); 4512 /* Get edge cones from subsets of cell vertices */ 4513 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4514 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4515 4516 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4517 const PetscInt *cellFaces; 4518 PetscInt numCellFaces, faceSize, cf; 4519 4520 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4521 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4522 for (cf = 0; cf < numCellFaces; ++cf) { 4523 #if 1 4524 PetscHashIJKey key; 4525 4526 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4527 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4528 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4529 if (e < 0) { 4530 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4531 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4532 e = edge++; 4533 } 4534 #else 4535 PetscBool found = PETSC_FALSE; 4536 4537 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4538 for (e = firstEdge; e < edge; ++e) { 4539 const PetscInt *cone; 4540 4541 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4542 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4543 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4544 found = PETSC_TRUE; 4545 break; 4546 } 4547 } 4548 if (!found) { 4549 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4550 ++edge; 4551 } 4552 #endif 4553 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4554 } 4555 } 4556 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4557 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4558 ierr = PetscFree(off);CHKERRQ(ierr); 4559 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4560 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4561 mesh = (DM_Plex*) (idm)->data; 4562 /* Orient edges */ 4563 for (c = 0; c < numCells; ++c) { 4564 const PetscInt *cone = NULL, *cellFaces; 4565 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4566 4567 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4568 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4569 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4570 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4571 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4572 for (cf = 0; cf < numCellFaces; ++cf) { 4573 const PetscInt *econe = NULL; 4574 PetscInt esize; 4575 4576 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4577 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4578 if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4579 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4580 /* Correctly oriented */ 4581 mesh->coneOrientations[coff+cf] = 0; 4582 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4583 /* Start at index 1, and reverse orientation */ 4584 mesh->coneOrientations[coff+cf] = -(1+1); 4585 } 4586 } 4587 } 4588 *dmInt = idm; 4589 PetscFunctionReturn(0); 4590 } 4591 4592 #undef __FUNCT__ 4593 #define __FUNCT__ "DMPlexInterpolate_3D" 4594 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4595 { 4596 DM idm, fdm; 4597 DM_Plex *mesh; 4598 PetscInt *off; 4599 const PetscInt numCorners = 4; 4600 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4601 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4602 PetscErrorCode ierr; 4603 4604 PetscFunctionBegin; 4605 { 4606 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4607 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4608 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4609 } 4610 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4611 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4612 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4613 numCells = cEnd - cStart; 4614 numVertices = vEnd - vStart; 4615 firstFace = numCells + numVertices; 4616 numFaces = 0; 4617 /* Count faces using algorithm from CreateNeighborCSR */ 4618 ierr = DMPlexCreateNeighborCSR(dm, NULL, &off, NULL);CHKERRQ(ierr); 4619 if (off) { 4620 numFaces = off[numCells]/2; 4621 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4622 numFaces += 4*numCells - off[numCells]; 4623 } 4624 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4625 firstEdge = firstFace + numFaces; 4626 numEdges = numVertices + numFaces - numCells - 1; 4627 /* Create interpolated mesh */ 4628 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4629 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4630 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4631 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4632 for (c = 0; c < numCells; ++c) { 4633 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4634 } 4635 for (f = firstFace; f < firstFace+numFaces; ++f) { 4636 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4637 } 4638 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4639 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4640 } 4641 ierr = DMSetUp(idm);CHKERRQ(ierr); 4642 /* Get face cones from subsets of cell vertices */ 4643 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4644 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4645 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4646 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4647 for (f = firstFace; f < firstFace+numFaces; ++f) { 4648 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4649 } 4650 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4651 for (c = 0, face = firstFace; c < numCells; ++c) { 4652 const PetscInt *cellFaces; 4653 PetscInt numCellFaces, faceSize, cf; 4654 4655 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4656 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4657 for (cf = 0; cf < numCellFaces; ++cf) { 4658 PetscBool found = PETSC_FALSE; 4659 4660 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4661 for (f = firstFace; f < face; ++f) { 4662 const PetscInt *cone = NULL; 4663 4664 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4665 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4666 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4667 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4668 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4669 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4670 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4671 found = PETSC_TRUE; 4672 break; 4673 } 4674 } 4675 if (!found) { 4676 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4677 /* Save the vertices for orientation calculation */ 4678 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4679 ++face; 4680 } 4681 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4682 } 4683 } 4684 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4685 /* Get edge cones from subsets of face vertices */ 4686 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4687 const PetscInt *cellFaces; 4688 PetscInt numCellFaces, faceSize, cf; 4689 4690 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4691 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4692 for (cf = 0; cf < numCellFaces; ++cf) { 4693 PetscBool found = PETSC_FALSE; 4694 4695 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4696 for (e = firstEdge; e < edge; ++e) { 4697 const PetscInt *cone = NULL; 4698 4699 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4700 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4701 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4702 found = PETSC_TRUE; 4703 break; 4704 } 4705 } 4706 if (!found) { 4707 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4708 ++edge; 4709 } 4710 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4711 } 4712 } 4713 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4714 ierr = PetscFree(off);CHKERRQ(ierr); 4715 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4716 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4717 mesh = (DM_Plex*) (idm)->data; 4718 /* Orient edges */ 4719 for (f = firstFace; f < firstFace+numFaces; ++f) { 4720 const PetscInt *cone, *cellFaces; 4721 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4722 4723 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4724 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4725 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4726 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4727 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4728 for (cf = 0; cf < numCellFaces; ++cf) { 4729 const PetscInt *econe; 4730 PetscInt esize; 4731 4732 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4733 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4734 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]); 4735 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4736 /* Correctly oriented */ 4737 mesh->coneOrientations[coff+cf] = 0; 4738 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4739 /* Start at index 1, and reverse orientation */ 4740 mesh->coneOrientations[coff+cf] = -(1+1); 4741 } 4742 } 4743 } 4744 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4745 /* Orient faces */ 4746 for (c = 0; c < numCells; ++c) { 4747 const PetscInt *cone, *cellFaces; 4748 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4749 4750 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4751 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4752 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4753 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4754 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4755 for (cf = 0; cf < numCellFaces; ++cf) { 4756 PetscInt *origClosure = NULL, *closure; 4757 PetscInt closureSize, i; 4758 4759 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4760 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4761 for (i = 4; i < 7; ++i) { 4762 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); 4763 } 4764 closure = &origClosure[4*2]; 4765 /* Remember that this is the orientation for edges, not vertices */ 4766 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4767 /* Correctly oriented */ 4768 mesh->coneOrientations[coff+cf] = 0; 4769 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4770 /* Shifted by 1 */ 4771 mesh->coneOrientations[coff+cf] = 1; 4772 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4773 /* Shifted by 2 */ 4774 mesh->coneOrientations[coff+cf] = 2; 4775 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4776 /* Start at edge 1, and reverse orientation */ 4777 mesh->coneOrientations[coff+cf] = -(1+1); 4778 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4779 /* Start at index 0, and reverse orientation */ 4780 mesh->coneOrientations[coff+cf] = -(0+1); 4781 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4782 /* Start at index 2, and reverse orientation */ 4783 mesh->coneOrientations[coff+cf] = -(2+1); 4784 } 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); 4785 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4786 } 4787 } 4788 { 4789 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4790 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4791 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4792 } 4793 *dmInt = idm; 4794 PetscFunctionReturn(0); 4795 } 4796 4797 #undef __FUNCT__ 4798 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4799 /* 4800 This takes as input the common mesh generator output, a list of the vertices for each cell 4801 */ 4802 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4803 { 4804 PetscInt *cone, c, p; 4805 PetscErrorCode ierr; 4806 4807 PetscFunctionBegin; 4808 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4809 for (c = 0; c < numCells; ++c) { 4810 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4811 } 4812 ierr = DMSetUp(dm);CHKERRQ(ierr); 4813 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4814 for (c = 0; c < numCells; ++c) { 4815 for (p = 0; p < numCorners; ++p) { 4816 cone[p] = cells[c*numCorners+p]+numCells; 4817 } 4818 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4819 } 4820 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4821 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4822 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4823 PetscFunctionReturn(0); 4824 } 4825 4826 #undef __FUNCT__ 4827 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4828 /* 4829 This takes as input the coordinates for each vertex 4830 */ 4831 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4832 { 4833 PetscSection coordSection; 4834 Vec coordinates; 4835 PetscScalar *coords; 4836 PetscInt coordSize, v, d; 4837 PetscErrorCode ierr; 4838 4839 PetscFunctionBegin; 4840 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4841 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4842 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4843 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4844 for (v = numCells; v < numCells+numVertices; ++v) { 4845 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4846 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4847 } 4848 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4849 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4850 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4851 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4852 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4853 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4854 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4855 for (v = 0; v < numVertices; ++v) { 4856 for (d = 0; d < spaceDim; ++d) { 4857 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4858 } 4859 } 4860 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4861 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4862 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4863 PetscFunctionReturn(0); 4864 } 4865 4866 #undef __FUNCT__ 4867 #define __FUNCT__ "DMPlexCreateFromCellList" 4868 /* 4869 This takes as input the common mesh generator output, a list of the vertices for each cell 4870 */ 4871 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4872 { 4873 PetscErrorCode ierr; 4874 4875 PetscFunctionBegin; 4876 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4877 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4878 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4879 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4880 if (interpolate) { 4881 DM idm; 4882 4883 switch (dim) { 4884 case 2: 4885 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4886 case 3: 4887 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4888 default: 4889 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4890 } 4891 ierr = DMDestroy(dm);CHKERRQ(ierr); 4892 *dm = idm; 4893 } 4894 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4895 PetscFunctionReturn(0); 4896 } 4897 4898 #if defined(PETSC_HAVE_TRIANGLE) 4899 #include <triangle.h> 4900 4901 #undef __FUNCT__ 4902 #define __FUNCT__ "InitInput_Triangle" 4903 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4904 { 4905 PetscFunctionBegin; 4906 inputCtx->numberofpoints = 0; 4907 inputCtx->numberofpointattributes = 0; 4908 inputCtx->pointlist = NULL; 4909 inputCtx->pointattributelist = NULL; 4910 inputCtx->pointmarkerlist = NULL; 4911 inputCtx->numberofsegments = 0; 4912 inputCtx->segmentlist = NULL; 4913 inputCtx->segmentmarkerlist = NULL; 4914 inputCtx->numberoftriangleattributes = 0; 4915 inputCtx->trianglelist = NULL; 4916 inputCtx->numberofholes = 0; 4917 inputCtx->holelist = NULL; 4918 inputCtx->numberofregions = 0; 4919 inputCtx->regionlist = NULL; 4920 PetscFunctionReturn(0); 4921 } 4922 4923 #undef __FUNCT__ 4924 #define __FUNCT__ "InitOutput_Triangle" 4925 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4926 { 4927 PetscFunctionBegin; 4928 outputCtx->numberofpoints = 0; 4929 outputCtx->pointlist = NULL; 4930 outputCtx->pointattributelist = NULL; 4931 outputCtx->pointmarkerlist = NULL; 4932 outputCtx->numberoftriangles = 0; 4933 outputCtx->trianglelist = NULL; 4934 outputCtx->triangleattributelist = NULL; 4935 outputCtx->neighborlist = NULL; 4936 outputCtx->segmentlist = NULL; 4937 outputCtx->segmentmarkerlist = NULL; 4938 outputCtx->numberofedges = 0; 4939 outputCtx->edgelist = NULL; 4940 outputCtx->edgemarkerlist = NULL; 4941 PetscFunctionReturn(0); 4942 } 4943 4944 #undef __FUNCT__ 4945 #define __FUNCT__ "FiniOutput_Triangle" 4946 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4947 { 4948 PetscFunctionBegin; 4949 free(outputCtx->pointmarkerlist); 4950 free(outputCtx->edgelist); 4951 free(outputCtx->edgemarkerlist); 4952 free(outputCtx->trianglelist); 4953 free(outputCtx->neighborlist); 4954 PetscFunctionReturn(0); 4955 } 4956 4957 #undef __FUNCT__ 4958 #define __FUNCT__ "DMPlexGenerate_Triangle" 4959 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4960 { 4961 MPI_Comm comm = ((PetscObject) boundary)->comm; 4962 PetscInt dim = 2; 4963 const PetscBool createConvexHull = PETSC_FALSE; 4964 const PetscBool constrained = PETSC_FALSE; 4965 struct triangulateio in; 4966 struct triangulateio out; 4967 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4968 PetscMPIInt rank; 4969 PetscErrorCode ierr; 4970 4971 PetscFunctionBegin; 4972 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4973 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4974 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4975 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4976 4977 in.numberofpoints = vEnd - vStart; 4978 if (in.numberofpoints > 0) { 4979 PetscSection coordSection; 4980 Vec coordinates; 4981 PetscScalar *array; 4982 4983 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4984 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4985 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4986 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4987 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4988 for (v = vStart; v < vEnd; ++v) { 4989 const PetscInt idx = v - vStart; 4990 PetscInt off, d; 4991 4992 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4993 for (d = 0; d < dim; ++d) { 4994 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4995 } 4996 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4997 } 4998 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4999 } 5000 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 5001 in.numberofsegments = eEnd - eStart; 5002 if (in.numberofsegments > 0) { 5003 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 5004 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 5005 for (e = eStart; e < eEnd; ++e) { 5006 const PetscInt idx = e - eStart; 5007 const PetscInt *cone; 5008 5009 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 5010 5011 in.segmentlist[idx*2+0] = cone[0] - vStart; 5012 in.segmentlist[idx*2+1] = cone[1] - vStart; 5013 5014 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5015 } 5016 } 5017 #if 0 /* Do not currently support holes */ 5018 PetscReal *holeCoords; 5019 PetscInt h, d; 5020 5021 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5022 if (in.numberofholes > 0) { 5023 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5024 for (h = 0; h < in.numberofholes; ++h) { 5025 for (d = 0; d < dim; ++d) { 5026 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5027 } 5028 } 5029 } 5030 #endif 5031 if (!rank) { 5032 char args[32]; 5033 5034 /* Take away 'Q' for verbose output */ 5035 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5036 if (createConvexHull) { 5037 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5038 } 5039 if (constrained) { 5040 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5041 } 5042 triangulate(args, &in, &out, NULL); 5043 } 5044 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5045 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5046 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5047 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5048 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5049 5050 { 5051 const PetscInt numCorners = 3; 5052 const PetscInt numCells = out.numberoftriangles; 5053 const PetscInt numVertices = out.numberofpoints; 5054 const int *cells = out.trianglelist; 5055 const double *meshCoords = out.pointlist; 5056 5057 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5058 /* Set labels */ 5059 for (v = 0; v < numVertices; ++v) { 5060 if (out.pointmarkerlist[v]) { 5061 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5062 } 5063 } 5064 if (interpolate) { 5065 for (e = 0; e < out.numberofedges; e++) { 5066 if (out.edgemarkerlist[e]) { 5067 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5068 const PetscInt *edges; 5069 PetscInt numEdges; 5070 5071 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5072 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5073 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5074 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5075 } 5076 } 5077 } 5078 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5079 } 5080 #if 0 /* Do not currently support holes */ 5081 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5082 #endif 5083 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5084 PetscFunctionReturn(0); 5085 } 5086 5087 #undef __FUNCT__ 5088 #define __FUNCT__ "DMPlexRefine_Triangle" 5089 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5090 { 5091 MPI_Comm comm = ((PetscObject) dm)->comm; 5092 PetscInt dim = 2; 5093 struct triangulateio in; 5094 struct triangulateio out; 5095 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5096 PetscMPIInt rank; 5097 PetscErrorCode ierr; 5098 5099 PetscFunctionBegin; 5100 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5101 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5102 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5103 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5104 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5105 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5106 5107 in.numberofpoints = vEnd - vStart; 5108 if (in.numberofpoints > 0) { 5109 PetscSection coordSection; 5110 Vec coordinates; 5111 PetscScalar *array; 5112 5113 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5114 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5115 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5116 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5117 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5118 for (v = vStart; v < vEnd; ++v) { 5119 const PetscInt idx = v - vStart; 5120 PetscInt off, d; 5121 5122 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5123 for (d = 0; d < dim; ++d) { 5124 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5125 } 5126 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5127 } 5128 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5129 } 5130 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5131 5132 in.numberofcorners = 3; 5133 in.numberoftriangles = cEnd - cStart; 5134 5135 in.trianglearealist = (double*) maxVolumes; 5136 if (in.numberoftriangles > 0) { 5137 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5138 for (c = cStart; c < cEnd; ++c) { 5139 const PetscInt idx = c - cStart; 5140 PetscInt *closure = NULL; 5141 PetscInt closureSize; 5142 5143 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5144 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5145 for (v = 0; v < 3; ++v) { 5146 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5147 } 5148 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5149 } 5150 } 5151 /* TODO: Segment markers are missing on input */ 5152 #if 0 /* Do not currently support holes */ 5153 PetscReal *holeCoords; 5154 PetscInt h, d; 5155 5156 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5157 if (in.numberofholes > 0) { 5158 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5159 for (h = 0; h < in.numberofholes; ++h) { 5160 for (d = 0; d < dim; ++d) { 5161 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5162 } 5163 } 5164 } 5165 #endif 5166 if (!rank) { 5167 char args[32]; 5168 5169 /* Take away 'Q' for verbose output */ 5170 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5171 triangulate(args, &in, &out, NULL); 5172 } 5173 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5174 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5175 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5176 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5177 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5178 5179 { 5180 const PetscInt numCorners = 3; 5181 const PetscInt numCells = out.numberoftriangles; 5182 const PetscInt numVertices = out.numberofpoints; 5183 const int *cells = out.trianglelist; 5184 const double *meshCoords = out.pointlist; 5185 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5186 5187 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5188 /* Set labels */ 5189 for (v = 0; v < numVertices; ++v) { 5190 if (out.pointmarkerlist[v]) { 5191 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5192 } 5193 } 5194 if (interpolate) { 5195 PetscInt e; 5196 5197 for (e = 0; e < out.numberofedges; e++) { 5198 if (out.edgemarkerlist[e]) { 5199 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5200 const PetscInt *edges; 5201 PetscInt numEdges; 5202 5203 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5204 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5205 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5206 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5207 } 5208 } 5209 } 5210 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5211 } 5212 #if 0 /* Do not currently support holes */ 5213 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5214 #endif 5215 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5216 PetscFunctionReturn(0); 5217 } 5218 #endif 5219 5220 #if defined(PETSC_HAVE_TETGEN) 5221 #include <tetgen.h> 5222 #undef __FUNCT__ 5223 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5224 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5225 { 5226 MPI_Comm comm = ((PetscObject) boundary)->comm; 5227 const PetscInt dim = 3; 5228 ::tetgenio in; 5229 ::tetgenio out; 5230 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5231 PetscMPIInt rank; 5232 PetscErrorCode ierr; 5233 5234 PetscFunctionBegin; 5235 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5236 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5237 in.numberofpoints = vEnd - vStart; 5238 if (in.numberofpoints > 0) { 5239 PetscSection coordSection; 5240 Vec coordinates; 5241 PetscScalar *array; 5242 5243 in.pointlist = new double[in.numberofpoints*dim]; 5244 in.pointmarkerlist = new int[in.numberofpoints]; 5245 5246 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5247 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5248 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5249 for (v = vStart; v < vEnd; ++v) { 5250 const PetscInt idx = v - vStart; 5251 PetscInt off, d; 5252 5253 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5254 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5255 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5256 } 5257 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5258 } 5259 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5260 5261 in.numberoffacets = fEnd - fStart; 5262 if (in.numberoffacets > 0) { 5263 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5264 in.facetmarkerlist = new int[in.numberoffacets]; 5265 for (f = fStart; f < fEnd; ++f) { 5266 const PetscInt idx = f - fStart; 5267 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 5268 5269 in.facetlist[idx].numberofpolygons = 1; 5270 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5271 in.facetlist[idx].numberofholes = 0; 5272 in.facetlist[idx].holelist = NULL; 5273 5274 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5275 for (p = 0; p < numPoints*2; p += 2) { 5276 const PetscInt point = points[p]; 5277 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5278 } 5279 5280 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5281 poly->numberofvertices = numVertices; 5282 poly->vertexlist = new int[poly->numberofvertices]; 5283 for (v = 0; v < numVertices; ++v) { 5284 const PetscInt vIdx = points[v] - vStart; 5285 poly->vertexlist[v] = vIdx; 5286 } 5287 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5288 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5289 } 5290 } 5291 if (!rank) { 5292 char args[32]; 5293 5294 /* Take away 'Q' for verbose output */ 5295 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5296 ::tetrahedralize(args, &in, &out); 5297 } 5298 { 5299 const PetscInt numCorners = 4; 5300 const PetscInt numCells = out.numberoftetrahedra; 5301 const PetscInt numVertices = out.numberofpoints; 5302 const int *cells = out.tetrahedronlist; 5303 const double *meshCoords = out.pointlist; 5304 5305 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5306 /* Set labels */ 5307 for (v = 0; v < numVertices; ++v) { 5308 if (out.pointmarkerlist[v]) { 5309 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5310 } 5311 } 5312 if (interpolate) { 5313 PetscInt e; 5314 5315 for (e = 0; e < out.numberofedges; e++) { 5316 if (out.edgemarkerlist[e]) { 5317 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5318 const PetscInt *edges; 5319 PetscInt numEdges; 5320 5321 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5322 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5323 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5324 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5325 } 5326 } 5327 for (f = 0; f < out.numberoftrifaces; f++) { 5328 if (out.trifacemarkerlist[f]) { 5329 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5330 const PetscInt *faces; 5331 PetscInt numFaces; 5332 5333 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5334 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5335 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5336 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5337 } 5338 } 5339 } 5340 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5341 } 5342 PetscFunctionReturn(0); 5343 } 5344 5345 #undef __FUNCT__ 5346 #define __FUNCT__ "DMPlexRefine_Tetgen" 5347 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5348 { 5349 MPI_Comm comm = ((PetscObject) dm)->comm; 5350 const PetscInt dim = 3; 5351 ::tetgenio in; 5352 ::tetgenio out; 5353 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5354 PetscMPIInt rank; 5355 PetscErrorCode ierr; 5356 5357 PetscFunctionBegin; 5358 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5359 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5360 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5361 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5362 5363 in.numberofpoints = vEnd - vStart; 5364 if (in.numberofpoints > 0) { 5365 PetscSection coordSection; 5366 Vec coordinates; 5367 PetscScalar *array; 5368 5369 in.pointlist = new double[in.numberofpoints*dim]; 5370 in.pointmarkerlist = new int[in.numberofpoints]; 5371 5372 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5373 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5374 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5375 for (v = vStart; v < vEnd; ++v) { 5376 const PetscInt idx = v - vStart; 5377 PetscInt off, d; 5378 5379 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5380 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5381 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5382 } 5383 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5384 } 5385 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5386 5387 in.numberofcorners = 4; 5388 in.numberoftetrahedra = cEnd - cStart; 5389 in.tetrahedronvolumelist = (double*) maxVolumes; 5390 if (in.numberoftetrahedra > 0) { 5391 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5392 for (c = cStart; c < cEnd; ++c) { 5393 const PetscInt idx = c - cStart; 5394 PetscInt *closure = NULL; 5395 PetscInt closureSize; 5396 5397 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5398 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5399 for (v = 0; v < 4; ++v) { 5400 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5401 } 5402 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5403 } 5404 } 5405 /* TODO: Put in boundary faces with markers */ 5406 if (!rank) { 5407 char args[32]; 5408 5409 /* Take away 'Q' for verbose output */ 5410 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5411 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5412 ::tetrahedralize(args, &in, &out); 5413 } 5414 in.tetrahedronvolumelist = NULL; 5415 5416 { 5417 const PetscInt numCorners = 4; 5418 const PetscInt numCells = out.numberoftetrahedra; 5419 const PetscInt numVertices = out.numberofpoints; 5420 const int *cells = out.tetrahedronlist; 5421 const double *meshCoords = out.pointlist; 5422 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5423 5424 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5425 /* Set labels */ 5426 for (v = 0; v < numVertices; ++v) { 5427 if (out.pointmarkerlist[v]) { 5428 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5429 } 5430 } 5431 if (interpolate) { 5432 PetscInt e, f; 5433 5434 for (e = 0; e < out.numberofedges; e++) { 5435 if (out.edgemarkerlist[e]) { 5436 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5437 const PetscInt *edges; 5438 PetscInt numEdges; 5439 5440 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5441 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5442 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5443 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5444 } 5445 } 5446 for (f = 0; f < out.numberoftrifaces; f++) { 5447 if (out.trifacemarkerlist[f]) { 5448 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5449 const PetscInt *faces; 5450 PetscInt numFaces; 5451 5452 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5453 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5454 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5455 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5456 } 5457 } 5458 } 5459 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5460 } 5461 PetscFunctionReturn(0); 5462 } 5463 #endif 5464 5465 #if defined(PETSC_HAVE_CTETGEN) 5466 #include "ctetgen.h" 5467 5468 #undef __FUNCT__ 5469 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5470 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5471 { 5472 MPI_Comm comm = ((PetscObject) boundary)->comm; 5473 const PetscInt dim = 3; 5474 PLC *in, *out; 5475 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5476 PetscMPIInt rank; 5477 PetscErrorCode ierr; 5478 5479 PetscFunctionBegin; 5480 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5481 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5482 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5483 ierr = PLCCreate(&in);CHKERRQ(ierr); 5484 ierr = PLCCreate(&out);CHKERRQ(ierr); 5485 5486 in->numberofpoints = vEnd - vStart; 5487 if (in->numberofpoints > 0) { 5488 PetscSection coordSection; 5489 Vec coordinates; 5490 PetscScalar *array; 5491 5492 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5493 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5494 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5495 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5496 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5497 for (v = vStart; v < vEnd; ++v) { 5498 const PetscInt idx = v - vStart; 5499 PetscInt off, d, m; 5500 5501 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5502 for (d = 0; d < dim; ++d) { 5503 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5504 } 5505 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5506 5507 in->pointmarkerlist[idx] = (int) m; 5508 } 5509 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5510 } 5511 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5512 5513 in->numberoffacets = fEnd - fStart; 5514 if (in->numberoffacets > 0) { 5515 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5516 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5517 for (f = fStart; f < fEnd; ++f) { 5518 const PetscInt idx = f - fStart; 5519 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5520 polygon *poly; 5521 5522 in->facetlist[idx].numberofpolygons = 1; 5523 5524 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5525 5526 in->facetlist[idx].numberofholes = 0; 5527 in->facetlist[idx].holelist = NULL; 5528 5529 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5530 for (p = 0; p < numPoints*2; p += 2) { 5531 const PetscInt point = points[p]; 5532 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5533 } 5534 5535 poly = in->facetlist[idx].polygonlist; 5536 poly->numberofvertices = numVertices; 5537 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5538 for (v = 0; v < numVertices; ++v) { 5539 const PetscInt vIdx = points[v] - vStart; 5540 poly->vertexlist[v] = vIdx; 5541 } 5542 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5543 in->facetmarkerlist[idx] = (int) m; 5544 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5545 } 5546 } 5547 if (!rank) { 5548 TetGenOpts t; 5549 5550 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5551 t.in = boundary; /* Should go away */ 5552 t.plc = 1; 5553 t.quality = 1; 5554 t.edgesout = 1; 5555 t.zeroindex = 1; 5556 t.quiet = 1; 5557 t.verbose = verbose; 5558 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5559 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5560 } 5561 { 5562 const PetscInt numCorners = 4; 5563 const PetscInt numCells = out->numberoftetrahedra; 5564 const PetscInt numVertices = out->numberofpoints; 5565 const int *cells = out->tetrahedronlist; 5566 const double *meshCoords = out->pointlist; 5567 5568 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5569 /* Set labels */ 5570 for (v = 0; v < numVertices; ++v) { 5571 if (out->pointmarkerlist[v]) { 5572 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5573 } 5574 } 5575 if (interpolate) { 5576 PetscInt e; 5577 5578 for (e = 0; e < out->numberofedges; e++) { 5579 if (out->edgemarkerlist[e]) { 5580 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5581 const PetscInt *edges; 5582 PetscInt numEdges; 5583 5584 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5585 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5586 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5587 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5588 } 5589 } 5590 for (f = 0; f < out->numberoftrifaces; f++) { 5591 if (out->trifacemarkerlist[f]) { 5592 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5593 const PetscInt *faces; 5594 PetscInt numFaces; 5595 5596 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5597 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5598 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5599 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5600 } 5601 } 5602 } 5603 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5604 } 5605 5606 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5607 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5608 PetscFunctionReturn(0); 5609 } 5610 5611 #undef __FUNCT__ 5612 #define __FUNCT__ "DMPlexRefine_CTetgen" 5613 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5614 { 5615 MPI_Comm comm = ((PetscObject) dm)->comm; 5616 const PetscInt dim = 3; 5617 PLC *in, *out; 5618 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5619 PetscMPIInt rank; 5620 PetscErrorCode ierr; 5621 5622 PetscFunctionBegin; 5623 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5624 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5625 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5626 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5627 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5628 ierr = PLCCreate(&in);CHKERRQ(ierr); 5629 ierr = PLCCreate(&out);CHKERRQ(ierr); 5630 5631 in->numberofpoints = vEnd - vStart; 5632 if (in->numberofpoints > 0) { 5633 PetscSection coordSection; 5634 Vec coordinates; 5635 PetscScalar *array; 5636 5637 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5638 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5639 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5640 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5641 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5642 for (v = vStart; v < vEnd; ++v) { 5643 const PetscInt idx = v - vStart; 5644 PetscInt off, d, m; 5645 5646 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5647 for (d = 0; d < dim; ++d) { 5648 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5649 } 5650 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5651 5652 in->pointmarkerlist[idx] = (int) m; 5653 } 5654 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5655 } 5656 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5657 5658 in->numberofcorners = 4; 5659 in->numberoftetrahedra = cEnd - cStart; 5660 in->tetrahedronvolumelist = maxVolumes; 5661 if (in->numberoftetrahedra > 0) { 5662 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5663 for (c = cStart; c < cEnd; ++c) { 5664 const PetscInt idx = c - cStart; 5665 PetscInt *closure = NULL; 5666 PetscInt closureSize; 5667 5668 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5669 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5670 for (v = 0; v < 4; ++v) { 5671 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5672 } 5673 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5674 } 5675 } 5676 if (!rank) { 5677 TetGenOpts t; 5678 5679 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5680 5681 t.in = dm; /* Should go away */ 5682 t.refine = 1; 5683 t.varvolume = 1; 5684 t.quality = 1; 5685 t.edgesout = 1; 5686 t.zeroindex = 1; 5687 t.quiet = 1; 5688 t.verbose = verbose; /* Change this */ 5689 5690 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5691 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5692 } 5693 { 5694 const PetscInt numCorners = 4; 5695 const PetscInt numCells = out->numberoftetrahedra; 5696 const PetscInt numVertices = out->numberofpoints; 5697 const int *cells = out->tetrahedronlist; 5698 const double *meshCoords = out->pointlist; 5699 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5700 5701 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5702 /* Set labels */ 5703 for (v = 0; v < numVertices; ++v) { 5704 if (out->pointmarkerlist[v]) { 5705 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5706 } 5707 } 5708 if (interpolate) { 5709 PetscInt e, f; 5710 5711 for (e = 0; e < out->numberofedges; e++) { 5712 if (out->edgemarkerlist[e]) { 5713 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5714 const PetscInt *edges; 5715 PetscInt numEdges; 5716 5717 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5718 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5719 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5720 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5721 } 5722 } 5723 for (f = 0; f < out->numberoftrifaces; f++) { 5724 if (out->trifacemarkerlist[f]) { 5725 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5726 const PetscInt *faces; 5727 PetscInt numFaces; 5728 5729 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5730 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5731 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5732 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5733 } 5734 } 5735 } 5736 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5737 } 5738 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5739 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5740 PetscFunctionReturn(0); 5741 } 5742 #endif 5743 5744 #undef __FUNCT__ 5745 #define __FUNCT__ "DMPlexGenerate" 5746 /*@C 5747 DMPlexGenerate - Generates a mesh. 5748 5749 Not Collective 5750 5751 Input Parameters: 5752 + boundary - The DMPlex boundary object 5753 . name - The mesh generation package name 5754 - interpolate - Flag to create intermediate mesh elements 5755 5756 Output Parameter: 5757 . mesh - The DMPlex object 5758 5759 Level: intermediate 5760 5761 .keywords: mesh, elements 5762 .seealso: DMPlexCreate(), DMRefine() 5763 @*/ 5764 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5765 { 5766 PetscInt dim; 5767 char genname[1024]; 5768 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5769 PetscErrorCode ierr; 5770 5771 PetscFunctionBegin; 5772 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5773 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5774 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5775 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5776 if (flg) name = genname; 5777 if (name) { 5778 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5779 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5780 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5781 } 5782 switch (dim) { 5783 case 1: 5784 if (!name || isTriangle) { 5785 #if defined(PETSC_HAVE_TRIANGLE) 5786 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5787 #else 5788 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5789 #endif 5790 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5791 break; 5792 case 2: 5793 if (!name || isCTetgen) { 5794 #if defined(PETSC_HAVE_CTETGEN) 5795 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5796 #else 5797 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5798 #endif 5799 } else if (isTetgen) { 5800 #if defined(PETSC_HAVE_TETGEN) 5801 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5802 #else 5803 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5804 #endif 5805 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5806 break; 5807 default: 5808 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5809 } 5810 PetscFunctionReturn(0); 5811 } 5812 5813 typedef PetscInt CellRefiner; 5814 5815 #undef __FUNCT__ 5816 #define __FUNCT__ "GetDepthStart_Private" 5817 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5818 { 5819 PetscFunctionBegin; 5820 if (cStart) *cStart = 0; 5821 if (vStart) *vStart = depthSize[depth]; 5822 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5823 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5824 PetscFunctionReturn(0); 5825 } 5826 5827 #undef __FUNCT__ 5828 #define __FUNCT__ "GetDepthEnd_Private" 5829 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5830 { 5831 PetscFunctionBegin; 5832 if (cEnd) *cEnd = depthSize[depth]; 5833 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5834 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5835 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5836 PetscFunctionReturn(0); 5837 } 5838 5839 #undef __FUNCT__ 5840 #define __FUNCT__ "CellRefinerGetSizes" 5841 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5842 { 5843 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5844 PetscErrorCode ierr; 5845 5846 PetscFunctionBegin; 5847 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5848 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5849 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5850 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5851 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5852 switch (refiner) { 5853 case 1: 5854 /* Simplicial 2D */ 5855 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5856 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5857 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5858 break; 5859 case 3: 5860 /* Hybrid 2D */ 5861 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5862 cMax = PetscMin(cEnd, cMax); 5863 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5864 fMax = PetscMin(fEnd, fMax); 5865 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5866 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 */ 5867 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5868 break; 5869 case 2: 5870 /* Hex 2D */ 5871 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5872 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5873 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5874 break; 5875 default: 5876 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5877 } 5878 PetscFunctionReturn(0); 5879 } 5880 5881 #undef __FUNCT__ 5882 #define __FUNCT__ "CellRefinerSetConeSizes" 5883 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5884 { 5885 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5886 PetscErrorCode ierr; 5887 5888 PetscFunctionBegin; 5889 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5890 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5891 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5892 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5893 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5894 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5895 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5896 switch (refiner) { 5897 case 1: 5898 /* Simplicial 2D */ 5899 /* All cells have 3 faces */ 5900 for (c = cStart; c < cEnd; ++c) { 5901 for (r = 0; r < 4; ++r) { 5902 const PetscInt newp = (c - cStart)*4 + r; 5903 5904 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5905 } 5906 } 5907 /* Split faces have 2 vertices and the same cells as the parent */ 5908 for (f = fStart; f < fEnd; ++f) { 5909 for (r = 0; r < 2; ++r) { 5910 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5911 PetscInt size; 5912 5913 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5914 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5915 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5916 } 5917 } 5918 /* Interior faces have 2 vertices and 2 cells */ 5919 for (c = cStart; c < cEnd; ++c) { 5920 for (r = 0; r < 3; ++r) { 5921 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5922 5923 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5924 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5925 } 5926 } 5927 /* Old vertices have identical supports */ 5928 for (v = vStart; v < vEnd; ++v) { 5929 const PetscInt newp = vStartNew + (v - vStart); 5930 PetscInt size; 5931 5932 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5933 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5934 } 5935 /* Face vertices have 2 + cells*2 supports */ 5936 for (f = fStart; f < fEnd; ++f) { 5937 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5938 PetscInt size; 5939 5940 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5941 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5942 } 5943 break; 5944 case 2: 5945 /* Hex 2D */ 5946 /* All cells have 4 faces */ 5947 for (c = cStart; c < cEnd; ++c) { 5948 for (r = 0; r < 4; ++r) { 5949 const PetscInt newp = (c - cStart)*4 + r; 5950 5951 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5952 } 5953 } 5954 /* Split faces have 2 vertices and the same cells as the parent */ 5955 for (f = fStart; f < fEnd; ++f) { 5956 for (r = 0; r < 2; ++r) { 5957 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5958 PetscInt size; 5959 5960 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5961 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5962 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5963 } 5964 } 5965 /* Interior faces have 2 vertices and 2 cells */ 5966 for (c = cStart; c < cEnd; ++c) { 5967 for (r = 0; r < 4; ++r) { 5968 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5969 5970 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5971 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5972 } 5973 } 5974 /* Old vertices have identical supports */ 5975 for (v = vStart; v < vEnd; ++v) { 5976 const PetscInt newp = vStartNew + (v - vStart); 5977 PetscInt size; 5978 5979 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5980 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5981 } 5982 /* Face vertices have 2 + cells supports */ 5983 for (f = fStart; f < fEnd; ++f) { 5984 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5985 PetscInt size; 5986 5987 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5988 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5989 } 5990 /* Cell vertices have 4 supports */ 5991 for (c = cStart; c < cEnd; ++c) { 5992 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5993 5994 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5995 } 5996 break; 5997 case 3: 5998 /* Hybrid 2D */ 5999 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6000 cMax = PetscMin(cEnd, cMax); 6001 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6002 fMax = PetscMin(fEnd, fMax); 6003 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6004 /* Interior cells have 3 faces */ 6005 for (c = cStart; c < cMax; ++c) { 6006 for (r = 0; r < 4; ++r) { 6007 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 6008 6009 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 6010 } 6011 } 6012 /* Hybrid cells have 4 faces */ 6013 for (c = cMax; c < cEnd; ++c) { 6014 for (r = 0; r < 2; ++r) { 6015 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6016 6017 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6018 } 6019 } 6020 /* Interior split faces have 2 vertices and the same cells as the parent */ 6021 for (f = fStart; f < fMax; ++f) { 6022 for (r = 0; r < 2; ++r) { 6023 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6024 PetscInt size; 6025 6026 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6027 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6028 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6029 } 6030 } 6031 /* Interior cell faces have 2 vertices and 2 cells */ 6032 for (c = cStart; c < cMax; ++c) { 6033 for (r = 0; r < 3; ++r) { 6034 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6035 6036 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6037 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6038 } 6039 } 6040 /* Hybrid faces have 2 vertices and the same cells */ 6041 for (f = fMax; f < fEnd; ++f) { 6042 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6043 PetscInt size; 6044 6045 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6046 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6047 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6048 } 6049 /* Hybrid cell faces have 2 vertices and 2 cells */ 6050 for (c = cMax; c < cEnd; ++c) { 6051 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6052 6053 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6054 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6055 } 6056 /* Old vertices have identical supports */ 6057 for (v = vStart; v < vEnd; ++v) { 6058 const PetscInt newp = vStartNew + (v - vStart); 6059 PetscInt size; 6060 6061 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6062 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6063 } 6064 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6065 for (f = fStart; f < fMax; ++f) { 6066 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6067 const PetscInt *support; 6068 PetscInt size, newSize = 2, s; 6069 6070 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6071 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6072 for (s = 0; s < size; ++s) { 6073 if (support[s] >= cMax) newSize += 1; 6074 else newSize += 2; 6075 } 6076 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6077 } 6078 break; 6079 default: 6080 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6081 } 6082 PetscFunctionReturn(0); 6083 } 6084 6085 #undef __FUNCT__ 6086 #define __FUNCT__ "CellRefinerSetCones" 6087 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6088 { 6089 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; 6090 PetscInt maxSupportSize, *supportRef; 6091 PetscErrorCode ierr; 6092 6093 PetscFunctionBegin; 6094 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6095 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6096 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6097 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6098 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6099 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6100 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6101 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6102 switch (refiner) { 6103 case 1: 6104 /* Simplicial 2D */ 6105 /* 6106 2 6107 |\ 6108 | \ 6109 | \ 6110 | \ 6111 | C \ 6112 | \ 6113 | \ 6114 2---1---1 6115 |\ D / \ 6116 | 2 0 \ 6117 |A \ / B \ 6118 0---0-------1 6119 */ 6120 /* All cells have 3 faces */ 6121 for (c = cStart; c < cEnd; ++c) { 6122 const PetscInt newp = cStartNew + (c - cStart)*4; 6123 const PetscInt *cone, *ornt; 6124 PetscInt coneNew[3], orntNew[3]; 6125 6126 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6127 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6128 /* A triangle */ 6129 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6130 orntNew[0] = ornt[0]; 6131 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6132 orntNew[1] = -2; 6133 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6134 orntNew[2] = ornt[2]; 6135 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6136 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6137 #if 1 6138 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); 6139 for (p = 0; p < 3; ++p) { 6140 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); 6141 } 6142 #endif 6143 /* B triangle */ 6144 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6145 orntNew[0] = ornt[0]; 6146 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6147 orntNew[1] = ornt[1]; 6148 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6149 orntNew[2] = -2; 6150 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6151 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6152 #if 1 6153 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); 6154 for (p = 0; p < 3; ++p) { 6155 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); 6156 } 6157 #endif 6158 /* C triangle */ 6159 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6160 orntNew[0] = -2; 6161 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6162 orntNew[1] = ornt[1]; 6163 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6164 orntNew[2] = ornt[2]; 6165 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6166 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6167 #if 1 6168 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); 6169 for (p = 0; p < 3; ++p) { 6170 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); 6171 } 6172 #endif 6173 /* D triangle */ 6174 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6175 orntNew[0] = 0; 6176 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6177 orntNew[1] = 0; 6178 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6179 orntNew[2] = 0; 6180 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6181 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6182 #if 1 6183 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); 6184 for (p = 0; p < 3; ++p) { 6185 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); 6186 } 6187 #endif 6188 } 6189 /* Split faces have 2 vertices and the same cells as the parent */ 6190 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6191 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6192 for (f = fStart; f < fEnd; ++f) { 6193 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6194 6195 for (r = 0; r < 2; ++r) { 6196 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6197 const PetscInt *cone, *support; 6198 PetscInt coneNew[2], coneSize, c, supportSize, s; 6199 6200 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6201 coneNew[0] = vStartNew + (cone[0] - vStart); 6202 coneNew[1] = vStartNew + (cone[1] - vStart); 6203 coneNew[(r+1)%2] = newv; 6204 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6205 #if 1 6206 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6207 for (p = 0; p < 2; ++p) { 6208 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); 6209 } 6210 #endif 6211 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6212 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6213 for (s = 0; s < supportSize; ++s) { 6214 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6215 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6216 for (c = 0; c < coneSize; ++c) { 6217 if (cone[c] == f) break; 6218 } 6219 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6220 } 6221 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6222 #if 1 6223 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6224 for (p = 0; p < supportSize; ++p) { 6225 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); 6226 } 6227 #endif 6228 } 6229 } 6230 /* Interior faces have 2 vertices and 2 cells */ 6231 for (c = cStart; c < cEnd; ++c) { 6232 const PetscInt *cone; 6233 6234 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6235 for (r = 0; r < 3; ++r) { 6236 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6237 PetscInt coneNew[2]; 6238 PetscInt supportNew[2]; 6239 6240 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6241 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6242 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6243 #if 1 6244 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6245 for (p = 0; p < 2; ++p) { 6246 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6247 } 6248 #endif 6249 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6250 supportNew[1] = (c - cStart)*4 + 3; 6251 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6252 #if 1 6253 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6254 for (p = 0; p < 2; ++p) { 6255 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); 6256 } 6257 #endif 6258 } 6259 } 6260 /* Old vertices have identical supports */ 6261 for (v = vStart; v < vEnd; ++v) { 6262 const PetscInt newp = vStartNew + (v - vStart); 6263 const PetscInt *support, *cone; 6264 PetscInt size, s; 6265 6266 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6267 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6268 for (s = 0; s < size; ++s) { 6269 PetscInt r = 0; 6270 6271 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6272 if (cone[1] == v) r = 1; 6273 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6274 } 6275 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6276 #if 1 6277 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6278 for (p = 0; p < size; ++p) { 6279 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); 6280 } 6281 #endif 6282 } 6283 /* Face vertices have 2 + cells*2 supports */ 6284 for (f = fStart; f < fEnd; ++f) { 6285 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6286 const PetscInt *cone, *support; 6287 PetscInt size, s; 6288 6289 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6290 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6291 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6292 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6293 for (s = 0; s < size; ++s) { 6294 PetscInt r = 0; 6295 6296 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6297 if (cone[1] == f) r = 1; 6298 else if (cone[2] == f) r = 2; 6299 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6300 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6301 } 6302 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6303 #if 1 6304 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6305 for (p = 0; p < 2+size*2; ++p) { 6306 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); 6307 } 6308 #endif 6309 } 6310 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6311 break; 6312 case 2: 6313 /* Hex 2D */ 6314 /* 6315 3---------2---------2 6316 | | | 6317 | D 2 C | 6318 | | | 6319 3----3----0----1----1 6320 | | | 6321 | A 0 B | 6322 | | | 6323 0---------0---------1 6324 */ 6325 /* All cells have 4 faces */ 6326 for (c = cStart; c < cEnd; ++c) { 6327 const PetscInt newp = (c - cStart)*4; 6328 const PetscInt *cone, *ornt; 6329 PetscInt coneNew[4], orntNew[4]; 6330 6331 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6332 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6333 /* A quad */ 6334 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6335 orntNew[0] = ornt[0]; 6336 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6337 orntNew[1] = 0; 6338 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6339 orntNew[2] = -2; 6340 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6341 orntNew[3] = ornt[3]; 6342 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6343 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6344 #if 1 6345 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); 6346 for (p = 0; p < 4; ++p) { 6347 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); 6348 } 6349 #endif 6350 /* B quad */ 6351 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6352 orntNew[0] = ornt[0]; 6353 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6354 orntNew[1] = ornt[1]; 6355 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6356 orntNew[2] = 0; 6357 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6358 orntNew[3] = -2; 6359 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6360 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6361 #if 1 6362 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); 6363 for (p = 0; p < 4; ++p) { 6364 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); 6365 } 6366 #endif 6367 /* C quad */ 6368 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6369 orntNew[0] = -2; 6370 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6371 orntNew[1] = ornt[1]; 6372 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6373 orntNew[2] = ornt[2]; 6374 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6375 orntNew[3] = 0; 6376 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6377 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6378 #if 1 6379 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); 6380 for (p = 0; p < 4; ++p) { 6381 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); 6382 } 6383 #endif 6384 /* D quad */ 6385 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6386 orntNew[0] = 0; 6387 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6388 orntNew[1] = -2; 6389 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6390 orntNew[2] = ornt[2]; 6391 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6392 orntNew[3] = ornt[3]; 6393 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6394 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6395 #if 1 6396 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); 6397 for (p = 0; p < 4; ++p) { 6398 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); 6399 } 6400 #endif 6401 } 6402 /* Split faces have 2 vertices and the same cells as the parent */ 6403 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6404 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6405 for (f = fStart; f < fEnd; ++f) { 6406 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6407 6408 for (r = 0; r < 2; ++r) { 6409 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6410 const PetscInt *cone, *support; 6411 PetscInt coneNew[2], coneSize, c, supportSize, s; 6412 6413 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6414 coneNew[0] = vStartNew + (cone[0] - vStart); 6415 coneNew[1] = vStartNew + (cone[1] - vStart); 6416 coneNew[(r+1)%2] = newv; 6417 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6418 #if 1 6419 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6420 for (p = 0; p < 2; ++p) { 6421 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); 6422 } 6423 #endif 6424 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6425 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6426 for (s = 0; s < supportSize; ++s) { 6427 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6428 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6429 for (c = 0; c < coneSize; ++c) { 6430 if (cone[c] == f) break; 6431 } 6432 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6433 } 6434 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6435 #if 1 6436 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6437 for (p = 0; p < supportSize; ++p) { 6438 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); 6439 } 6440 #endif 6441 } 6442 } 6443 /* Interior faces have 2 vertices and 2 cells */ 6444 for (c = cStart; c < cEnd; ++c) { 6445 const PetscInt *cone; 6446 PetscInt coneNew[2], supportNew[2]; 6447 6448 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6449 for (r = 0; r < 4; ++r) { 6450 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6451 6452 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6453 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6454 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6455 #if 1 6456 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6457 for (p = 0; p < 2; ++p) { 6458 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); 6459 } 6460 #endif 6461 supportNew[0] = (c - cStart)*4 + r; 6462 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6463 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6464 #if 1 6465 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6466 for (p = 0; p < 2; ++p) { 6467 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); 6468 } 6469 #endif 6470 } 6471 } 6472 /* Old vertices have identical supports */ 6473 for (v = vStart; v < vEnd; ++v) { 6474 const PetscInt newp = vStartNew + (v - vStart); 6475 const PetscInt *support, *cone; 6476 PetscInt size, s; 6477 6478 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6479 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6480 for (s = 0; s < size; ++s) { 6481 PetscInt r = 0; 6482 6483 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6484 if (cone[1] == v) r = 1; 6485 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6486 } 6487 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6488 #if 1 6489 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6490 for (p = 0; p < size; ++p) { 6491 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); 6492 } 6493 #endif 6494 } 6495 /* Face vertices have 2 + cells supports */ 6496 for (f = fStart; f < fEnd; ++f) { 6497 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6498 const PetscInt *cone, *support; 6499 PetscInt size, s; 6500 6501 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6502 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6503 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6504 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6505 for (s = 0; s < size; ++s) { 6506 PetscInt r = 0; 6507 6508 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6509 if (cone[1] == f) r = 1; 6510 else if (cone[2] == f) r = 2; 6511 else if (cone[3] == f) r = 3; 6512 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6513 } 6514 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6515 #if 1 6516 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6517 for (p = 0; p < 2+size; ++p) { 6518 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); 6519 } 6520 #endif 6521 } 6522 /* Cell vertices have 4 supports */ 6523 for (c = cStart; c < cEnd; ++c) { 6524 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6525 PetscInt supportNew[4]; 6526 6527 for (r = 0; r < 4; ++r) { 6528 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6529 } 6530 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6531 } 6532 break; 6533 case 3: 6534 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6535 cMax = PetscMin(cEnd, cMax); 6536 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6537 fMax = PetscMin(fEnd, fMax); 6538 /* Interior cells have 3 faces */ 6539 for (c = cStart; c < cMax; ++c) { 6540 const PetscInt newp = cStartNew + (c - cStart)*4; 6541 const PetscInt *cone, *ornt; 6542 PetscInt coneNew[3], orntNew[3]; 6543 6544 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6545 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6546 /* A triangle */ 6547 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6548 orntNew[0] = ornt[0]; 6549 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6550 orntNew[1] = -2; 6551 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6552 orntNew[2] = ornt[2]; 6553 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6554 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6555 #if 1 6556 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); 6557 for (p = 0; p < 3; ++p) { 6558 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); 6559 } 6560 #endif 6561 /* B triangle */ 6562 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6563 orntNew[0] = ornt[0]; 6564 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6565 orntNew[1] = ornt[1]; 6566 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6567 orntNew[2] = -2; 6568 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6569 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6570 #if 1 6571 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); 6572 for (p = 0; p < 3; ++p) { 6573 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6574 } 6575 #endif 6576 /* C triangle */ 6577 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6578 orntNew[0] = -2; 6579 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6580 orntNew[1] = ornt[1]; 6581 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6582 orntNew[2] = ornt[2]; 6583 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6584 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6585 #if 1 6586 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); 6587 for (p = 0; p < 3; ++p) { 6588 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); 6589 } 6590 #endif 6591 /* D triangle */ 6592 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6593 orntNew[0] = 0; 6594 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6595 orntNew[1] = 0; 6596 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6597 orntNew[2] = 0; 6598 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6599 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6600 #if 1 6601 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); 6602 for (p = 0; p < 3; ++p) { 6603 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); 6604 } 6605 #endif 6606 } 6607 /* 6608 2----3----3 6609 | | 6610 | B | 6611 | | 6612 0----4--- 1 6613 | | 6614 | A | 6615 | | 6616 0----2----1 6617 */ 6618 /* Hybrid cells have 4 faces */ 6619 for (c = cMax; c < cEnd; ++c) { 6620 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6621 const PetscInt *cone, *ornt; 6622 PetscInt coneNew[4], orntNew[4]; 6623 6624 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6625 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6626 /* A quad */ 6627 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6628 orntNew[0] = ornt[0]; 6629 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6630 orntNew[1] = ornt[1]; 6631 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6632 orntNew[2] = 0; 6633 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6634 orntNew[3] = 0; 6635 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6636 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6637 #if 1 6638 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); 6639 for (p = 0; p < 4; ++p) { 6640 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); 6641 } 6642 #endif 6643 /* B quad */ 6644 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6645 orntNew[0] = ornt[0]; 6646 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6647 orntNew[1] = ornt[1]; 6648 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6649 orntNew[2] = 0; 6650 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6651 orntNew[3] = 0; 6652 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6653 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6654 #if 1 6655 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); 6656 for (p = 0; p < 4; ++p) { 6657 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); 6658 } 6659 #endif 6660 } 6661 /* Interior split faces have 2 vertices and the same cells as the parent */ 6662 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6663 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6664 for (f = fStart; f < fMax; ++f) { 6665 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6666 6667 for (r = 0; r < 2; ++r) { 6668 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6669 const PetscInt *cone, *support; 6670 PetscInt coneNew[2], coneSize, c, supportSize, s; 6671 6672 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6673 coneNew[0] = vStartNew + (cone[0] - vStart); 6674 coneNew[1] = vStartNew + (cone[1] - vStart); 6675 coneNew[(r+1)%2] = newv; 6676 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6677 #if 1 6678 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6679 for (p = 0; p < 2; ++p) { 6680 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); 6681 } 6682 #endif 6683 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6684 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6685 for (s = 0; s < supportSize; ++s) { 6686 if (support[s] >= cMax) { 6687 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6688 } else { 6689 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6690 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6691 for (c = 0; c < coneSize; ++c) { 6692 if (cone[c] == f) break; 6693 } 6694 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6695 } 6696 } 6697 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6698 #if 1 6699 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6700 for (p = 0; p < supportSize; ++p) { 6701 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); 6702 } 6703 #endif 6704 } 6705 } 6706 /* Interior cell faces have 2 vertices and 2 cells */ 6707 for (c = cStart; c < cMax; ++c) { 6708 const PetscInt *cone; 6709 6710 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6711 for (r = 0; r < 3; ++r) { 6712 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6713 PetscInt coneNew[2]; 6714 PetscInt supportNew[2]; 6715 6716 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6717 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6718 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6719 #if 1 6720 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6721 for (p = 0; p < 2; ++p) { 6722 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); 6723 } 6724 #endif 6725 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6726 supportNew[1] = (c - cStart)*4 + 3; 6727 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6728 #if 1 6729 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6730 for (p = 0; p < 2; ++p) { 6731 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); 6732 } 6733 #endif 6734 } 6735 } 6736 /* Interior hybrid faces have 2 vertices and the same cells */ 6737 for (f = fMax; f < fEnd; ++f) { 6738 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6739 const PetscInt *cone; 6740 const PetscInt *support; 6741 PetscInt coneNew[2]; 6742 PetscInt supportNew[2]; 6743 PetscInt size, s, r; 6744 6745 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6746 coneNew[0] = vStartNew + (cone[0] - vStart); 6747 coneNew[1] = vStartNew + (cone[1] - vStart); 6748 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6749 #if 1 6750 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6751 for (p = 0; p < 2; ++p) { 6752 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); 6753 } 6754 #endif 6755 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6756 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6757 for (s = 0; s < size; ++s) { 6758 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6759 for (r = 0; r < 2; ++r) { 6760 if (cone[r+2] == f) break; 6761 } 6762 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6763 } 6764 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6765 #if 1 6766 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6767 for (p = 0; p < size; ++p) { 6768 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); 6769 } 6770 #endif 6771 } 6772 /* Cell hybrid faces have 2 vertices and 2 cells */ 6773 for (c = cMax; c < cEnd; ++c) { 6774 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6775 const PetscInt *cone; 6776 PetscInt coneNew[2]; 6777 PetscInt supportNew[2]; 6778 6779 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6780 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6781 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6782 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6783 #if 1 6784 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6785 for (p = 0; p < 2; ++p) { 6786 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); 6787 } 6788 #endif 6789 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6790 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6791 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6792 #if 1 6793 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6794 for (p = 0; p < 2; ++p) { 6795 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); 6796 } 6797 #endif 6798 } 6799 /* Old vertices have identical supports */ 6800 for (v = vStart; v < vEnd; ++v) { 6801 const PetscInt newp = vStartNew + (v - vStart); 6802 const PetscInt *support, *cone; 6803 PetscInt size, s; 6804 6805 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6806 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6807 for (s = 0; s < size; ++s) { 6808 if (support[s] >= fMax) { 6809 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6810 } else { 6811 PetscInt r = 0; 6812 6813 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6814 if (cone[1] == v) r = 1; 6815 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6816 } 6817 } 6818 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6819 #if 1 6820 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6821 for (p = 0; p < size; ++p) { 6822 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); 6823 } 6824 #endif 6825 } 6826 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6827 for (f = fStart; f < fMax; ++f) { 6828 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6829 const PetscInt *cone, *support; 6830 PetscInt size, newSize = 2, s; 6831 6832 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6833 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6834 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6835 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6836 for (s = 0; s < size; ++s) { 6837 PetscInt r = 0; 6838 6839 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6840 if (support[s] >= cMax) { 6841 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6842 6843 newSize += 1; 6844 } else { 6845 if (cone[1] == f) r = 1; 6846 else if (cone[2] == f) r = 2; 6847 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6848 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6849 6850 newSize += 2; 6851 } 6852 } 6853 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6854 #if 1 6855 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6856 for (p = 0; p < newSize; ++p) { 6857 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); 6858 } 6859 #endif 6860 } 6861 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6862 break; 6863 default: 6864 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6865 } 6866 PetscFunctionReturn(0); 6867 } 6868 6869 #undef __FUNCT__ 6870 #define __FUNCT__ "CellRefinerSetCoordinates" 6871 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6872 { 6873 PetscSection coordSection, coordSectionNew; 6874 Vec coordinates, coordinatesNew; 6875 PetscScalar *coords, *coordsNew; 6876 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6877 PetscErrorCode ierr; 6878 6879 PetscFunctionBegin; 6880 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6881 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6882 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6883 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6884 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6885 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6886 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6887 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6888 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6889 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6890 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6891 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6892 if (fMax < 0) fMax = fEnd; 6893 switch (refiner) { 6894 case 1: 6895 case 2: 6896 case 3: 6897 /* Simplicial and Hex 2D */ 6898 /* All vertices have the dim coordinates */ 6899 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6900 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6901 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6902 } 6903 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6904 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6905 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6906 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6907 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6908 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6909 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6910 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6911 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6912 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6913 /* Old vertices have the same coordinates */ 6914 for (v = vStart; v < vEnd; ++v) { 6915 const PetscInt newv = vStartNew + (v - vStart); 6916 PetscInt off, offnew, d; 6917 6918 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6919 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6920 for (d = 0; d < dim; ++d) { 6921 coordsNew[offnew+d] = coords[off+d]; 6922 } 6923 } 6924 /* Face vertices have the average of endpoint coordinates */ 6925 for (f = fStart; f < fMax; ++f) { 6926 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6927 const PetscInt *cone; 6928 PetscInt coneSize, offA, offB, offnew, d; 6929 6930 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6931 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6932 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6933 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6934 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6935 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6936 for (d = 0; d < dim; ++d) { 6937 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6938 } 6939 } 6940 /* Just Hex 2D */ 6941 if (refiner == 2) { 6942 /* Cell vertices have the average of corner coordinates */ 6943 for (c = cStart; c < cEnd; ++c) { 6944 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6945 PetscInt *cone = NULL; 6946 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6947 6948 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6949 for (p = 0; p < closureSize*2; p += 2) { 6950 const PetscInt point = cone[p]; 6951 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6952 } 6953 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6954 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6955 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6956 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6957 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6958 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6959 for (d = 0; d < dim; ++d) { 6960 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6961 } 6962 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6963 } 6964 } 6965 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6966 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6967 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6968 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6969 break; 6970 default: 6971 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6972 } 6973 PetscFunctionReturn(0); 6974 } 6975 6976 #undef __FUNCT__ 6977 #define __FUNCT__ "DMPlexCreateProcessSF" 6978 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6979 { 6980 PetscInt numRoots, numLeaves, l; 6981 const PetscInt *localPoints; 6982 const PetscSFNode *remotePoints; 6983 PetscInt *localPointsNew; 6984 PetscSFNode *remotePointsNew; 6985 PetscInt *ranks, *ranksNew; 6986 PetscErrorCode ierr; 6987 6988 PetscFunctionBegin; 6989 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6990 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6991 for (l = 0; l < numLeaves; ++l) { 6992 ranks[l] = remotePoints[l].rank; 6993 } 6994 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6995 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6996 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6997 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6998 for (l = 0; l < numLeaves; ++l) { 6999 ranksNew[l] = ranks[l]; 7000 localPointsNew[l] = l; 7001 remotePointsNew[l].index = 0; 7002 remotePointsNew[l].rank = ranksNew[l]; 7003 } 7004 ierr = PetscFree(ranks);CHKERRQ(ierr); 7005 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 7006 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 7007 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 7008 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7009 PetscFunctionReturn(0); 7010 } 7011 7012 #undef __FUNCT__ 7013 #define __FUNCT__ "CellRefinerCreateSF" 7014 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7015 { 7016 PetscSF sf, sfNew, sfProcess; 7017 IS processRanks; 7018 MPI_Datatype depthType; 7019 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7020 const PetscInt *localPoints, *neighbors; 7021 const PetscSFNode *remotePoints; 7022 PetscInt *localPointsNew; 7023 PetscSFNode *remotePointsNew; 7024 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7025 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7026 PetscErrorCode ierr; 7027 7028 PetscFunctionBegin; 7029 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7030 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7031 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7032 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7033 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7034 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7035 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7036 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7037 switch (refiner) { 7038 case 3: 7039 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7040 cMax = PetscMin(cEnd, cMax); 7041 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7042 fMax = PetscMin(fEnd, fMax); 7043 } 7044 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7045 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7046 /* Caculate size of new SF */ 7047 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7048 if (numRoots < 0) PetscFunctionReturn(0); 7049 for (l = 0; l < numLeaves; ++l) { 7050 const PetscInt p = localPoints[l]; 7051 7052 switch (refiner) { 7053 case 1: 7054 /* Simplicial 2D */ 7055 if ((p >= vStart) && (p < vEnd)) { 7056 /* Old vertices stay the same */ 7057 ++numLeavesNew; 7058 } else if ((p >= fStart) && (p < fEnd)) { 7059 /* Old faces add new faces and vertex */ 7060 numLeavesNew += 1 + 2; 7061 } else if ((p >= cStart) && (p < cEnd)) { 7062 /* Old cells add new cells and interior faces */ 7063 numLeavesNew += 4 + 3; 7064 } 7065 break; 7066 case 2: 7067 /* Hex 2D */ 7068 if ((p >= vStart) && (p < vEnd)) { 7069 /* Old vertices stay the same */ 7070 ++numLeavesNew; 7071 } else if ((p >= fStart) && (p < fEnd)) { 7072 /* Old faces add new faces and vertex */ 7073 numLeavesNew += 1 + 2; 7074 } else if ((p >= cStart) && (p < cEnd)) { 7075 /* Old cells add new cells and interior faces */ 7076 numLeavesNew += 4 + 4; 7077 } 7078 break; 7079 default: 7080 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7081 } 7082 } 7083 /* Communicate depthSizes for each remote rank */ 7084 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7085 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7086 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7087 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); 7088 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7089 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7090 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7091 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7092 for (n = 0; n < numNeighbors; ++n) { 7093 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7094 } 7095 depthSizeOld[depth] = cMax; 7096 depthSizeOld[0] = vMax; 7097 depthSizeOld[depth-1] = fMax; 7098 depthSizeOld[1] = eMax; 7099 7100 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7101 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7102 7103 depthSizeOld[depth] = cEnd - cStart; 7104 depthSizeOld[0] = vEnd - vStart; 7105 depthSizeOld[depth-1] = fEnd - fStart; 7106 depthSizeOld[1] = eEnd - eStart; 7107 7108 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7109 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7110 for (n = 0; n < numNeighbors; ++n) { 7111 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7112 } 7113 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7114 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7115 /* Calculate new point SF */ 7116 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7117 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7118 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7119 for (l = 0, m = 0; l < numLeaves; ++l) { 7120 PetscInt p = localPoints[l]; 7121 PetscInt rp = remotePoints[l].index, n; 7122 PetscMPIInt rrank = remotePoints[l].rank; 7123 7124 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7125 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7126 switch (refiner) { 7127 case 1: 7128 /* Simplicial 2D */ 7129 if ((p >= vStart) && (p < vEnd)) { 7130 /* Old vertices stay the same */ 7131 localPointsNew[m] = vStartNew + (p - vStart); 7132 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7133 remotePointsNew[m].rank = rrank; 7134 ++m; 7135 } else if ((p >= fStart) && (p < fEnd)) { 7136 /* Old faces add new faces and vertex */ 7137 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7138 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7139 remotePointsNew[m].rank = rrank; 7140 ++m; 7141 for (r = 0; r < 2; ++r, ++m) { 7142 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7143 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7144 remotePointsNew[m].rank = rrank; 7145 } 7146 } else if ((p >= cStart) && (p < cEnd)) { 7147 /* Old cells add new cells and interior faces */ 7148 for (r = 0; r < 4; ++r, ++m) { 7149 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7150 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7151 remotePointsNew[m].rank = rrank; 7152 } 7153 for (r = 0; r < 3; ++r, ++m) { 7154 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7155 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7156 remotePointsNew[m].rank = rrank; 7157 } 7158 } 7159 break; 7160 case 2: 7161 /* Hex 2D */ 7162 if ((p >= vStart) && (p < vEnd)) { 7163 /* Old vertices stay the same */ 7164 localPointsNew[m] = vStartNew + (p - vStart); 7165 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7166 remotePointsNew[m].rank = rrank; 7167 ++m; 7168 } else if ((p >= fStart) && (p < fEnd)) { 7169 /* Old faces add new faces and vertex */ 7170 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7171 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7172 remotePointsNew[m].rank = rrank; 7173 ++m; 7174 for (r = 0; r < 2; ++r, ++m) { 7175 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7176 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7177 remotePointsNew[m].rank = rrank; 7178 } 7179 } else if ((p >= cStart) && (p < cEnd)) { 7180 /* Old cells add new cells and interior faces */ 7181 for (r = 0; r < 4; ++r, ++m) { 7182 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7183 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7184 remotePointsNew[m].rank = rrank; 7185 } 7186 for (r = 0; r < 4; ++r, ++m) { 7187 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7188 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7189 remotePointsNew[m].rank = rrank; 7190 } 7191 } 7192 break; 7193 case 3: 7194 /* Hybrid simplicial 2D */ 7195 if ((p >= vStart) && (p < vEnd)) { 7196 /* Old vertices stay the same */ 7197 localPointsNew[m] = vStartNew + (p - vStart); 7198 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7199 remotePointsNew[m].rank = rrank; 7200 ++m; 7201 } else if ((p >= fStart) && (p < fMax)) { 7202 /* Old interior faces add new faces and vertex */ 7203 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7204 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7205 remotePointsNew[m].rank = rrank; 7206 ++m; 7207 for (r = 0; r < 2; ++r, ++m) { 7208 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7209 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7210 remotePointsNew[m].rank = rrank; 7211 } 7212 } else if ((p >= fMax) && (p < fEnd)) { 7213 /* Old hybrid faces stay the same */ 7214 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7215 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7216 remotePointsNew[m].rank = rrank; 7217 ++m; 7218 } else if ((p >= cStart) && (p < cMax)) { 7219 /* Old interior cells add new cells and interior faces */ 7220 for (r = 0; r < 4; ++r, ++m) { 7221 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7222 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7223 remotePointsNew[m].rank = rrank; 7224 } 7225 for (r = 0; r < 3; ++r, ++m) { 7226 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7227 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7228 remotePointsNew[m].rank = rrank; 7229 } 7230 } else if ((p >= cStart) && (p < cMax)) { 7231 /* Old hybrid cells add new cells and hybrid face */ 7232 for (r = 0; r < 2; ++r, ++m) { 7233 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7234 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7235 remotePointsNew[m].rank = rrank; 7236 } 7237 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7238 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]); 7239 remotePointsNew[m].rank = rrank; 7240 ++m; 7241 } 7242 break; 7243 default: 7244 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7245 } 7246 } 7247 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7248 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7249 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7250 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7251 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7252 PetscFunctionReturn(0); 7253 } 7254 7255 #undef __FUNCT__ 7256 #define __FUNCT__ "CellRefinerCreateLabels" 7257 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7258 { 7259 PetscInt numLabels, l; 7260 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7261 PetscErrorCode ierr; 7262 7263 PetscFunctionBegin; 7264 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7265 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7266 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7267 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7268 7269 cStartNew = 0; 7270 vStartNew = depthSize[2]; 7271 fStartNew = depthSize[2] + depthSize[0]; 7272 7273 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7274 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7275 switch (refiner) { 7276 case 3: 7277 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7278 cMax = PetscMin(cEnd, cMax); 7279 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7280 fMax = PetscMin(fEnd, fMax); 7281 } 7282 for (l = 0; l < numLabels; ++l) { 7283 DMLabel label, labelNew; 7284 const char *lname; 7285 PetscBool isDepth; 7286 IS valueIS; 7287 const PetscInt *values; 7288 PetscInt numValues, val; 7289 7290 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7291 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7292 if (isDepth) continue; 7293 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7294 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7295 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7296 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7297 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7298 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7299 for (val = 0; val < numValues; ++val) { 7300 IS pointIS; 7301 const PetscInt *points; 7302 PetscInt numPoints, n; 7303 7304 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7305 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7306 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7307 for (n = 0; n < numPoints; ++n) { 7308 const PetscInt p = points[n]; 7309 switch (refiner) { 7310 case 1: 7311 /* Simplicial 2D */ 7312 if ((p >= vStart) && (p < vEnd)) { 7313 /* Old vertices stay the same */ 7314 newp = vStartNew + (p - vStart); 7315 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7316 } else if ((p >= fStart) && (p < fEnd)) { 7317 /* Old faces add new faces and vertex */ 7318 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7319 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7320 for (r = 0; r < 2; ++r) { 7321 newp = fStartNew + (p - fStart)*2 + r; 7322 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7323 } 7324 } else if ((p >= cStart) && (p < cEnd)) { 7325 /* Old cells add new cells and interior faces */ 7326 for (r = 0; r < 4; ++r) { 7327 newp = cStartNew + (p - cStart)*4 + r; 7328 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7329 } 7330 for (r = 0; r < 3; ++r) { 7331 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7332 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7333 } 7334 } 7335 break; 7336 case 2: 7337 /* Hex 2D */ 7338 if ((p >= vStart) && (p < vEnd)) { 7339 /* Old vertices stay the same */ 7340 newp = vStartNew + (p - vStart); 7341 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7342 } else if ((p >= fStart) && (p < fEnd)) { 7343 /* Old faces add new faces and vertex */ 7344 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7345 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7346 for (r = 0; r < 2; ++r) { 7347 newp = fStartNew + (p - fStart)*2 + r; 7348 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7349 } 7350 } else if ((p >= cStart) && (p < cEnd)) { 7351 /* Old cells add new cells and interior faces and vertex */ 7352 for (r = 0; r < 4; ++r) { 7353 newp = cStartNew + (p - cStart)*4 + r; 7354 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7355 } 7356 for (r = 0; r < 4; ++r) { 7357 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7358 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7359 } 7360 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7361 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7362 } 7363 break; 7364 case 3: 7365 /* Hybrid simplicial 2D */ 7366 if ((p >= vStart) && (p < vEnd)) { 7367 /* Old vertices stay the same */ 7368 newp = vStartNew + (p - vStart); 7369 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7370 } else if ((p >= fStart) && (p < fMax)) { 7371 /* Old interior faces add new faces and vertex */ 7372 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7373 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7374 for (r = 0; r < 2; ++r) { 7375 newp = fStartNew + (p - fStart)*2 + r; 7376 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7377 } 7378 } else if ((p >= fMax) && (p < fEnd)) { 7379 /* Old hybrid faces stay the same */ 7380 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7381 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7382 } else if ((p >= cStart) && (p < cMax)) { 7383 /* Old interior cells add new cells and interior faces */ 7384 for (r = 0; r < 4; ++r) { 7385 newp = cStartNew + (p - cStart)*4 + r; 7386 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7387 } 7388 for (r = 0; r < 3; ++r) { 7389 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7390 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7391 } 7392 } else if ((p >= cMax) && (p < cEnd)) { 7393 /* Old hybrid cells add new cells and hybrid face */ 7394 for (r = 0; r < 2; ++r) { 7395 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7396 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7397 } 7398 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7399 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7400 } 7401 break; 7402 default: 7403 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7404 } 7405 } 7406 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7407 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7408 } 7409 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7410 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7411 if (0) { 7412 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7413 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7414 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7415 } 7416 } 7417 PetscFunctionReturn(0); 7418 } 7419 7420 #undef __FUNCT__ 7421 #define __FUNCT__ "DMPlexRefine_Uniform" 7422 /* This will only work for interpolated meshes */ 7423 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7424 { 7425 DM rdm; 7426 PetscInt *depthSize; 7427 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7428 PetscErrorCode ierr; 7429 7430 PetscFunctionBegin; 7431 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7432 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7433 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7434 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7435 /* Calculate number of new points of each depth */ 7436 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7437 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7438 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7439 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7440 /* Step 1: Set chart */ 7441 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7442 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7443 /* Step 2: Set cone/support sizes */ 7444 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7445 /* Step 3: Setup refined DM */ 7446 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7447 /* Step 4: Set cones and supports */ 7448 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7449 /* Step 5: Stratify */ 7450 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7451 /* Step 6: Set coordinates for vertices */ 7452 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7453 /* Step 7: Create pointSF */ 7454 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7455 /* Step 8: Create labels */ 7456 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7457 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7458 7459 *dmRefined = rdm; 7460 PetscFunctionReturn(0); 7461 } 7462 7463 #undef __FUNCT__ 7464 #define __FUNCT__ "DMPlexSetRefinementUniform" 7465 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7466 { 7467 DM_Plex *mesh = (DM_Plex*) dm->data; 7468 7469 PetscFunctionBegin; 7470 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7471 mesh->refinementUniform = refinementUniform; 7472 PetscFunctionReturn(0); 7473 } 7474 7475 #undef __FUNCT__ 7476 #define __FUNCT__ "DMPlexGetRefinementUniform" 7477 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7478 { 7479 DM_Plex *mesh = (DM_Plex*) dm->data; 7480 7481 PetscFunctionBegin; 7482 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7483 PetscValidPointer(refinementUniform, 2); 7484 *refinementUniform = mesh->refinementUniform; 7485 PetscFunctionReturn(0); 7486 } 7487 7488 #undef __FUNCT__ 7489 #define __FUNCT__ "DMPlexSetRefinementLimit" 7490 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7491 { 7492 DM_Plex *mesh = (DM_Plex*) dm->data; 7493 7494 PetscFunctionBegin; 7495 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7496 mesh->refinementLimit = refinementLimit; 7497 PetscFunctionReturn(0); 7498 } 7499 7500 #undef __FUNCT__ 7501 #define __FUNCT__ "DMPlexGetRefinementLimit" 7502 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7503 { 7504 DM_Plex *mesh = (DM_Plex*) dm->data; 7505 7506 PetscFunctionBegin; 7507 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7508 PetscValidPointer(refinementLimit, 2); 7509 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7510 *refinementLimit = mesh->refinementLimit; 7511 PetscFunctionReturn(0); 7512 } 7513 7514 #undef __FUNCT__ 7515 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7516 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7517 { 7518 PetscInt dim, cStart, coneSize, cMax; 7519 PetscErrorCode ierr; 7520 7521 PetscFunctionBegin; 7522 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7523 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7524 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7525 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7526 switch (dim) { 7527 case 2: 7528 switch (coneSize) { 7529 case 3: 7530 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7531 else *cellRefiner = 1; /* Triangular */ 7532 break; 7533 case 4: 7534 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7535 else *cellRefiner = 2; /* Quadrilateral */ 7536 break; 7537 default: 7538 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7539 } 7540 break; 7541 default: 7542 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7543 } 7544 PetscFunctionReturn(0); 7545 } 7546 7547 #undef __FUNCT__ 7548 #define __FUNCT__ "DMRefine_Plex" 7549 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7550 { 7551 PetscReal refinementLimit; 7552 PetscInt dim, cStart, cEnd; 7553 char genname[1024], *name = NULL; 7554 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7555 PetscErrorCode ierr; 7556 7557 PetscFunctionBegin; 7558 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7559 if (isUniform) { 7560 CellRefiner cellRefiner; 7561 7562 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7563 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7564 PetscFunctionReturn(0); 7565 } 7566 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7567 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7568 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7569 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7570 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7571 if (flg) name = genname; 7572 if (name) { 7573 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7574 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7575 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7576 } 7577 switch (dim) { 7578 case 2: 7579 if (!name || isTriangle) { 7580 #if defined(PETSC_HAVE_TRIANGLE) 7581 double *maxVolumes; 7582 PetscInt c; 7583 7584 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7585 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7586 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7587 #else 7588 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7589 #endif 7590 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7591 break; 7592 case 3: 7593 if (!name || isCTetgen) { 7594 #if defined(PETSC_HAVE_CTETGEN) 7595 PetscReal *maxVolumes; 7596 PetscInt c; 7597 7598 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7599 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7600 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7601 #else 7602 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7603 #endif 7604 } else if (isTetgen) { 7605 #if defined(PETSC_HAVE_TETGEN) 7606 double *maxVolumes; 7607 PetscInt c; 7608 7609 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7610 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7611 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7612 #else 7613 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7614 #endif 7615 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7616 break; 7617 default: 7618 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7619 } 7620 PetscFunctionReturn(0); 7621 } 7622 7623 #undef __FUNCT__ 7624 #define __FUNCT__ "DMPlexGetDepth" 7625 /*@ 7626 DMPlexGetDepth - get the number of strata 7627 7628 Not Collective 7629 7630 Input Parameters: 7631 . dm - The DMPlex object 7632 7633 Output Parameters: 7634 . depth - number of strata 7635 7636 Level: developer 7637 7638 Notes: 7639 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7640 7641 .keywords: mesh, points 7642 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7643 @*/ 7644 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7645 { 7646 PetscInt d; 7647 PetscErrorCode ierr; 7648 7649 PetscFunctionBegin; 7650 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7651 PetscValidPointer(depth, 2); 7652 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7653 *depth = d-1; 7654 PetscFunctionReturn(0); 7655 } 7656 7657 #undef __FUNCT__ 7658 #define __FUNCT__ "DMPlexGetDepthStratum" 7659 /*@ 7660 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7661 7662 Not Collective 7663 7664 Input Parameters: 7665 + dm - The DMPlex object 7666 - stratumValue - The requested depth 7667 7668 Output Parameters: 7669 + start - The first point at this depth 7670 - end - One beyond the last point at this depth 7671 7672 Level: developer 7673 7674 .keywords: mesh, points 7675 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7676 @*/ 7677 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7678 { 7679 DM_Plex *mesh = (DM_Plex*) dm->data; 7680 DMLabel next = mesh->labels; 7681 PetscBool flg = PETSC_FALSE; 7682 PetscInt depth; 7683 PetscErrorCode ierr; 7684 7685 PetscFunctionBegin; 7686 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7687 if (stratumValue < 0) { 7688 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7689 PetscFunctionReturn(0); 7690 } else { 7691 PetscInt pStart, pEnd; 7692 7693 if (start) *start = 0; 7694 if (end) *end = 0; 7695 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7696 if (pStart == pEnd) PetscFunctionReturn(0); 7697 } 7698 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7699 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7700 /* We should have a generic GetLabel() and a Label class */ 7701 while (next) { 7702 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7703 if (flg) break; 7704 next = next->next; 7705 } 7706 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7707 depth = stratumValue; 7708 if ((depth < 0) || (depth >= next->numStrata)) { 7709 if (start) *start = 0; 7710 if (end) *end = 0; 7711 } else { 7712 if (start) *start = next->points[next->stratumOffsets[depth]]; 7713 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7714 } 7715 PetscFunctionReturn(0); 7716 } 7717 7718 #undef __FUNCT__ 7719 #define __FUNCT__ "DMPlexGetHeightStratum" 7720 /*@ 7721 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7722 7723 Not Collective 7724 7725 Input Parameters: 7726 + dm - The DMPlex object 7727 - stratumValue - The requested height 7728 7729 Output Parameters: 7730 + start - The first point at this height 7731 - end - One beyond the last point at this height 7732 7733 Level: developer 7734 7735 .keywords: mesh, points 7736 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7737 @*/ 7738 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7739 { 7740 DM_Plex *mesh = (DM_Plex*) dm->data; 7741 DMLabel next = mesh->labels; 7742 PetscBool flg = PETSC_FALSE; 7743 PetscInt depth; 7744 PetscErrorCode ierr; 7745 7746 PetscFunctionBegin; 7747 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7748 if (stratumValue < 0) { 7749 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7750 } else { 7751 PetscInt pStart, pEnd; 7752 7753 if (start) *start = 0; 7754 if (end) *end = 0; 7755 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7756 if (pStart == pEnd) PetscFunctionReturn(0); 7757 } 7758 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7759 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7760 /* We should have a generic GetLabel() and a Label class */ 7761 while (next) { 7762 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7763 if (flg) break; 7764 next = next->next; 7765 } 7766 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7767 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7768 if ((depth < 0) || (depth >= next->numStrata)) { 7769 if (start) *start = 0; 7770 if (end) *end = 0; 7771 } else { 7772 if (start) *start = next->points[next->stratumOffsets[depth]]; 7773 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7774 } 7775 PetscFunctionReturn(0); 7776 } 7777 7778 #undef __FUNCT__ 7779 #define __FUNCT__ "DMPlexCreateSectionInitial" 7780 /* Set the number of dof on each point and separate by fields */ 7781 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7782 { 7783 PetscInt *numDofTot; 7784 PetscInt pStart = 0, pEnd = 0; 7785 PetscInt p, d, f; 7786 PetscErrorCode ierr; 7787 7788 PetscFunctionBegin; 7789 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7790 for (d = 0; d <= dim; ++d) { 7791 numDofTot[d] = 0; 7792 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7793 } 7794 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7795 if (numFields > 0) { 7796 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7797 if (numComp) { 7798 for (f = 0; f < numFields; ++f) { 7799 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7800 } 7801 } 7802 } 7803 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7804 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7805 for (d = 0; d <= dim; ++d) { 7806 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7807 for (p = pStart; p < pEnd; ++p) { 7808 for (f = 0; f < numFields; ++f) { 7809 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7810 } 7811 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7812 } 7813 } 7814 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7815 PetscFunctionReturn(0); 7816 } 7817 7818 #undef __FUNCT__ 7819 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7820 /* Set the number of dof on each point and separate by fields 7821 If constDof is PETSC_DETERMINE, constrain every dof on the point 7822 */ 7823 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7824 { 7825 PetscInt numFields; 7826 PetscInt bc; 7827 PetscErrorCode ierr; 7828 7829 PetscFunctionBegin; 7830 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7831 for (bc = 0; bc < numBC; ++bc) { 7832 PetscInt field = 0; 7833 const PetscInt *idx; 7834 PetscInt n, i; 7835 7836 if (numFields) field = bcField[bc]; 7837 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7838 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7839 for (i = 0; i < n; ++i) { 7840 const PetscInt p = idx[i]; 7841 PetscInt numConst = constDof; 7842 7843 /* Constrain every dof on the point */ 7844 if (numConst < 0) { 7845 if (numFields) { 7846 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7847 } else { 7848 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7849 } 7850 } 7851 if (numFields) { 7852 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7853 } 7854 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7855 } 7856 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7857 } 7858 PetscFunctionReturn(0); 7859 } 7860 7861 #undef __FUNCT__ 7862 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7863 /* Set the constrained indices on each point and separate by fields */ 7864 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7865 { 7866 PetscInt *maxConstraints; 7867 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7868 PetscErrorCode ierr; 7869 7870 PetscFunctionBegin; 7871 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7872 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7873 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7874 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7875 for (p = pStart; p < pEnd; ++p) { 7876 PetscInt cdof; 7877 7878 if (numFields) { 7879 for (f = 0; f < numFields; ++f) { 7880 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7881 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7882 } 7883 } else { 7884 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7885 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7886 } 7887 } 7888 for (f = 0; f < numFields; ++f) { 7889 maxConstraints[numFields] += maxConstraints[f]; 7890 } 7891 if (maxConstraints[numFields]) { 7892 PetscInt *indices; 7893 7894 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7895 for (p = pStart; p < pEnd; ++p) { 7896 PetscInt cdof, d; 7897 7898 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7899 if (cdof) { 7900 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7901 if (numFields) { 7902 PetscInt numConst = 0, foff = 0; 7903 7904 for (f = 0; f < numFields; ++f) { 7905 PetscInt cfdof, fdof; 7906 7907 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7908 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7909 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7910 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7911 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7912 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7913 numConst += cfdof; 7914 foff += fdof; 7915 } 7916 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7917 } else { 7918 for (d = 0; d < cdof; ++d) indices[d] = d; 7919 } 7920 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7921 } 7922 } 7923 ierr = PetscFree(indices);CHKERRQ(ierr); 7924 } 7925 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7926 PetscFunctionReturn(0); 7927 } 7928 7929 #undef __FUNCT__ 7930 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7931 /* Set the constrained field indices on each point */ 7932 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7933 { 7934 const PetscInt *points, *indices; 7935 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7936 PetscErrorCode ierr; 7937 7938 PetscFunctionBegin; 7939 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7940 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7941 7942 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7943 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7944 if (!constraintIndices) { 7945 PetscInt *idx, i; 7946 7947 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7948 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7949 for (i = 0; i < maxDof; ++i) idx[i] = i; 7950 for (p = 0; p < numPoints; ++p) { 7951 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7952 } 7953 ierr = PetscFree(idx);CHKERRQ(ierr); 7954 } else { 7955 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7956 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7957 for (p = 0; p < numPoints; ++p) { 7958 PetscInt fcdof; 7959 7960 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7961 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); 7962 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7963 } 7964 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7965 } 7966 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7967 PetscFunctionReturn(0); 7968 } 7969 7970 #undef __FUNCT__ 7971 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7972 /* Set the constrained indices on each point and separate by fields */ 7973 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7974 { 7975 PetscInt *indices; 7976 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7977 PetscErrorCode ierr; 7978 7979 PetscFunctionBegin; 7980 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7981 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7982 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7983 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7984 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7985 for (p = pStart; p < pEnd; ++p) { 7986 PetscInt cdof, d; 7987 7988 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7989 if (cdof) { 7990 PetscInt numConst = 0, foff = 0; 7991 7992 for (f = 0; f < numFields; ++f) { 7993 const PetscInt *fcind; 7994 PetscInt fdof, fcdof; 7995 7996 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7997 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7998 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7999 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8000 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 8001 foff += fdof; 8002 numConst += fcdof; 8003 } 8004 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8005 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8006 } 8007 } 8008 ierr = PetscFree(indices);CHKERRQ(ierr); 8009 PetscFunctionReturn(0); 8010 } 8011 8012 #undef __FUNCT__ 8013 #define __FUNCT__ "DMPlexCreateSection" 8014 /*@C 8015 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8016 8017 Not Collective 8018 8019 Input Parameters: 8020 + dm - The DMPlex object 8021 . dim - The spatial dimension of the problem 8022 . numFields - The number of fields in the problem 8023 . numComp - An array of size numFields that holds the number of components for each field 8024 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8025 . numBC - The number of boundary conditions 8026 . bcField - An array of size numBC giving the field number for each boundry condition 8027 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8028 8029 Output Parameter: 8030 . section - The PetscSection object 8031 8032 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 8033 nubmer of dof for field 0 on each edge. 8034 8035 Level: developer 8036 8037 .keywords: mesh, elements 8038 .seealso: DMPlexCreate(), PetscSectionCreate() 8039 @*/ 8040 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8041 { 8042 PetscErrorCode ierr; 8043 8044 PetscFunctionBegin; 8045 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8046 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8047 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8048 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8049 { 8050 PetscBool view = PETSC_FALSE; 8051 8052 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8053 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8054 } 8055 PetscFunctionReturn(0); 8056 } 8057 8058 #undef __FUNCT__ 8059 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8060 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8061 { 8062 PetscSection section; 8063 PetscErrorCode ierr; 8064 8065 PetscFunctionBegin; 8066 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8067 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8068 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8069 PetscFunctionReturn(0); 8070 } 8071 8072 #undef __FUNCT__ 8073 #define __FUNCT__ "DMPlexGetCoordinateSection" 8074 /*@ 8075 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8076 8077 Not Collective 8078 8079 Input Parameter: 8080 . dm - The DMPlex object 8081 8082 Output Parameter: 8083 . section - The PetscSection object 8084 8085 Level: intermediate 8086 8087 .keywords: mesh, coordinates 8088 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8089 @*/ 8090 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8091 { 8092 DM cdm; 8093 PetscErrorCode ierr; 8094 8095 PetscFunctionBegin; 8096 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8097 PetscValidPointer(section, 2); 8098 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8099 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8100 PetscFunctionReturn(0); 8101 } 8102 8103 #undef __FUNCT__ 8104 #define __FUNCT__ "DMPlexSetCoordinateSection" 8105 /*@ 8106 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8107 8108 Not Collective 8109 8110 Input Parameters: 8111 + dm - The DMPlex object 8112 - section - The PetscSection object 8113 8114 Level: intermediate 8115 8116 .keywords: mesh, coordinates 8117 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8118 @*/ 8119 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8120 { 8121 DM cdm; 8122 PetscErrorCode ierr; 8123 8124 PetscFunctionBegin; 8125 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8126 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8127 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8128 PetscFunctionReturn(0); 8129 } 8130 8131 #undef __FUNCT__ 8132 #define __FUNCT__ "DMPlexGetConeSection" 8133 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8134 { 8135 DM_Plex *mesh = (DM_Plex*) dm->data; 8136 8137 PetscFunctionBegin; 8138 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8139 if (section) *section = mesh->coneSection; 8140 PetscFunctionReturn(0); 8141 } 8142 8143 #undef __FUNCT__ 8144 #define __FUNCT__ "DMPlexGetCones" 8145 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8146 { 8147 DM_Plex *mesh = (DM_Plex*) dm->data; 8148 8149 PetscFunctionBegin; 8150 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8151 if (cones) *cones = mesh->cones; 8152 PetscFunctionReturn(0); 8153 } 8154 8155 #undef __FUNCT__ 8156 #define __FUNCT__ "DMPlexGetConeOrientations" 8157 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8158 { 8159 DM_Plex *mesh = (DM_Plex*) dm->data; 8160 8161 PetscFunctionBegin; 8162 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8163 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8164 PetscFunctionReturn(0); 8165 } 8166 8167 #undef __FUNCT__ 8168 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8169 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8170 { 8171 const PetscInt embedDim = 2; 8172 PetscReal x = PetscRealPart(point[0]); 8173 PetscReal y = PetscRealPart(point[1]); 8174 PetscReal v0[2], J[4], invJ[4], detJ; 8175 PetscReal xi, eta; 8176 PetscErrorCode ierr; 8177 8178 PetscFunctionBegin; 8179 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8180 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8181 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8182 8183 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8184 else *cell = -1; 8185 PetscFunctionReturn(0); 8186 } 8187 8188 #undef __FUNCT__ 8189 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8190 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8191 { 8192 PetscSection coordSection; 8193 Vec coordsLocal; 8194 const PetscScalar *coords; 8195 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8196 PetscReal x = PetscRealPart(point[0]); 8197 PetscReal y = PetscRealPart(point[1]); 8198 PetscInt crossings = 0, f; 8199 PetscErrorCode ierr; 8200 8201 PetscFunctionBegin; 8202 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8203 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8204 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8205 for (f = 0; f < 4; ++f) { 8206 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8207 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8208 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8209 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8210 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8211 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8212 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8213 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8214 if ((cond1 || cond2) && above) ++crossings; 8215 } 8216 if (crossings % 2) *cell = c; 8217 else *cell = -1; 8218 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8219 PetscFunctionReturn(0); 8220 } 8221 8222 #undef __FUNCT__ 8223 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8224 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8225 { 8226 const PetscInt embedDim = 3; 8227 PetscReal v0[3], J[9], invJ[9], detJ; 8228 PetscReal x = PetscRealPart(point[0]); 8229 PetscReal y = PetscRealPart(point[1]); 8230 PetscReal z = PetscRealPart(point[2]); 8231 PetscReal xi, eta, zeta; 8232 PetscErrorCode ierr; 8233 8234 PetscFunctionBegin; 8235 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8236 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8237 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8238 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8239 8240 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8241 else *cell = -1; 8242 PetscFunctionReturn(0); 8243 } 8244 8245 #undef __FUNCT__ 8246 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8247 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8248 { 8249 PetscSection coordSection; 8250 Vec coordsLocal; 8251 const PetscScalar *coords; 8252 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8253 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8254 PetscBool found = PETSC_TRUE; 8255 PetscInt f; 8256 PetscErrorCode ierr; 8257 8258 PetscFunctionBegin; 8259 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8260 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8261 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8262 for (f = 0; f < 6; ++f) { 8263 /* Check the point is under plane */ 8264 /* Get face normal */ 8265 PetscReal v_i[3]; 8266 PetscReal v_j[3]; 8267 PetscReal normal[3]; 8268 PetscReal pp[3]; 8269 PetscReal dot; 8270 8271 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8272 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8273 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8274 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8275 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8276 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8277 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8278 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8279 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8280 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8281 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8282 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8283 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8284 8285 /* Check that projected point is in face (2D location problem) */ 8286 if (dot < 0.0) { 8287 found = PETSC_FALSE; 8288 break; 8289 } 8290 } 8291 if (found) *cell = c; 8292 else *cell = -1; 8293 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 8294 PetscFunctionReturn(0); 8295 } 8296 8297 #undef __FUNCT__ 8298 #define __FUNCT__ "DMLocatePoints_Plex" 8299 /* 8300 Need to implement using the guess 8301 */ 8302 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8303 { 8304 PetscInt cell = -1 /*, guess = -1*/; 8305 PetscInt bs, numPoints, p; 8306 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8307 PetscInt *cells; 8308 PetscScalar *a; 8309 PetscErrorCode ierr; 8310 8311 PetscFunctionBegin; 8312 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8313 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8314 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 8315 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8316 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8317 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8318 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8319 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); 8320 numPoints /= bs; 8321 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8322 for (p = 0; p < numPoints; ++p) { 8323 const PetscScalar *point = &a[p*bs]; 8324 8325 switch (dim) { 8326 case 2: 8327 for (c = cStart; c < cEnd; ++c) { 8328 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8329 switch (coneSize) { 8330 case 3: 8331 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8332 break; 8333 case 4: 8334 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8335 break; 8336 default: 8337 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8338 } 8339 if (cell >= 0) break; 8340 } 8341 break; 8342 case 3: 8343 for (c = cStart; c < cEnd; ++c) { 8344 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8345 switch (coneSize) { 8346 case 4: 8347 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8348 break; 8349 case 8: 8350 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8351 break; 8352 default: 8353 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8354 } 8355 if (cell >= 0) break; 8356 } 8357 break; 8358 default: 8359 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8360 } 8361 cells[p] = cell; 8362 } 8363 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8364 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8365 PetscFunctionReturn(0); 8366 } 8367 8368 /******************************** FEM Support **********************************/ 8369 8370 #undef __FUNCT__ 8371 #define __FUNCT__ "DMPlexVecGetClosure" 8372 /*@C 8373 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8374 8375 Not collective 8376 8377 Input Parameters: 8378 + dm - The DM 8379 . section - The section describing the layout in v, or NULL to use the default section 8380 . v - The local vector 8381 - point - The sieve point in the DM 8382 8383 Output Parameters: 8384 + csize - The number of values in the closure, or NULL 8385 - values - The array of values, which is a borrowed array and should not be freed 8386 8387 Level: intermediate 8388 8389 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8390 @*/ 8391 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8392 { 8393 PetscScalar *array, *vArray; 8394 PetscInt *points = NULL; 8395 PetscInt offsets[32]; 8396 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8397 PetscErrorCode ierr; 8398 8399 PetscFunctionBegin; 8400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8401 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8402 if (!section) { 8403 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8404 } 8405 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8406 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8407 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8408 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8409 /* Compress out points not in the section */ 8410 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8411 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8412 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8413 points[q*2] = points[p]; 8414 points[q*2+1] = points[p+1]; 8415 ++q; 8416 } 8417 } 8418 numPoints = q; 8419 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8420 PetscInt dof, fdof; 8421 8422 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8423 for (f = 0; f < numFields; ++f) { 8424 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8425 offsets[f+1] += fdof; 8426 } 8427 size += dof; 8428 } 8429 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8430 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8431 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8432 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8433 for (p = 0; p < numPoints*2; p += 2) { 8434 PetscInt o = points[p+1]; 8435 PetscInt dof, off, d; 8436 PetscScalar *varr; 8437 8438 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8439 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8440 varr = &vArray[off]; 8441 if (numFields) { 8442 PetscInt fdof, foff, fcomp, f, c; 8443 8444 for (f = 0, foff = 0; f < numFields; ++f) { 8445 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8446 if (o >= 0) { 8447 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8448 array[offsets[f]] = varr[foff+d]; 8449 } 8450 } else { 8451 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8452 for (d = fdof/fcomp-1; d >= 0; --d) { 8453 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8454 array[offsets[f]] = varr[foff+d*fcomp+c]; 8455 } 8456 } 8457 } 8458 foff += fdof; 8459 } 8460 } else { 8461 if (o >= 0) { 8462 for (d = 0; d < dof; ++d, ++offsets[0]) { 8463 array[offsets[0]] = varr[d]; 8464 } 8465 } else { 8466 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8467 array[offsets[0]] = varr[d]; 8468 } 8469 } 8470 } 8471 } 8472 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8473 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8474 if (csize) *csize = size; 8475 *values = array; 8476 PetscFunctionReturn(0); 8477 } 8478 8479 #undef __FUNCT__ 8480 #define __FUNCT__ "DMPlexVecRestoreClosure" 8481 /*@C 8482 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8483 8484 Not collective 8485 8486 Input Parameters: 8487 + dm - The DM 8488 . section - The section describing the layout in v, or NULL to use the default section 8489 . v - The local vector 8490 . point - The sieve point in the DM 8491 . csize - The number of values in the closure, or NULL 8492 - values - The array of values, which is a borrowed array and should not be freed 8493 8494 Level: intermediate 8495 8496 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8497 @*/ 8498 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8499 { 8500 PetscInt size = 0; 8501 PetscErrorCode ierr; 8502 8503 PetscFunctionBegin; 8504 /* Should work without recalculating size */ 8505 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8506 PetscFunctionReturn(0); 8507 } 8508 8509 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8510 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8511 8512 #undef __FUNCT__ 8513 #define __FUNCT__ "updatePoint_private" 8514 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8515 { 8516 PetscInt cdof; /* The number of constraints on this point */ 8517 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8518 PetscScalar *a; 8519 PetscInt off, cind = 0, k; 8520 PetscErrorCode ierr; 8521 8522 PetscFunctionBegin; 8523 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8524 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8525 a = &array[off]; 8526 if (!cdof || setBC) { 8527 if (orientation >= 0) { 8528 for (k = 0; k < dof; ++k) { 8529 fuse(&a[k], values[k]); 8530 } 8531 } else { 8532 for (k = 0; k < dof; ++k) { 8533 fuse(&a[k], values[dof-k-1]); 8534 } 8535 } 8536 } else { 8537 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8538 if (orientation >= 0) { 8539 for (k = 0; k < dof; ++k) { 8540 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8541 fuse(&a[k], values[k]); 8542 } 8543 } else { 8544 for (k = 0; k < dof; ++k) { 8545 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8546 fuse(&a[k], values[dof-k-1]); 8547 } 8548 } 8549 } 8550 PetscFunctionReturn(0); 8551 } 8552 8553 #undef __FUNCT__ 8554 #define __FUNCT__ "updatePointFields_private" 8555 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8556 { 8557 PetscScalar *a; 8558 PetscInt numFields, off, foff, f; 8559 PetscErrorCode ierr; 8560 8561 PetscFunctionBegin; 8562 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8563 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8564 a = &array[off]; 8565 for (f = 0, foff = 0; f < numFields; ++f) { 8566 PetscInt fdof, fcomp, fcdof; 8567 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8568 PetscInt cind = 0, k, c; 8569 8570 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8571 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8572 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8573 if (!fcdof || setBC) { 8574 if (orientation >= 0) { 8575 for (k = 0; k < fdof; ++k) { 8576 fuse(&a[foff+k], values[foffs[f]+k]); 8577 } 8578 } else { 8579 for (k = fdof/fcomp-1; k >= 0; --k) { 8580 for (c = 0; c < fcomp; ++c) { 8581 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8582 } 8583 } 8584 } 8585 } else { 8586 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8587 if (orientation >= 0) { 8588 for (k = 0; k < fdof; ++k) { 8589 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8590 fuse(&a[foff+k], values[foffs[f]+k]); 8591 } 8592 } else { 8593 for (k = fdof/fcomp-1; k >= 0; --k) { 8594 for (c = 0; c < fcomp; ++c) { 8595 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8596 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8597 } 8598 } 8599 } 8600 } 8601 foff += fdof; 8602 foffs[f] += fdof; 8603 } 8604 PetscFunctionReturn(0); 8605 } 8606 8607 #undef __FUNCT__ 8608 #define __FUNCT__ "DMPlexVecSetClosure" 8609 /*@C 8610 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8611 8612 Not collective 8613 8614 Input Parameters: 8615 + dm - The DM 8616 . section - The section describing the layout in v, or NULL to use the default sectionw 8617 . v - The local vector 8618 . point - The sieve point in the DM 8619 . values - The array of values, which is a borrowed array and should not be freed 8620 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8621 8622 Level: intermediate 8623 8624 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8625 @*/ 8626 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8627 { 8628 PetscScalar *array; 8629 PetscInt *points = NULL; 8630 PetscInt offsets[32]; 8631 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8632 PetscErrorCode ierr; 8633 8634 PetscFunctionBegin; 8635 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8636 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8637 if (!section) { 8638 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8639 } 8640 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8641 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8642 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8643 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8644 /* Compress out points not in the section */ 8645 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8646 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8647 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8648 points[q*2] = points[p]; 8649 points[q*2+1] = points[p+1]; 8650 ++q; 8651 } 8652 } 8653 numPoints = q; 8654 for (p = 0; p < numPoints*2; p += 2) { 8655 PetscInt fdof; 8656 8657 for (f = 0; f < numFields; ++f) { 8658 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8659 offsets[f+1] += fdof; 8660 } 8661 } 8662 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8663 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8664 if (numFields) { 8665 switch (mode) { 8666 case INSERT_VALUES: 8667 for (p = 0; p < numPoints*2; p += 2) { 8668 PetscInt o = points[p+1]; 8669 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8670 } break; 8671 case INSERT_ALL_VALUES: 8672 for (p = 0; p < numPoints*2; p += 2) { 8673 PetscInt o = points[p+1]; 8674 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8675 } break; 8676 case ADD_VALUES: 8677 for (p = 0; p < numPoints*2; p += 2) { 8678 PetscInt o = points[p+1]; 8679 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8680 } break; 8681 case ADD_ALL_VALUES: 8682 for (p = 0; p < numPoints*2; p += 2) { 8683 PetscInt o = points[p+1]; 8684 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8685 } break; 8686 default: 8687 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8688 } 8689 } else { 8690 switch (mode) { 8691 case INSERT_VALUES: 8692 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8693 PetscInt o = points[p+1]; 8694 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8695 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8696 } break; 8697 case INSERT_ALL_VALUES: 8698 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8699 PetscInt o = points[p+1]; 8700 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8701 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8702 } break; 8703 case ADD_VALUES: 8704 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8705 PetscInt o = points[p+1]; 8706 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8707 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8708 } break; 8709 case ADD_ALL_VALUES: 8710 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8711 PetscInt o = points[p+1]; 8712 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8713 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8714 } break; 8715 default: 8716 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8717 } 8718 } 8719 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8720 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8721 PetscFunctionReturn(0); 8722 } 8723 8724 #undef __FUNCT__ 8725 #define __FUNCT__ "DMPlexPrintMatSetValues" 8726 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8727 { 8728 PetscMPIInt rank; 8729 PetscInt i, j; 8730 PetscErrorCode ierr; 8731 8732 PetscFunctionBegin; 8733 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8734 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8735 for (i = 0; i < numIndices; i++) { 8736 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8737 } 8738 for (i = 0; i < numIndices; i++) { 8739 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8740 for (j = 0; j < numIndices; j++) { 8741 #if defined(PETSC_USE_COMPLEX) 8742 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8743 #else 8744 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8745 #endif 8746 } 8747 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8748 } 8749 PetscFunctionReturn(0); 8750 } 8751 8752 #undef __FUNCT__ 8753 #define __FUNCT__ "indicesPoint_private" 8754 /* . off - The global offset of this point */ 8755 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8756 { 8757 PetscInt dof; /* The number of unknowns on this point */ 8758 PetscInt cdof; /* The number of constraints on this point */ 8759 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8760 PetscInt cind = 0, k; 8761 PetscErrorCode ierr; 8762 8763 PetscFunctionBegin; 8764 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8765 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8766 if (!cdof || setBC) { 8767 if (orientation >= 0) { 8768 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8769 } else { 8770 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8771 } 8772 } else { 8773 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8774 if (orientation >= 0) { 8775 for (k = 0; k < dof; ++k) { 8776 if ((cind < cdof) && (k == cdofs[cind])) { 8777 /* Insert check for returning constrained indices */ 8778 indices[*loff+k] = -(off+k+1); 8779 ++cind; 8780 } else { 8781 indices[*loff+k] = off+k-cind; 8782 } 8783 } 8784 } else { 8785 for (k = 0; k < dof; ++k) { 8786 if ((cind < cdof) && (k == cdofs[cind])) { 8787 /* Insert check for returning constrained indices */ 8788 indices[*loff+dof-k-1] = -(off+k+1); 8789 ++cind; 8790 } else { 8791 indices[*loff+dof-k-1] = off+k-cind; 8792 } 8793 } 8794 } 8795 } 8796 *loff += dof; 8797 PetscFunctionReturn(0); 8798 } 8799 8800 #undef __FUNCT__ 8801 #define __FUNCT__ "indicesPointFields_private" 8802 /* . off - The global offset of this point */ 8803 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8804 { 8805 PetscInt numFields, foff, f; 8806 PetscErrorCode ierr; 8807 8808 PetscFunctionBegin; 8809 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8810 for (f = 0, foff = 0; f < numFields; ++f) { 8811 PetscInt fdof, fcomp, cfdof; 8812 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8813 PetscInt cind = 0, k, c; 8814 8815 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8816 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8817 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8818 if (!cfdof || setBC) { 8819 if (orientation >= 0) { 8820 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8821 } else { 8822 for (k = fdof/fcomp-1; k >= 0; --k) { 8823 for (c = 0; c < fcomp; ++c) { 8824 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8825 } 8826 } 8827 } 8828 } else { 8829 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8830 if (orientation >= 0) { 8831 for (k = 0; k < fdof; ++k) { 8832 if ((cind < cfdof) && (k == fcdofs[cind])) { 8833 indices[foffs[f]+k] = -(off+foff+k+1); 8834 ++cind; 8835 } else { 8836 indices[foffs[f]+k] = off+foff+k-cind; 8837 } 8838 } 8839 } else { 8840 for (k = fdof/fcomp-1; k >= 0; --k) { 8841 for (c = 0; c < fcomp; ++c) { 8842 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8843 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8844 ++cind; 8845 } else { 8846 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8847 } 8848 } 8849 } 8850 } 8851 } 8852 foff += fdof - cfdof; 8853 foffs[f] += fdof; 8854 } 8855 PetscFunctionReturn(0); 8856 } 8857 8858 #undef __FUNCT__ 8859 #define __FUNCT__ "DMPlexMatSetClosure" 8860 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8861 { 8862 DM_Plex *mesh = (DM_Plex*) dm->data; 8863 PetscInt *points = NULL; 8864 PetscInt *indices; 8865 PetscInt offsets[32]; 8866 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8867 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8868 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8869 PetscErrorCode ierr; 8870 8871 PetscFunctionBegin; 8872 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8873 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8874 if (useDefault) { 8875 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8876 } 8877 if (useGlobalDefault) { 8878 if (useDefault) { 8879 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8880 } else { 8881 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8882 } 8883 } 8884 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8885 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8886 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8887 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8888 /* Compress out points not in the section */ 8889 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8890 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8891 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8892 points[q*2] = points[p]; 8893 points[q*2+1] = points[p+1]; 8894 ++q; 8895 } 8896 } 8897 numPoints = q; 8898 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8899 PetscInt fdof; 8900 8901 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8902 for (f = 0; f < numFields; ++f) { 8903 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8904 offsets[f+1] += fdof; 8905 } 8906 numIndices += dof; 8907 } 8908 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8909 8910 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8911 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8912 if (numFields) { 8913 for (p = 0; p < numPoints*2; p += 2) { 8914 PetscInt o = points[p+1]; 8915 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8916 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8917 } 8918 } else { 8919 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8920 PetscInt o = points[p+1]; 8921 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8922 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8923 } 8924 } 8925 if (useGlobalDefault && !useDefault) { 8926 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8927 } 8928 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8929 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8930 if (ierr) { 8931 PetscMPIInt rank; 8932 PetscErrorCode ierr2; 8933 8934 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8935 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8936 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8937 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8938 CHKERRQ(ierr); 8939 } 8940 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8941 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8942 PetscFunctionReturn(0); 8943 } 8944 8945 #undef __FUNCT__ 8946 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8947 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8948 { 8949 PetscSection coordSection; 8950 Vec coordinates; 8951 const PetscScalar *coords; 8952 const PetscInt dim = 2; 8953 PetscInt d, f; 8954 PetscErrorCode ierr; 8955 8956 PetscFunctionBegin; 8957 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8958 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8959 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8960 if (v0) { 8961 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8962 } 8963 if (J) { 8964 for (d = 0; d < dim; d++) { 8965 for (f = 0; f < dim; f++) { 8966 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8967 } 8968 } 8969 *detJ = J[0]*J[3] - J[1]*J[2]; 8970 #if 0 8971 if (detJ < 0.0) { 8972 const PetscReal xLength = mesh->periodicity[0]; 8973 8974 if (xLength != 0.0) { 8975 PetscReal v0x = coords[0*dim+0]; 8976 8977 if (v0x == 0.0) v0x = v0[0] = xLength; 8978 for (f = 0; f < dim; f++) { 8979 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8980 8981 J[0*dim+f] = 0.5*(px - v0x); 8982 } 8983 } 8984 detJ = J[0]*J[3] - J[1]*J[2]; 8985 } 8986 #endif 8987 PetscLogFlops(8.0 + 3.0); 8988 } 8989 if (invJ) { 8990 const PetscReal invDet = 1.0/(*detJ); 8991 8992 invJ[0] = invDet*J[3]; 8993 invJ[1] = -invDet*J[1]; 8994 invJ[2] = -invDet*J[2]; 8995 invJ[3] = invDet*J[0]; 8996 PetscLogFlops(5.0); 8997 } 8998 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8999 PetscFunctionReturn(0); 9000 } 9001 9002 #undef __FUNCT__ 9003 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9004 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9005 { 9006 PetscSection coordSection; 9007 Vec coordinates; 9008 const PetscScalar *coords; 9009 const PetscInt dim = 2; 9010 PetscInt d, f; 9011 PetscErrorCode ierr; 9012 9013 PetscFunctionBegin; 9014 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9015 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9016 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9017 if (v0) { 9018 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9019 } 9020 if (J) { 9021 for (d = 0; d < dim; d++) { 9022 for (f = 0; f < dim; f++) { 9023 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9024 } 9025 } 9026 *detJ = J[0]*J[3] - J[1]*J[2]; 9027 PetscLogFlops(8.0 + 3.0); 9028 } 9029 if (invJ) { 9030 const PetscReal invDet = 1.0/(*detJ); 9031 9032 invJ[0] = invDet*J[3]; 9033 invJ[1] = -invDet*J[1]; 9034 invJ[2] = -invDet*J[2]; 9035 invJ[3] = invDet*J[0]; 9036 PetscLogFlops(5.0); 9037 } 9038 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9039 PetscFunctionReturn(0); 9040 } 9041 9042 #undef __FUNCT__ 9043 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9044 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9045 { 9046 PetscSection coordSection; 9047 Vec coordinates; 9048 const PetscScalar *coords; 9049 const PetscInt dim = 3; 9050 PetscInt d, f; 9051 PetscErrorCode ierr; 9052 9053 PetscFunctionBegin; 9054 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9055 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9056 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9057 if (v0) { 9058 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9059 } 9060 if (J) { 9061 for (d = 0; d < dim; d++) { 9062 for (f = 0; f < dim; f++) { 9063 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9064 } 9065 } 9066 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9067 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9068 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9069 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9070 PetscLogFlops(18.0 + 12.0); 9071 } 9072 if (invJ) { 9073 const PetscReal invDet = 1.0/(*detJ); 9074 9075 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9076 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9077 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9078 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9079 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9080 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9081 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9082 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9083 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9084 PetscLogFlops(37.0); 9085 } 9086 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9087 PetscFunctionReturn(0); 9088 } 9089 9090 #undef __FUNCT__ 9091 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9092 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9093 { 9094 PetscSection coordSection; 9095 Vec coordinates; 9096 const PetscScalar *coords; 9097 const PetscInt dim = 3; 9098 PetscInt d; 9099 PetscErrorCode ierr; 9100 9101 PetscFunctionBegin; 9102 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9103 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9104 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9105 if (v0) { 9106 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9107 } 9108 if (J) { 9109 for (d = 0; d < dim; d++) { 9110 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9111 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9112 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9113 } 9114 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9115 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9116 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9117 PetscLogFlops(18.0 + 12.0); 9118 } 9119 if (invJ) { 9120 const PetscReal invDet = -1.0/(*detJ); 9121 9122 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9123 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9124 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9125 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9126 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9127 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9128 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9129 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9130 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9131 PetscLogFlops(37.0); 9132 } 9133 *detJ *= 8.0; 9134 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 9135 PetscFunctionReturn(0); 9136 } 9137 9138 #undef __FUNCT__ 9139 #define __FUNCT__ "DMPlexComputeCellGeometry" 9140 /*@C 9141 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9142 9143 Collective on DM 9144 9145 Input Arguments: 9146 + dm - the DM 9147 - cell - the cell 9148 9149 Output Arguments: 9150 + v0 - the translation part of this affine transform 9151 . J - the Jacobian of the transform to the reference element 9152 . invJ - the inverse of the Jacobian 9153 - detJ - the Jacobian determinant 9154 9155 Level: advanced 9156 9157 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9158 @*/ 9159 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9160 { 9161 PetscInt dim, coneSize; 9162 PetscErrorCode ierr; 9163 9164 PetscFunctionBegin; 9165 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9166 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9167 switch (dim) { 9168 case 2: 9169 switch (coneSize) { 9170 case 3: 9171 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9172 break; 9173 case 4: 9174 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9175 break; 9176 default: 9177 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9178 } 9179 break; 9180 case 3: 9181 switch (coneSize) { 9182 case 4: 9183 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9184 break; 9185 case 8: 9186 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9187 break; 9188 default: 9189 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9190 } 9191 break; 9192 default: 9193 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9194 } 9195 PetscFunctionReturn(0); 9196 } 9197 9198 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9199 { 9200 switch (i) { 9201 case 0: 9202 switch (j) { 9203 case 0: return 0; 9204 case 1: 9205 switch (k) { 9206 case 0: return 0; 9207 case 1: return 0; 9208 case 2: return 1; 9209 } 9210 case 2: 9211 switch (k) { 9212 case 0: return 0; 9213 case 1: return -1; 9214 case 2: return 0; 9215 } 9216 } 9217 case 1: 9218 switch (j) { 9219 case 0: 9220 switch (k) { 9221 case 0: return 0; 9222 case 1: return 0; 9223 case 2: return -1; 9224 } 9225 case 1: return 0; 9226 case 2: 9227 switch (k) { 9228 case 0: return 1; 9229 case 1: return 0; 9230 case 2: return 0; 9231 } 9232 } 9233 case 2: 9234 switch (j) { 9235 case 0: 9236 switch (k) { 9237 case 0: return 0; 9238 case 1: return 1; 9239 case 2: return 0; 9240 } 9241 case 1: 9242 switch (k) { 9243 case 0: return -1; 9244 case 1: return 0; 9245 case 2: return 0; 9246 } 9247 case 2: return 0; 9248 } 9249 } 9250 return 0; 9251 } 9252 9253 #undef __FUNCT__ 9254 #define __FUNCT__ "DMPlexCreateRigidBody" 9255 /*@C 9256 DMPlexCreateRigidBody - create rigid body modes from coordinates 9257 9258 Collective on DM 9259 9260 Input Arguments: 9261 + dm - the DM 9262 . section - the local section associated with the rigid field, or NULL for the default section 9263 - globalSection - the global section associated with the rigid field, or NULL for the default section 9264 9265 Output Argument: 9266 . sp - the null space 9267 9268 Note: This is necessary to take account of Dirichlet conditions on the displacements 9269 9270 Level: advanced 9271 9272 .seealso: MatNullSpaceCreate() 9273 @*/ 9274 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9275 { 9276 MPI_Comm comm = ((PetscObject) dm)->comm; 9277 Vec coordinates, localMode, mode[6]; 9278 PetscSection coordSection; 9279 PetscScalar *coords; 9280 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9281 PetscErrorCode ierr; 9282 9283 PetscFunctionBegin; 9284 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9285 if (dim == 1) { 9286 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 9287 PetscFunctionReturn(0); 9288 } 9289 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9290 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9291 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9292 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9293 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9294 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9295 m = (dim*(dim+1))/2; 9296 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9297 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9298 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9299 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9300 /* Assume P1 */ 9301 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9302 for (d = 0; d < dim; ++d) { 9303 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9304 9305 values[d] = 1.0; 9306 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9307 for (v = vStart; v < vEnd; ++v) { 9308 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9309 } 9310 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9311 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9312 } 9313 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9314 for (d = dim; d < dim*(dim+1)/2; ++d) { 9315 PetscInt i, j, k = dim > 2 ? d - dim : d; 9316 9317 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9318 for (v = vStart; v < vEnd; ++v) { 9319 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9320 PetscInt off; 9321 9322 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9323 for (i = 0; i < dim; ++i) { 9324 for (j = 0; j < dim; ++j) { 9325 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9326 } 9327 } 9328 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9329 } 9330 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9331 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9332 } 9333 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9334 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9335 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 9336 /* Orthonormalize system */ 9337 for (i = dim; i < m; ++i) { 9338 PetscScalar dots[6]; 9339 9340 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9341 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9342 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9343 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 9344 } 9345 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9346 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9347 PetscFunctionReturn(0); 9348 } 9349 9350 #undef __FUNCT__ 9351 #define __FUNCT__ "DMPlexGetHybridBounds" 9352 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9353 { 9354 DM_Plex *mesh = (DM_Plex*) dm->data; 9355 PetscInt dim; 9356 PetscErrorCode ierr; 9357 9358 PetscFunctionBegin; 9359 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9360 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9361 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9362 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9363 if (eMax) *eMax = mesh->hybridPointMax[1]; 9364 if (vMax) *vMax = mesh->hybridPointMax[0]; 9365 PetscFunctionReturn(0); 9366 } 9367 9368 #undef __FUNCT__ 9369 #define __FUNCT__ "DMPlexSetHybridBounds" 9370 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9371 { 9372 DM_Plex *mesh = (DM_Plex*) dm->data; 9373 PetscInt dim; 9374 PetscErrorCode ierr; 9375 9376 PetscFunctionBegin; 9377 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9378 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9379 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9380 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9381 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9382 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9383 PetscFunctionReturn(0); 9384 } 9385 9386 #undef __FUNCT__ 9387 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9388 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9389 { 9390 DM_Plex *mesh = (DM_Plex*) dm->data; 9391 9392 PetscFunctionBegin; 9393 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9394 PetscValidPointer(cellHeight, 2); 9395 *cellHeight = mesh->vtkCellHeight; 9396 PetscFunctionReturn(0); 9397 } 9398 9399 #undef __FUNCT__ 9400 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9401 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9402 { 9403 DM_Plex *mesh = (DM_Plex*) dm->data; 9404 9405 PetscFunctionBegin; 9406 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9407 mesh->vtkCellHeight = cellHeight; 9408 PetscFunctionReturn(0); 9409 } 9410 9411 #undef __FUNCT__ 9412 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9413 /* We can easily have a form that takes an IS instead */ 9414 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9415 { 9416 PetscSection section, globalSection; 9417 PetscInt *numbers, p; 9418 PetscErrorCode ierr; 9419 9420 PetscFunctionBegin; 9421 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9422 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9423 for (p = pStart; p < pEnd; ++p) { 9424 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9425 } 9426 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9427 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9428 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9429 for (p = pStart; p < pEnd; ++p) { 9430 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9431 } 9432 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9433 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9434 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9435 PetscFunctionReturn(0); 9436 } 9437 9438 #undef __FUNCT__ 9439 #define __FUNCT__ "DMPlexGetCellNumbering" 9440 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9441 { 9442 DM_Plex *mesh = (DM_Plex*) dm->data; 9443 PetscInt cellHeight, cStart, cEnd, cMax; 9444 PetscErrorCode ierr; 9445 9446 PetscFunctionBegin; 9447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9448 if (!mesh->globalCellNumbers) { 9449 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9450 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9451 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 9452 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9453 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9454 } 9455 *globalCellNumbers = mesh->globalCellNumbers; 9456 PetscFunctionReturn(0); 9457 } 9458 9459 #undef __FUNCT__ 9460 #define __FUNCT__ "DMPlexGetVertexNumbering" 9461 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9462 { 9463 DM_Plex *mesh = (DM_Plex*) dm->data; 9464 PetscInt vStart, vEnd, vMax; 9465 PetscErrorCode ierr; 9466 9467 PetscFunctionBegin; 9468 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9469 if (!mesh->globalVertexNumbers) { 9470 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9471 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9472 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9473 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9474 } 9475 *globalVertexNumbers = mesh->globalVertexNumbers; 9476 PetscFunctionReturn(0); 9477 } 9478 9479 #undef __FUNCT__ 9480 #define __FUNCT__ "DMPlexGetScale" 9481 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9482 { 9483 DM_Plex *mesh = (DM_Plex*) dm->data; 9484 9485 PetscFunctionBegin; 9486 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9487 PetscValidPointer(scale, 3); 9488 *scale = mesh->scale[unit]; 9489 PetscFunctionReturn(0); 9490 } 9491 9492 #undef __FUNCT__ 9493 #define __FUNCT__ "DMPlexSetScale" 9494 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9495 { 9496 DM_Plex *mesh = (DM_Plex*) dm->data; 9497 9498 PetscFunctionBegin; 9499 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9500 mesh->scale[unit] = scale; 9501 PetscFunctionReturn(0); 9502 } 9503 9504 9505 /******************************************************************************* 9506 This should be in a separate Discretization object, but I am not sure how to lay 9507 it out yet, so I am stuffing things here while I experiment. 9508 *******************************************************************************/ 9509 #undef __FUNCT__ 9510 #define __FUNCT__ "DMPlexSetFEMIntegration" 9511 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9512 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9513 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9514 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9515 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9516 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9517 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9518 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9519 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9520 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9521 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9522 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9523 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9524 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9525 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9526 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9527 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9528 { 9529 DM_Plex *mesh = (DM_Plex*) dm->data; 9530 9531 PetscFunctionBegin; 9532 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9533 mesh->integrateResidualFEM = integrateResidualFEM; 9534 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9535 mesh->integrateJacobianFEM = integrateJacobianFEM; 9536 PetscFunctionReturn(0); 9537 } 9538 9539 #undef __FUNCT__ 9540 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9541 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9542 { 9543 Vec coordinates; 9544 PetscSection section, cSection; 9545 PetscInt dim, vStart, vEnd, v, c, d; 9546 PetscScalar *values, *cArray; 9547 PetscReal *coords; 9548 PetscErrorCode ierr; 9549 9550 PetscFunctionBegin; 9551 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9552 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9553 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9554 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9555 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9556 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9557 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9558 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9559 for (v = vStart; v < vEnd; ++v) { 9560 PetscInt dof, off; 9561 9562 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9563 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9564 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9565 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9566 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9567 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9568 } 9569 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9570 /* Temporary, must be replaced by a projection on the finite element basis */ 9571 { 9572 PetscInt eStart = 0, eEnd = 0, e, depth; 9573 9574 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9575 --depth; 9576 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9577 for (e = eStart; e < eEnd; ++e) { 9578 const PetscInt *cone = NULL; 9579 PetscInt coneSize, d; 9580 PetscScalar *coordsA, *coordsB; 9581 9582 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9583 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9584 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9585 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9586 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9587 for (d = 0; d < dim; ++d) { 9588 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9589 } 9590 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9591 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9592 } 9593 } 9594 9595 ierr = PetscFree(coords);CHKERRQ(ierr); 9596 ierr = PetscFree(values);CHKERRQ(ierr); 9597 #if 0 9598 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9599 PetscReal detJ; 9600 9601 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9602 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9603 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9604 9605 for (PetscInt c = cStart; c < cEnd; ++c) { 9606 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9607 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9608 const int oSize = pV.getSize(); 9609 int v = 0; 9610 9611 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9612 for (PetscInt cl = 0; cl < oSize; ++cl) { 9613 const PetscInt fDim; 9614 9615 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9616 if (pointDim) { 9617 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9618 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9619 } 9620 } 9621 } 9622 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9623 pV.clear(); 9624 } 9625 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9626 ierr = PetscFree(values);CHKERRQ(ierr); 9627 #endif 9628 PetscFunctionReturn(0); 9629 } 9630 9631 #undef __FUNCT__ 9632 #define __FUNCT__ "DMPlexProjectFunction" 9633 /*@C 9634 DMPlexProjectFunction - This projects the given function into the function space provided. 9635 9636 Input Parameters: 9637 + dm - The DM 9638 . numComp - The number of components (functions) 9639 . funcs - The coordinate functions to evaluate 9640 - mode - The insertion mode for values 9641 9642 Output Parameter: 9643 . X - vector 9644 9645 Level: developer 9646 9647 Note: 9648 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9649 We will eventually fix it. 9650 9651 ,seealso: DMPlexComputeL2Diff() 9652 */ 9653 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9654 { 9655 Vec localX; 9656 PetscErrorCode ierr; 9657 9658 PetscFunctionBegin; 9659 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9660 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9661 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9662 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9663 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9664 PetscFunctionReturn(0); 9665 } 9666 9667 #undef __FUNCT__ 9668 #define __FUNCT__ "DMPlexComputeL2Diff" 9669 /*@C 9670 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9671 9672 Input Parameters: 9673 + dm - The DM 9674 . quad - The PetscQuadrature object for each field 9675 . funcs - The functions to evaluate for each field component 9676 - X - The coefficient vector u_h 9677 9678 Output Parameter: 9679 . diff - The diff ||u - u_h||_2 9680 9681 Level: developer 9682 9683 .seealso: DMPlexProjectFunction() 9684 */ 9685 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9686 { 9687 const PetscInt debug = 0; 9688 PetscSection section; 9689 Vec localX; 9690 PetscReal *coords, *v0, *J, *invJ, detJ; 9691 PetscReal localDiff = 0.0; 9692 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9693 PetscErrorCode ierr; 9694 9695 PetscFunctionBegin; 9696 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9697 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9698 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9699 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9700 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9701 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9702 for (field = 0; field < numFields; ++field) { 9703 numComponents += quad[field].numComponents; 9704 } 9705 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9706 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9707 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9708 for (c = cStart; c < cEnd; ++c) { 9709 const PetscScalar *x; 9710 PetscReal elemDiff = 0.0; 9711 9712 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9713 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9714 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9715 9716 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9717 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9718 const PetscReal *quadPoints = quad[field].quadPoints; 9719 const PetscReal *quadWeights = quad[field].quadWeights; 9720 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9721 const PetscInt numBasisComps = quad[field].numComponents; 9722 const PetscReal *basis = quad[field].basis; 9723 PetscInt q, d, e, fc, f; 9724 9725 if (debug) { 9726 char title[1024]; 9727 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9728 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9729 } 9730 for (q = 0; q < numQuadPoints; ++q) { 9731 for (d = 0; d < dim; d++) { 9732 coords[d] = v0[d]; 9733 for (e = 0; e < dim; e++) { 9734 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9735 } 9736 } 9737 for (fc = 0; fc < numBasisComps; ++fc) { 9738 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9739 PetscReal interpolant = 0.0; 9740 for (f = 0; f < numBasisFuncs; ++f) { 9741 const PetscInt fidx = f*numBasisComps+fc; 9742 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9743 } 9744 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9745 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9746 } 9747 } 9748 comp += numBasisComps; 9749 fieldOffset += numBasisFuncs*numBasisComps; 9750 } 9751 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9752 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9753 localDiff += elemDiff; 9754 } 9755 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9756 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9757 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9758 *diff = PetscSqrtReal(*diff); 9759 PetscFunctionReturn(0); 9760 } 9761 9762 #undef __FUNCT__ 9763 #define __FUNCT__ "DMPlexComputeResidualFEM" 9764 /*@ 9765 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9766 9767 Input Parameters: 9768 + dm - The mesh 9769 . X - Local input vector 9770 - user - The user context 9771 9772 Output Parameter: 9773 . F - Local output vector 9774 9775 Note: 9776 The second member of the user context must be an FEMContext. 9777 9778 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9779 like a GPU, or vectorize on a multicore machine. 9780 9781 .seealso: DMPlexComputeJacobianActionFEM() 9782 */ 9783 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9784 { 9785 DM_Plex *mesh = (DM_Plex*) dm->data; 9786 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9787 PetscQuadrature *quad = fem->quad; 9788 PetscSection section; 9789 PetscReal *v0, *J, *invJ, *detJ; 9790 PetscScalar *elemVec, *u; 9791 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9792 PetscInt cellDof = 0, numComponents = 0; 9793 PetscErrorCode ierr; 9794 9795 PetscFunctionBegin; 9796 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9797 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9798 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9799 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9800 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9801 numCells = cEnd - cStart; 9802 for (field = 0; field < numFields; ++field) { 9803 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9804 numComponents += quad[field].numComponents; 9805 } 9806 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9807 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9808 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); 9809 for (c = cStart; c < cEnd; ++c) { 9810 const PetscScalar *x; 9811 PetscInt i; 9812 9813 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9814 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9815 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9816 9817 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9818 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9819 } 9820 for (field = 0; field < numFields; ++field) { 9821 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9822 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9823 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9824 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9825 /* Conforming batches */ 9826 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9827 PetscInt numBlocks = 1; 9828 PetscInt batchSize = numBlocks * blockSize; 9829 PetscInt numBatches = numBatchesTmp; 9830 PetscInt numChunks = numCells / (numBatches*batchSize); 9831 /* Remainder */ 9832 PetscInt numRemainder = numCells % (numBatches * batchSize); 9833 PetscInt offset = numCells - numRemainder; 9834 9835 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9836 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9837 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9838 } 9839 for (c = cStart; c < cEnd; ++c) { 9840 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9841 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9842 } 9843 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9844 if (mesh->printFEM) { 9845 PetscMPIInt rank, numProcs; 9846 PetscInt p; 9847 9848 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9849 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9850 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9851 for (p = 0; p < numProcs; ++p) { 9852 if (p == rank) { 9853 Vec f; 9854 9855 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9856 ierr = VecCopy(F, f);CHKERRQ(ierr); 9857 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9858 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9859 ierr = VecDestroy(&f);CHKERRQ(ierr); 9860 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9861 } 9862 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9863 } 9864 } 9865 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9866 PetscFunctionReturn(0); 9867 } 9868 9869 #undef __FUNCT__ 9870 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9871 /*@C 9872 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9873 9874 Input Parameters: 9875 + dm - The mesh 9876 . J - The Jacobian shell matrix 9877 . X - Local input vector 9878 - user - The user context 9879 9880 Output Parameter: 9881 . F - Local output vector 9882 9883 Note: 9884 The second member of the user context must be an FEMContext. 9885 9886 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9887 like a GPU, or vectorize on a multicore machine. 9888 9889 .seealso: DMPlexComputeResidualFEM() 9890 */ 9891 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9892 { 9893 DM_Plex *mesh = (DM_Plex*) dm->data; 9894 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9895 PetscQuadrature *quad = fem->quad; 9896 PetscSection section; 9897 JacActionCtx *jctx; 9898 PetscReal *v0, *J, *invJ, *detJ; 9899 PetscScalar *elemVec, *u, *a; 9900 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9901 PetscInt cellDof = 0; 9902 PetscErrorCode ierr; 9903 9904 PetscFunctionBegin; 9905 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9906 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9907 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9908 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9909 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9910 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9911 numCells = cEnd - cStart; 9912 for (field = 0; field < numFields; ++field) { 9913 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9914 } 9915 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9916 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); 9917 for (c = cStart; c < cEnd; ++c) { 9918 const PetscScalar *x; 9919 PetscInt i; 9920 9921 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9922 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9923 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9924 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9925 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9926 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9927 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9928 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9929 } 9930 for (field = 0; field < numFields; ++field) { 9931 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9932 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9933 /* Conforming batches */ 9934 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9935 PetscInt numBlocks = 1; 9936 PetscInt batchSize = numBlocks * blockSize; 9937 PetscInt numBatches = numBatchesTmp; 9938 PetscInt numChunks = numCells / (numBatches*batchSize); 9939 /* Remainder */ 9940 PetscInt numRemainder = numCells % (numBatches * batchSize); 9941 PetscInt offset = numCells - numRemainder; 9942 9943 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); 9944 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], 9945 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9946 } 9947 for (c = cStart; c < cEnd; ++c) { 9948 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9949 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9950 } 9951 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9952 if (mesh->printFEM) { 9953 PetscMPIInt rank, numProcs; 9954 PetscInt p; 9955 9956 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9957 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9958 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9959 for (p = 0; p < numProcs; ++p) { 9960 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9961 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9962 } 9963 } 9964 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9965 PetscFunctionReturn(0); 9966 } 9967 9968 #undef __FUNCT__ 9969 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9970 /*@ 9971 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9972 9973 Input Parameters: 9974 + dm - The mesh 9975 . X - Local input vector 9976 - user - The user context 9977 9978 Output Parameter: 9979 . Jac - Jacobian matrix 9980 9981 Note: 9982 The second member of the user context must be an FEMContext. 9983 9984 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9985 like a GPU, or vectorize on a multicore machine. 9986 9987 .seealso: FormFunctionLocal() 9988 */ 9989 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9990 { 9991 DM_Plex *mesh = (DM_Plex*) dm->data; 9992 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9993 PetscQuadrature *quad = fem->quad; 9994 PetscSection section; 9995 PetscReal *v0, *J, *invJ, *detJ; 9996 PetscScalar *elemMat, *u; 9997 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9998 PetscInt cellDof = 0, numComponents = 0; 9999 PetscBool isShell; 10000 PetscErrorCode ierr; 10001 10002 PetscFunctionBegin; 10003 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10004 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10005 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10006 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10007 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10008 numCells = cEnd - cStart; 10009 for (field = 0; field < numFields; ++field) { 10010 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10011 numComponents += quad[field].numComponents; 10012 } 10013 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10014 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10015 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); 10016 for (c = cStart; c < cEnd; ++c) { 10017 const PetscScalar *x; 10018 PetscInt i; 10019 10020 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10021 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10022 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 10023 10024 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10025 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 10026 } 10027 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10028 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10029 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10030 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10031 PetscInt fieldJ; 10032 10033 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10034 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10035 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10036 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10037 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10038 /* Conforming batches */ 10039 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10040 PetscInt numBlocks = 1; 10041 PetscInt batchSize = numBlocks * blockSize; 10042 PetscInt numBatches = numBatchesTmp; 10043 PetscInt numChunks = numCells / (numBatches*batchSize); 10044 /* Remainder */ 10045 PetscInt numRemainder = numCells % (numBatches * batchSize); 10046 PetscInt offset = numCells - numRemainder; 10047 10048 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10049 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10050 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10051 } 10052 } 10053 for (c = cStart; c < cEnd; ++c) { 10054 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10055 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10056 } 10057 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10058 10059 /* Assemble matrix, using the 2-step process: 10060 MatAssemblyBegin(), MatAssemblyEnd(). */ 10061 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10062 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10063 10064 if (mesh->printFEM) { 10065 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10066 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10067 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10068 } 10069 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10070 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10071 if (isShell) { 10072 JacActionCtx *jctx; 10073 10074 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10075 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10076 } 10077 *str = SAME_NONZERO_PATTERN; 10078 PetscFunctionReturn(0); 10079 } 10080 10081 10082 #undef __FUNCT__ 10083 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10084 /*@C 10085 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10086 the local section and an SF describing the section point overlap. 10087 10088 Input Parameters: 10089 + s - The PetscSection for the local field layout 10090 . sf - The SF describing parallel layout of the section points 10091 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10092 . label - The label specifying the points 10093 - labelValue - The label stratum specifying the points 10094 10095 Output Parameter: 10096 . gsection - The PetscSection for the global field layout 10097 10098 Note: This gives negative sizes and offsets to points not owned by this process 10099 10100 Level: developer 10101 10102 .seealso: PetscSectionCreate() 10103 @*/ 10104 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10105 { 10106 PetscInt *neg; 10107 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10108 PetscErrorCode ierr; 10109 10110 PetscFunctionBegin; 10111 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10112 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10113 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10114 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10115 /* Mark ghost points with negative dof */ 10116 for (p = pStart; p < pEnd; ++p) { 10117 PetscInt value; 10118 10119 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10120 if (value != labelValue) continue; 10121 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10122 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10123 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10124 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10125 neg[p-pStart] = -(dof+1); 10126 } 10127 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10128 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 10129 if (nroots >= 0) { 10130 if (nroots > pEnd - pStart) { 10131 PetscInt *tmpDof; 10132 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10133 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10134 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10135 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10136 for (p = pStart; p < pEnd; ++p) { 10137 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 10138 } 10139 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10140 } else { 10141 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10142 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10143 } 10144 } 10145 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10146 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10147 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10148 10149 (*gsection)->atlasOff[p] = off; 10150 10151 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10152 } 10153 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10154 globalOff -= off; 10155 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10156 (*gsection)->atlasOff[p] += globalOff; 10157 10158 neg[p] = -((*gsection)->atlasOff[p]+1); 10159 } 10160 /* Put in negative offsets for ghost points */ 10161 if (nroots >= 0) { 10162 if (nroots > pEnd - pStart) { 10163 PetscInt *tmpOff; 10164 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10165 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10166 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10167 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10168 for (p = pStart; p < pEnd; ++p) { 10169 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 10170 } 10171 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10172 } else { 10173 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10174 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10175 } 10176 } 10177 ierr = PetscFree(neg);CHKERRQ(ierr); 10178 PetscFunctionReturn(0); 10179 } 10180