1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex*) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 167 if (size > 1) { 168 PetscSF sf; 169 170 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 171 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 172 } 173 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 174 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 175 const char *name; 176 const char *colors[3] = {"red", "blue", "green"}; 177 const int numColors = 3; 178 PetscReal scale = 2.0; 179 PetscScalar *coords; 180 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 181 PetscMPIInt rank, size; 182 183 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 184 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 185 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 186 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 187 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 188 ierr = PetscViewerASCIIPrintf(viewer, "\ 189 \\documentclass[crop,multi=false]{standalone}\n\n\ 190 \\usepackage{tikz}\n\ 191 \\usepackage{pgflibraryshapes}\n\ 192 \\usetikzlibrary{backgrounds}\n\ 193 \\usetikzlibrary{arrows}\n\ 194 \\begin{document}\n\ 195 \\section{%s}\n\ 196 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 197 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 198 for (p = 0; p < size; ++p) { 199 if (p > 0 && p == size-1) { 200 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 201 } else if (p > 0) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 203 } 204 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 207 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 208 /* Plot vertices */ 209 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 210 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 211 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 212 for (v = vStart; v < vEnd; ++v) { 213 PetscInt off, dof, d; 214 215 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 216 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 217 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 218 for (d = 0; d < dof; ++d) { 219 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 220 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 221 } 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 223 } 224 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 225 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 226 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 227 /* Plot edges */ 228 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 229 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 230 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 231 for (e = eStart; e < eEnd; ++e) { 232 const PetscInt *cone; 233 PetscInt coneSize, offA, offB, dof, d; 234 235 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 236 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 237 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 238 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 239 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 240 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 241 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 242 for (d = 0; d < dof; ++d) { 243 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 244 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 245 } 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 247 } 248 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 249 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 250 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 251 /* Plot cells */ 252 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 253 for (c = cStart; c < cEnd; ++c) { 254 PetscInt *closure = PETSC_NULL; 255 PetscInt closureSize, firstPoint = -1; 256 257 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 258 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 259 for (p = 0; p < closureSize*2; p += 2) { 260 const PetscInt point = closure[p]; 261 262 if ((point < vStart) || (point >= vEnd)) continue; 263 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 264 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 265 if (firstPoint < 0) firstPoint = point; 266 } 267 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 268 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 269 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 270 } 271 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 272 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 273 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 274 } else { 275 MPI_Comm comm = ((PetscObject) dm)->comm; 276 PetscInt *sizes; 277 PetscInt locDepth, depth, dim, d; 278 PetscInt pStart, pEnd, p; 279 PetscMPIInt size; 280 281 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 282 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 283 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 284 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 285 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 286 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 287 if (depth == 1) { 288 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 289 pEnd = pEnd - pStart; 290 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 291 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 292 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 293 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 294 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 295 pEnd = pEnd - pStart; 296 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 297 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 298 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 299 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 300 } else { 301 for (d = 0; d <= dim; d++) { 302 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 303 pEnd = pEnd - pStart; 304 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 305 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 306 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 307 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 308 } 309 } 310 ierr = PetscFree(sizes);CHKERRQ(ierr); 311 } 312 PetscFunctionReturn(0); 313 } 314 315 #undef __FUNCT__ 316 #define __FUNCT__ "DMView_Plex" 317 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 318 { 319 PetscBool iascii, isbinary; 320 PetscErrorCode ierr; 321 322 PetscFunctionBegin; 323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 324 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 325 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 326 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 327 if (iascii) { 328 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 329 #if 0 330 } else if (isbinary) { 331 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 332 #endif 333 } 334 PetscFunctionReturn(0); 335 } 336 337 #undef __FUNCT__ 338 #define __FUNCT__ "DMDestroy_Plex" 339 PetscErrorCode DMDestroy_Plex(DM dm) 340 { 341 DM_Plex *mesh = (DM_Plex*) dm->data; 342 DMLabel next = mesh->labels; 343 PetscErrorCode ierr; 344 345 PetscFunctionBegin; 346 if (--mesh->refct > 0) PetscFunctionReturn(0); 347 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 348 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 349 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 350 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 353 while (next) { 354 DMLabel tmp = next->next; 355 356 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 357 next = tmp; 358 } 359 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 360 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 361 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 362 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 363 ierr = PetscFree(mesh);CHKERRQ(ierr); 364 PetscFunctionReturn(0); 365 } 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 369 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 370 { 371 const PetscInt *support = PETSC_NULL; 372 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 373 PetscErrorCode ierr; 374 375 PetscFunctionBegin; 376 if (useClosure) { 377 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 378 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 379 for (s = 0; s < supportSize; ++s) { 380 const PetscInt *cone = PETSC_NULL; 381 PetscInt coneSize, c, q; 382 383 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 384 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 385 for (c = 0; c < coneSize; ++c) { 386 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 387 if (cone[c] == adj[q]) break; 388 } 389 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 390 } 391 } 392 } else { 393 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 394 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 395 for (s = 0; s < supportSize; ++s) { 396 const PetscInt *cone = PETSC_NULL; 397 PetscInt coneSize, c, q; 398 399 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 400 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 401 for (c = 0; c < coneSize; ++c) { 402 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 403 if (cone[c] == adj[q]) break; 404 } 405 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 406 } 407 } 408 } 409 *adjSize = numAdj; 410 PetscFunctionReturn(0); 411 } 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "DMPlexGetAdjacency_Private" 415 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 416 { 417 const PetscInt *star = tmpClosure; 418 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 419 PetscErrorCode ierr; 420 421 PetscFunctionBegin; 422 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 423 for (s = 2; s < starSize*2; s += 2) { 424 const PetscInt *closure = PETSC_NULL; 425 PetscInt closureSize, c, q; 426 427 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 428 for (c = 0; c < closureSize*2; c += 2) { 429 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 430 if (closure[c] == adj[q]) break; 431 } 432 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 433 } 434 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 435 } 436 *adjSize = numAdj; 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNCT__ 441 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 442 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 443 { 444 DM_Plex *mesh = (DM_Plex*) dm->data; 445 446 PetscFunctionBegin; 447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 448 mesh->preallocCenterDim = preallocCenterDim; 449 PetscFunctionReturn(0); 450 } 451 452 #undef __FUNCT__ 453 #define __FUNCT__ "DMPlexPreallocateOperator" 454 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 455 { 456 DM_Plex *mesh = (DM_Plex*) dm->data; 457 MPI_Comm comm = ((PetscObject) dm)->comm; 458 PetscSF sf, sfDof, sfAdj; 459 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 460 PetscInt nleaves, l, p; 461 const PetscInt *leaves; 462 const PetscSFNode *remotes; 463 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 464 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 465 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 466 PetscLayout rLayout; 467 PetscInt locRows, rStart, rEnd, r; 468 PetscMPIInt size; 469 PetscBool useClosure, debug = PETSC_FALSE; 470 PetscErrorCode ierr; 471 472 PetscFunctionBegin; 473 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 474 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 475 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 476 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 477 /* Create dof SF based on point SF */ 478 if (debug) { 479 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 480 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 481 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 485 } 486 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 487 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 488 if (debug) { 489 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 490 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 491 } 492 /* Create section for dof adjacency (dof ==> # adj dof) */ 493 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 494 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 495 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 496 if (mesh->preallocCenterDim == dim) { 497 useClosure = PETSC_FALSE; 498 } else if (mesh->preallocCenterDim == 0) { 499 useClosure = PETSC_TRUE; 500 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 501 502 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 503 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 504 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 505 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 508 /* Fill in the ghost dofs on the interface */ 509 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 510 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 511 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 512 513 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 514 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 515 516 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 517 518 /* 519 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 520 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 521 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 522 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 523 Create sfAdj connecting rootSectionAdj and leafSectionAdj 524 3. Visit unowned points on interface, write adjacencies to adj 525 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 526 4. Visit owned points on interface, write adjacencies to rootAdj 527 Remove redundancy in rootAdj 528 ** The last two traversals use transitive closure 529 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 530 Allocate memory addressed by sectionAdj (cols) 531 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 532 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 533 */ 534 535 for (l = 0; l < nleaves; ++l) { 536 PetscInt dof, off, d, q; 537 PetscInt p = leaves[l], numAdj = maxAdjSize; 538 539 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 540 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 541 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 542 for (q = 0; q < numAdj; ++q) { 543 PetscInt ndof, ncdof; 544 545 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 546 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 547 for (d = off; d < off+dof; ++d) { 548 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 549 } 550 } 551 } 552 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 553 if (debug) { 554 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 555 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 556 } 557 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 558 if (size > 1) { 559 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 560 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 561 } 562 if (debug) { 563 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 564 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 565 } 566 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 567 for (p = pStart; p < pEnd; ++p) { 568 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 569 570 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 571 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 572 if (!dof) continue; 573 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 574 if (adof <= 0) continue; 575 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 576 for (q = 0; q < numAdj; ++q) { 577 PetscInt ndof, ncdof; 578 579 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 580 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 581 for (d = off; d < off+dof; ++d) { 582 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 583 } 584 } 585 } 586 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 587 if (debug) { 588 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 589 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 590 } 591 /* Create adj SF based on dof SF */ 592 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 593 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 594 if (debug) { 595 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 596 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 597 } 598 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 599 /* Create leaf adjacency */ 600 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 601 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 602 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 603 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 604 for (l = 0; l < nleaves; ++l) { 605 PetscInt dof, off, d, q; 606 PetscInt p = leaves[l], numAdj = maxAdjSize; 607 608 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 609 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 610 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 611 for (d = off; d < off+dof; ++d) { 612 PetscInt aoff, i = 0; 613 614 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 615 for (q = 0; q < numAdj; ++q) { 616 PetscInt ndof, ncdof, ngoff, nd; 617 618 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 619 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 621 for (nd = 0; nd < ndof-ncdof; ++nd) { 622 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 623 ++i; 624 } 625 } 626 } 627 } 628 /* Debugging */ 629 if (debug) { 630 IS tmp; 631 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 632 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 633 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 634 } 635 /* Gather adjacenct indices to root */ 636 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 637 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 638 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 639 if (size > 1) { 640 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 641 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 642 } 643 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 644 ierr = PetscFree(adj);CHKERRQ(ierr); 645 /* Debugging */ 646 if (debug) { 647 IS tmp; 648 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 649 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 650 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 651 } 652 /* Add in local adjacency indices for owned dofs on interface (roots) */ 653 for (p = pStart; p < pEnd; ++p) { 654 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 655 656 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 657 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 658 if (!dof) continue; 659 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 660 if (adof <= 0) continue; 661 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 662 for (d = off; d < off+dof; ++d) { 663 PetscInt adof, aoff, i; 664 665 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 666 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 667 i = adof-1; 668 for (q = 0; q < numAdj; ++q) { 669 PetscInt ndof, ncdof, ngoff, nd; 670 671 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 672 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 673 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 674 for (nd = 0; nd < ndof-ncdof; ++nd) { 675 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 676 --i; 677 } 678 } 679 } 680 } 681 /* Debugging */ 682 if (debug) { 683 IS tmp; 684 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 685 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 686 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 687 } 688 /* Compress indices */ 689 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 690 for (p = pStart; p < pEnd; ++p) { 691 PetscInt dof, cdof, off, d; 692 PetscInt adof, aoff; 693 694 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 695 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 696 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 697 if (!dof) continue; 698 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 699 if (adof <= 0) continue; 700 for (d = off; d < off+dof-cdof; ++d) { 701 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 702 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 703 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 704 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 705 } 706 } 707 /* Debugging */ 708 if (debug) { 709 IS tmp; 710 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 711 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 712 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 713 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 714 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 715 } 716 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 717 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 718 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 719 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 720 for (p = pStart; p < pEnd; ++p) { 721 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 722 PetscBool found = PETSC_TRUE; 723 724 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 725 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 727 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 728 for (d = 0; d < dof-cdof; ++d) { 729 PetscInt ldof, rdof; 730 731 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 732 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 733 if (ldof > 0) { 734 /* We do not own this point */ 735 } else if (rdof > 0) { 736 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 737 } else { 738 found = PETSC_FALSE; 739 } 740 } 741 if (found) continue; 742 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 743 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 744 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 745 for (q = 0; q < numAdj; ++q) { 746 PetscInt ndof, ncdof, noff; 747 748 /* Adjacent points may not be in the section chart */ 749 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 750 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 751 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 752 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 753 for (d = goff; d < goff+dof-cdof; ++d) { 754 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 755 } 756 } 757 } 758 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 759 if (debug) { 760 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 761 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 762 } 763 /* Get adjacent indices */ 764 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 765 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 768 PetscBool found = PETSC_TRUE; 769 770 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 771 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 772 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 773 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 774 for (d = 0; d < dof-cdof; ++d) { 775 PetscInt ldof, rdof; 776 777 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 778 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 779 if (ldof > 0) { 780 /* We do not own this point */ 781 } else if (rdof > 0) { 782 PetscInt aoff, roff; 783 784 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 786 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 787 } else { 788 found = PETSC_FALSE; 789 } 790 } 791 if (found) continue; 792 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 793 for (d = goff; d < goff+dof-cdof; ++d) { 794 PetscInt adof, aoff, i = 0; 795 796 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 797 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 798 for (q = 0; q < numAdj; ++q) { 799 PetscInt ndof, ncdof, ngoff, nd; 800 const PetscInt *ncind; 801 802 /* Adjacent points may not be in the section chart */ 803 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 804 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 805 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 806 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 807 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 808 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 809 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 810 } 811 } 812 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); 813 } 814 } 815 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 816 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 817 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 818 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 819 /* Debugging */ 820 if (debug) { 821 IS tmp; 822 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 823 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 824 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 825 } 826 /* Create allocation vectors from adjacency graph */ 827 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 828 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 829 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 830 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 831 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 832 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 833 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 834 /* Only loop over blocks of rows */ 835 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); 836 for (r = rStart/bs; r < rEnd/bs; ++r) { 837 const PetscInt row = r*bs; 838 PetscInt numCols, cStart, c; 839 840 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 841 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 842 for (c = cStart; c < cStart+numCols; ++c) { 843 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 844 ++dnz[r-rStart]; 845 if (cols[c] >= row) ++dnzu[r-rStart]; 846 } else { 847 ++onz[r-rStart]; 848 if (cols[c] >= row) ++onzu[r-rStart]; 849 } 850 } 851 } 852 if (bs > 1) { 853 for (r = 0; r < locRows/bs; ++r) { 854 dnz[r] /= bs; 855 onz[r] /= bs; 856 dnzu[r] /= bs; 857 onzu[r] /= bs; 858 } 859 } 860 /* Set matrix pattern */ 861 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 862 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 863 /* Fill matrix with zeros */ 864 if (fillMatrix) { 865 PetscScalar *values; 866 PetscInt maxRowLen = 0; 867 868 for (r = rStart; r < rEnd; ++r) { 869 PetscInt len; 870 871 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 872 maxRowLen = PetscMax(maxRowLen, len); 873 } 874 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 875 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 876 for (r = rStart; r < rEnd; ++r) { 877 PetscInt numCols, cStart; 878 879 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 880 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 881 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 882 } 883 ierr = PetscFree(values);CHKERRQ(ierr); 884 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 885 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 886 } 887 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 888 ierr = PetscFree(cols);CHKERRQ(ierr); 889 PetscFunctionReturn(0); 890 } 891 892 #if 0 893 #undef __FUNCT__ 894 #define __FUNCT__ "DMPlexPreallocateOperator_2" 895 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 896 { 897 PetscErrorCode ierr; 898 PetscInt c,cStart,cEnd,pStart,pEnd; 899 PetscInt *tmpClosure,*tmpAdj,*visits; 900 901 PetscFunctionBegin; 902 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 903 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 904 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 905 906 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 907 908 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 909 npoints = pEnd - pStart; 910 911 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 912 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 913 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 914 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 915 for (c=cStart; c<cEnd; c++) { 916 PetscInt *support = tmpClosure; 917 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 918 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 919 } 920 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 921 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 922 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 923 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 924 925 ierr = PetscSFGetRanks();CHKERRQ(ierr); 926 927 928 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 929 for (c=cStart; c<cEnd; c++) { 930 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 931 /* 932 Depth-first walk of transitive closure. 933 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. 934 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 935 */ 936 } 937 938 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 939 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 940 PetscFunctionReturn(0); 941 } 942 #endif 943 944 #undef __FUNCT__ 945 #define __FUNCT__ "DMCreateMatrix_Plex" 946 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 947 { 948 PetscSection section, sectionGlobal; 949 PetscInt bs = -1; 950 PetscInt localSize; 951 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 952 PetscErrorCode ierr; 953 954 PetscFunctionBegin; 955 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 956 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 957 #endif 958 if (!mtype) mtype = MATAIJ; 959 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 960 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 961 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 962 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 963 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 964 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 965 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 966 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 967 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 974 /* Check for symmetric storage */ 975 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 976 if (isSymmetric) { 977 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 978 } 979 if (!isShell) { 980 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 981 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 982 983 if (bs < 0) { 984 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 985 PetscInt pStart, pEnd, p, dof; 986 987 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 988 for (p = pStart; p < pEnd; ++p) { 989 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 990 if (dof) { 991 if (bs < 0) { 992 bs = dof; 993 } else if (bs != dof) { 994 /* Layout does not admit a pointwise block size */ 995 bs = 1; 996 break; 997 } 998 } 999 } 1000 /* Must have same blocksize on all procs (some might have no points) */ 1001 bsLocal = bs; 1002 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1003 bsLocal = bs < 0 ? bsMax : bs; 1004 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1005 if (bsMin != bsMax) { 1006 bs = 1; 1007 } else { 1008 bs = bsMax; 1009 } 1010 } else { 1011 bs = 1; 1012 } 1013 } 1014 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1015 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1016 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1017 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1018 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1019 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1020 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1021 } 1022 PetscFunctionReturn(0); 1023 } 1024 1025 #undef __FUNCT__ 1026 #define __FUNCT__ "DMPlexGetDimension" 1027 /*@ 1028 DMPlexGetDimension - Return the topological mesh dimension 1029 1030 Not collective 1031 1032 Input Parameter: 1033 . mesh - The DMPlex 1034 1035 Output Parameter: 1036 . dim - The topological mesh dimension 1037 1038 Level: beginner 1039 1040 .seealso: DMPlexCreate() 1041 @*/ 1042 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1043 { 1044 DM_Plex *mesh = (DM_Plex*) dm->data; 1045 1046 PetscFunctionBegin; 1047 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1048 PetscValidPointer(dim, 2); 1049 *dim = mesh->dim; 1050 PetscFunctionReturn(0); 1051 } 1052 1053 #undef __FUNCT__ 1054 #define __FUNCT__ "DMPlexSetDimension" 1055 /*@ 1056 DMPlexSetDimension - Set the topological mesh dimension 1057 1058 Collective on mesh 1059 1060 Input Parameters: 1061 + mesh - The DMPlex 1062 - dim - The topological mesh dimension 1063 1064 Level: beginner 1065 1066 .seealso: DMPlexCreate() 1067 @*/ 1068 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1069 { 1070 DM_Plex *mesh = (DM_Plex*) dm->data; 1071 1072 PetscFunctionBegin; 1073 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1074 PetscValidLogicalCollectiveInt(dm, dim, 2); 1075 mesh->dim = dim; 1076 mesh->preallocCenterDim = dim; 1077 PetscFunctionReturn(0); 1078 } 1079 1080 #undef __FUNCT__ 1081 #define __FUNCT__ "DMPlexGetChart" 1082 /*@ 1083 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1084 1085 Not collective 1086 1087 Input Parameter: 1088 . mesh - The DMPlex 1089 1090 Output Parameters: 1091 + pStart - The first mesh point 1092 - pEnd - The upper bound for mesh points 1093 1094 Level: beginner 1095 1096 .seealso: DMPlexCreate(), DMPlexSetChart() 1097 @*/ 1098 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1099 { 1100 DM_Plex *mesh = (DM_Plex*) dm->data; 1101 PetscErrorCode ierr; 1102 1103 PetscFunctionBegin; 1104 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1105 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1106 PetscFunctionReturn(0); 1107 } 1108 1109 #undef __FUNCT__ 1110 #define __FUNCT__ "DMPlexSetChart" 1111 /*@ 1112 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1113 1114 Not collective 1115 1116 Input Parameters: 1117 + mesh - The DMPlex 1118 . pStart - The first mesh point 1119 - pEnd - The upper bound for mesh points 1120 1121 Output Parameters: 1122 1123 Level: beginner 1124 1125 .seealso: DMPlexCreate(), DMPlexGetChart() 1126 @*/ 1127 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1128 { 1129 DM_Plex *mesh = (DM_Plex*) dm->data; 1130 PetscErrorCode ierr; 1131 1132 PetscFunctionBegin; 1133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1134 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1135 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1136 PetscFunctionReturn(0); 1137 } 1138 1139 #undef __FUNCT__ 1140 #define __FUNCT__ "DMPlexGetConeSize" 1141 /*@ 1142 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1143 1144 Not collective 1145 1146 Input Parameters: 1147 + mesh - The DMPlex 1148 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1149 1150 Output Parameter: 1151 . size - The cone size for point p 1152 1153 Level: beginner 1154 1155 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1156 @*/ 1157 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1158 { 1159 DM_Plex *mesh = (DM_Plex*) dm->data; 1160 PetscErrorCode ierr; 1161 1162 PetscFunctionBegin; 1163 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1164 PetscValidPointer(size, 3); 1165 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1166 PetscFunctionReturn(0); 1167 } 1168 1169 #undef __FUNCT__ 1170 #define __FUNCT__ "DMPlexSetConeSize" 1171 /*@ 1172 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1173 1174 Not collective 1175 1176 Input Parameters: 1177 + mesh - The DMPlex 1178 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1179 - size - The cone size for point p 1180 1181 Output Parameter: 1182 1183 Note: 1184 This should be called after DMPlexSetChart(). 1185 1186 Level: beginner 1187 1188 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1189 @*/ 1190 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1191 { 1192 DM_Plex *mesh = (DM_Plex*) dm->data; 1193 PetscErrorCode ierr; 1194 1195 PetscFunctionBegin; 1196 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1197 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1198 1199 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1200 PetscFunctionReturn(0); 1201 } 1202 1203 #undef __FUNCT__ 1204 #define __FUNCT__ "DMPlexGetCone" 1205 /*@C 1206 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1207 1208 Not collective 1209 1210 Input Parameters: 1211 + mesh - The DMPlex 1212 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1213 1214 Output Parameter: 1215 . cone - An array of points which are on the in-edges for point p 1216 1217 Level: beginner 1218 1219 Note: 1220 This routine is not available in Fortran. 1221 1222 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1223 @*/ 1224 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1225 { 1226 DM_Plex *mesh = (DM_Plex*) dm->data; 1227 PetscInt off; 1228 PetscErrorCode ierr; 1229 1230 PetscFunctionBegin; 1231 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1232 PetscValidPointer(cone, 3); 1233 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1234 *cone = &mesh->cones[off]; 1235 PetscFunctionReturn(0); 1236 } 1237 1238 #undef __FUNCT__ 1239 #define __FUNCT__ "DMPlexSetCone" 1240 /*@ 1241 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1242 1243 Not collective 1244 1245 Input Parameters: 1246 + mesh - The DMPlex 1247 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1248 - cone - An array of points which are on the in-edges for point p 1249 1250 Output Parameter: 1251 1252 Note: 1253 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1254 1255 Level: beginner 1256 1257 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1258 @*/ 1259 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1260 { 1261 DM_Plex *mesh = (DM_Plex*) dm->data; 1262 PetscInt pStart, pEnd; 1263 PetscInt dof, off, c; 1264 PetscErrorCode ierr; 1265 1266 PetscFunctionBegin; 1267 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1268 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1269 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1270 if (dof) PetscValidPointer(cone, 3); 1271 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1272 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); 1273 for (c = 0; c < dof; ++c) { 1274 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); 1275 mesh->cones[off+c] = cone[c]; 1276 } 1277 PetscFunctionReturn(0); 1278 } 1279 1280 #undef __FUNCT__ 1281 #define __FUNCT__ "DMPlexGetConeOrientation" 1282 /*@C 1283 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1284 1285 Not collective 1286 1287 Input Parameters: 1288 + mesh - The DMPlex 1289 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1290 1291 Output Parameter: 1292 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1293 integer giving the prescription for cone traversal. If it is negative, the cone is 1294 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1295 the index of the cone point on which to start. 1296 1297 Level: beginner 1298 1299 Note: 1300 This routine is not available in Fortran. 1301 1302 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1303 @*/ 1304 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1305 { 1306 DM_Plex *mesh = (DM_Plex*) dm->data; 1307 PetscInt off; 1308 PetscErrorCode ierr; 1309 1310 PetscFunctionBegin; 1311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1312 #if defined(PETSC_USE_DEBUG) 1313 { 1314 PetscInt dof; 1315 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1316 if (dof) PetscValidPointer(coneOrientation, 3); 1317 } 1318 #endif 1319 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1320 1321 *coneOrientation = &mesh->coneOrientations[off]; 1322 PetscFunctionReturn(0); 1323 } 1324 1325 #undef __FUNCT__ 1326 #define __FUNCT__ "DMPlexSetConeOrientation" 1327 /*@ 1328 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1329 1330 Not collective 1331 1332 Input Parameters: 1333 + mesh - The DMPlex 1334 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1335 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1336 integer giving the prescription for cone traversal. If it is negative, the cone is 1337 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1338 the index of the cone point on which to start. 1339 1340 Output Parameter: 1341 1342 Note: 1343 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1344 1345 Level: beginner 1346 1347 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1348 @*/ 1349 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1350 { 1351 DM_Plex *mesh = (DM_Plex*) dm->data; 1352 PetscInt pStart, pEnd; 1353 PetscInt dof, off, c; 1354 PetscErrorCode ierr; 1355 1356 PetscFunctionBegin; 1357 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1358 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1359 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1360 if (dof) PetscValidPointer(coneOrientation, 3); 1361 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1362 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); 1363 for (c = 0; c < dof; ++c) { 1364 PetscInt cdof, o = coneOrientation[c]; 1365 1366 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1367 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); 1368 mesh->coneOrientations[off+c] = o; 1369 } 1370 PetscFunctionReturn(0); 1371 } 1372 1373 #undef __FUNCT__ 1374 #define __FUNCT__ "DMPlexInsertCone" 1375 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1376 { 1377 DM_Plex *mesh = (DM_Plex*) dm->data; 1378 PetscInt pStart, pEnd; 1379 PetscInt dof, off; 1380 PetscErrorCode ierr; 1381 1382 PetscFunctionBegin; 1383 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1384 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1385 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1386 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1387 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); 1388 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); 1389 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); 1390 mesh->cones[off+conePos] = conePoint; 1391 PetscFunctionReturn(0); 1392 } 1393 1394 #undef __FUNCT__ 1395 #define __FUNCT__ "DMPlexGetSupportSize" 1396 /*@ 1397 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1398 1399 Not collective 1400 1401 Input Parameters: 1402 + mesh - The DMPlex 1403 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1404 1405 Output Parameter: 1406 . size - The support size for point p 1407 1408 Level: beginner 1409 1410 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1411 @*/ 1412 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1413 { 1414 DM_Plex *mesh = (DM_Plex*) dm->data; 1415 PetscErrorCode ierr; 1416 1417 PetscFunctionBegin; 1418 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1419 PetscValidPointer(size, 3); 1420 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1421 PetscFunctionReturn(0); 1422 } 1423 1424 #undef __FUNCT__ 1425 #define __FUNCT__ "DMPlexSetSupportSize" 1426 /*@ 1427 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1428 1429 Not collective 1430 1431 Input Parameters: 1432 + mesh - The DMPlex 1433 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1434 - size - The support size for point p 1435 1436 Output Parameter: 1437 1438 Note: 1439 This should be called after DMPlexSetChart(). 1440 1441 Level: beginner 1442 1443 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1444 @*/ 1445 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1446 { 1447 DM_Plex *mesh = (DM_Plex*) dm->data; 1448 PetscErrorCode ierr; 1449 1450 PetscFunctionBegin; 1451 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1452 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1453 1454 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1455 PetscFunctionReturn(0); 1456 } 1457 1458 #undef __FUNCT__ 1459 #define __FUNCT__ "DMPlexGetSupport" 1460 /*@C 1461 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1462 1463 Not collective 1464 1465 Input Parameters: 1466 + mesh - The DMPlex 1467 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1468 1469 Output Parameter: 1470 . support - An array of points which are on the out-edges for point p 1471 1472 Level: beginner 1473 1474 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1475 @*/ 1476 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1477 { 1478 DM_Plex *mesh = (DM_Plex*) dm->data; 1479 PetscInt off; 1480 PetscErrorCode ierr; 1481 1482 PetscFunctionBegin; 1483 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1484 PetscValidPointer(support, 3); 1485 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1486 *support = &mesh->supports[off]; 1487 PetscFunctionReturn(0); 1488 } 1489 1490 #undef __FUNCT__ 1491 #define __FUNCT__ "DMPlexSetSupport" 1492 /*@ 1493 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1494 1495 Not collective 1496 1497 Input Parameters: 1498 + mesh - The DMPlex 1499 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1500 - support - An array of points which are on the in-edges for point p 1501 1502 Output Parameter: 1503 1504 Note: 1505 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1506 1507 Level: beginner 1508 1509 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1510 @*/ 1511 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1512 { 1513 DM_Plex *mesh = (DM_Plex*) dm->data; 1514 PetscInt pStart, pEnd; 1515 PetscInt dof, off, c; 1516 PetscErrorCode ierr; 1517 1518 PetscFunctionBegin; 1519 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1520 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1521 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1522 if (dof) PetscValidPointer(support, 3); 1523 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1524 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); 1525 for (c = 0; c < dof; ++c) { 1526 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); 1527 mesh->supports[off+c] = support[c]; 1528 } 1529 PetscFunctionReturn(0); 1530 } 1531 1532 #undef __FUNCT__ 1533 #define __FUNCT__ "DMPlexInsertSupport" 1534 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1535 { 1536 DM_Plex *mesh = (DM_Plex*) dm->data; 1537 PetscInt pStart, pEnd; 1538 PetscInt dof, off; 1539 PetscErrorCode ierr; 1540 1541 PetscFunctionBegin; 1542 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1543 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1544 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1545 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1546 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); 1547 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); 1548 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); 1549 mesh->supports[off+supportPos] = supportPoint; 1550 PetscFunctionReturn(0); 1551 } 1552 1553 #undef __FUNCT__ 1554 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1555 /*@C 1556 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1557 1558 Not collective 1559 1560 Input Parameters: 1561 + mesh - The DMPlex 1562 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1563 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1564 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1565 1566 Output Parameters: 1567 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1568 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1569 1570 Note: 1571 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1572 1573 Level: beginner 1574 1575 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1576 @*/ 1577 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1578 { 1579 DM_Plex *mesh = (DM_Plex*) dm->data; 1580 PetscInt *closure, *fifo; 1581 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1582 PetscInt tmpSize, t; 1583 PetscInt depth = 0, maxSize; 1584 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1585 PetscErrorCode ierr; 1586 1587 PetscFunctionBegin; 1588 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1589 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1590 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1591 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1592 if (*points) { 1593 closure = *points; 1594 } else { 1595 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1596 } 1597 closure[0] = p; closure[1] = 0; 1598 /* This is only 1-level */ 1599 if (useCone) { 1600 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1601 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1602 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1603 } else { 1604 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1605 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1606 } 1607 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1608 const PetscInt cp = tmp[t]; 1609 const PetscInt co = tmpO ? tmpO[t] : 0; 1610 1611 closure[closureSize] = cp; 1612 closure[closureSize+1] = co; 1613 fifo[fifoSize] = cp; 1614 fifo[fifoSize+1] = co; 1615 } 1616 while (fifoSize - fifoStart) { 1617 const PetscInt q = fifo[fifoStart]; 1618 const PetscInt o = fifo[fifoStart+1]; 1619 const PetscInt rev = o >= 0 ? 0 : 1; 1620 const PetscInt off = rev ? -(o+1) : o; 1621 1622 if (useCone) { 1623 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1624 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1625 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1626 } else { 1627 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1628 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1629 tmpO = PETSC_NULL; 1630 } 1631 for (t = 0; t < tmpSize; ++t) { 1632 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1633 const PetscInt cp = tmp[i]; 1634 /* Must propogate orientation */ 1635 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1636 PetscInt c; 1637 1638 /* Check for duplicate */ 1639 for (c = 0; c < closureSize; c += 2) { 1640 if (closure[c] == cp) break; 1641 } 1642 if (c == closureSize) { 1643 closure[closureSize] = cp; 1644 closure[closureSize+1] = co; 1645 fifo[fifoSize] = cp; 1646 fifo[fifoSize+1] = co; 1647 closureSize += 2; 1648 fifoSize += 2; 1649 } 1650 } 1651 fifoStart += 2; 1652 } 1653 if (numPoints) *numPoints = closureSize/2; 1654 if (points) *points = closure; 1655 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1656 PetscFunctionReturn(0); 1657 } 1658 1659 #undef __FUNCT__ 1660 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1661 /*@C 1662 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1663 1664 Not collective 1665 1666 Input Parameters: 1667 + mesh - The DMPlex 1668 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1669 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1670 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1671 1672 Output Parameters: 1673 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1674 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1675 1676 Note: 1677 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1678 1679 Level: beginner 1680 1681 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1682 @*/ 1683 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1684 { 1685 PetscErrorCode ierr; 1686 1687 PetscFunctionBegin; 1688 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1689 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1690 PetscFunctionReturn(0); 1691 } 1692 1693 #undef __FUNCT__ 1694 #define __FUNCT__ "DMPlexGetFaces" 1695 /* 1696 DMPlexGetFaces - 1697 1698 Note: This will only work for cell-vertex meshes. 1699 */ 1700 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1701 { 1702 DM_Plex *mesh = (DM_Plex*) dm->data; 1703 const PetscInt *cone = PETSC_NULL; 1704 PetscInt depth = 0, dim, coneSize; 1705 PetscErrorCode ierr; 1706 1707 PetscFunctionBegin; 1708 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1709 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1710 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1711 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1712 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1713 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1714 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1715 switch (dim) { 1716 case 2: 1717 switch (coneSize) { 1718 case 3: 1719 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1720 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1721 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1722 *numFaces = 3; 1723 *faceSize = 2; 1724 *faces = mesh->facesTmp; 1725 break; 1726 case 4: 1727 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1728 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1729 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1730 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1731 *numFaces = 4; 1732 *faceSize = 2; 1733 *faces = mesh->facesTmp; 1734 break; 1735 default: 1736 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1737 } 1738 break; 1739 case 3: 1740 switch (coneSize) { 1741 case 3: 1742 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1743 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1744 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1745 *numFaces = 3; 1746 *faceSize = 2; 1747 *faces = mesh->facesTmp; 1748 break; 1749 case 4: 1750 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1751 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1752 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1753 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1754 *numFaces = 4; 1755 *faceSize = 3; 1756 *faces = mesh->facesTmp; 1757 break; 1758 default: 1759 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1760 } 1761 break; 1762 default: 1763 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1764 } 1765 PetscFunctionReturn(0); 1766 } 1767 1768 #undef __FUNCT__ 1769 #define __FUNCT__ "DMPlexGetMaxSizes" 1770 /*@ 1771 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1772 1773 Not collective 1774 1775 Input Parameter: 1776 . mesh - The DMPlex 1777 1778 Output Parameters: 1779 + maxConeSize - The maximum number of in-edges 1780 - maxSupportSize - The maximum number of out-edges 1781 1782 Level: beginner 1783 1784 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1785 @*/ 1786 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1787 { 1788 DM_Plex *mesh = (DM_Plex*) dm->data; 1789 1790 PetscFunctionBegin; 1791 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1792 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1793 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1794 PetscFunctionReturn(0); 1795 } 1796 1797 #undef __FUNCT__ 1798 #define __FUNCT__ "DMSetUp_Plex" 1799 PetscErrorCode DMSetUp_Plex(DM dm) 1800 { 1801 DM_Plex *mesh = (DM_Plex*) dm->data; 1802 PetscInt size; 1803 PetscErrorCode ierr; 1804 1805 PetscFunctionBegin; 1806 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1807 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1808 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1809 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1810 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1811 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1812 if (mesh->maxSupportSize) { 1813 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1814 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1815 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1816 } 1817 PetscFunctionReturn(0); 1818 } 1819 1820 #undef __FUNCT__ 1821 #define __FUNCT__ "DMCreateSubDM_Plex" 1822 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1823 { 1824 PetscSection section, sectionGlobal; 1825 PetscInt *subIndices; 1826 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1827 PetscErrorCode ierr; 1828 1829 PetscFunctionBegin; 1830 if (!numFields) PetscFunctionReturn(0); 1831 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1832 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1833 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1834 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1835 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1836 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); 1837 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1838 for (p = pStart; p < pEnd; ++p) { 1839 PetscInt gdof; 1840 1841 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1842 if (gdof > 0) { 1843 for (f = 0; f < numFields; ++f) { 1844 PetscInt fdof, fcdof; 1845 1846 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1847 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1848 subSize += fdof-fcdof; 1849 } 1850 } 1851 } 1852 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1853 for (p = pStart; p < pEnd; ++p) { 1854 PetscInt gdof, goff; 1855 1856 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1857 if (gdof > 0) { 1858 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1859 for (f = 0; f < numFields; ++f) { 1860 PetscInt fdof, fcdof, fc, f2, poff = 0; 1861 1862 /* Can get rid of this loop by storing field information in the global section */ 1863 for (f2 = 0; f2 < fields[f]; ++f2) { 1864 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1865 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1866 poff += fdof-fcdof; 1867 } 1868 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1869 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1870 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1871 subIndices[subOff] = goff+poff+fc; 1872 } 1873 } 1874 } 1875 } 1876 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1877 if (subdm) { 1878 PetscSection subsection; 1879 PetscBool haveNull = PETSC_FALSE; 1880 PetscInt f, nf = 0; 1881 1882 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1883 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1884 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1885 for (f = 0; f < numFields; ++f) { 1886 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1887 if ((*subdm)->nullspaceConstructors[f]) { 1888 haveNull = PETSC_TRUE; 1889 nf = f; 1890 } 1891 } 1892 if (haveNull) { 1893 MatNullSpace nullSpace; 1894 1895 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1896 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1897 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1898 } 1899 if (dm->fields) { 1900 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); 1901 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1902 for (f = 0; f < numFields; ++f) { 1903 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1904 } 1905 if (numFields == 1) { 1906 MatNullSpace space; 1907 Mat pmat; 1908 1909 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1910 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1911 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1912 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1913 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1914 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1915 } 1916 } 1917 } 1918 PetscFunctionReturn(0); 1919 } 1920 1921 #undef __FUNCT__ 1922 #define __FUNCT__ "DMPlexSymmetrize" 1923 /*@ 1924 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1925 1926 Not collective 1927 1928 Input Parameter: 1929 . mesh - The DMPlex 1930 1931 Output Parameter: 1932 1933 Note: 1934 This should be called after all calls to DMPlexSetCone() 1935 1936 Level: beginner 1937 1938 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1939 @*/ 1940 PetscErrorCode DMPlexSymmetrize(DM dm) 1941 { 1942 DM_Plex *mesh = (DM_Plex*) dm->data; 1943 PetscInt *offsets; 1944 PetscInt supportSize; 1945 PetscInt pStart, pEnd, p; 1946 PetscErrorCode ierr; 1947 1948 PetscFunctionBegin; 1949 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1950 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1951 /* Calculate support sizes */ 1952 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1953 for (p = pStart; p < pEnd; ++p) { 1954 PetscInt dof, off, c; 1955 1956 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1957 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1958 for (c = off; c < off+dof; ++c) { 1959 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1960 } 1961 } 1962 for (p = pStart; p < pEnd; ++p) { 1963 PetscInt dof; 1964 1965 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1966 1967 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1968 } 1969 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1970 /* Calculate supports */ 1971 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1972 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1973 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1974 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1975 for (p = pStart; p < pEnd; ++p) { 1976 PetscInt dof, off, c; 1977 1978 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1979 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1980 for (c = off; c < off+dof; ++c) { 1981 const PetscInt q = mesh->cones[c]; 1982 PetscInt offS; 1983 1984 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1985 1986 mesh->supports[offS+offsets[q]] = p; 1987 ++offsets[q]; 1988 } 1989 } 1990 ierr = PetscFree(offsets);CHKERRQ(ierr); 1991 PetscFunctionReturn(0); 1992 } 1993 1994 #undef __FUNCT__ 1995 #define __FUNCT__ "DMPlexSetDepth_Private" 1996 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1997 { 1998 PetscInt d; 1999 PetscErrorCode ierr; 2000 2001 PetscFunctionBegin; 2002 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 2003 if (d < 0) { 2004 /* We are guaranteed that the point has a cone since the depth was not yet set */ 2005 const PetscInt *cone = PETSC_NULL; 2006 PetscInt dCone; 2007 2008 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2009 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2010 d = dCone+1; 2011 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2012 } 2013 *depth = d; 2014 PetscFunctionReturn(0); 2015 } 2016 2017 #undef __FUNCT__ 2018 #define __FUNCT__ "DMPlexStratify" 2019 /*@ 2020 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2021 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2022 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2023 the DAG. 2024 2025 Not collective 2026 2027 Input Parameter: 2028 . mesh - The DMPlex 2029 2030 Output Parameter: 2031 2032 Notes: 2033 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2034 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2035 2036 This should be called after all calls to DMPlexSymmetrize() 2037 2038 Level: beginner 2039 2040 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2041 @*/ 2042 PetscErrorCode DMPlexStratify(DM dm) 2043 { 2044 DM_Plex *mesh = (DM_Plex*) dm->data; 2045 PetscInt pStart, pEnd, p; 2046 PetscInt numRoots = 0, numLeaves = 0; 2047 PetscErrorCode ierr; 2048 2049 PetscFunctionBegin; 2050 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2051 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2052 /* Calculate depth */ 2053 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2054 /* Initialize roots and count leaves */ 2055 for (p = pStart; p < pEnd; ++p) { 2056 PetscInt coneSize, supportSize; 2057 2058 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2059 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2060 if (!coneSize && supportSize) { 2061 ++numRoots; 2062 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2063 } else if (!supportSize && coneSize) { 2064 ++numLeaves; 2065 } else if (!supportSize && !coneSize) { 2066 /* Isolated points */ 2067 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2068 } 2069 } 2070 if (numRoots + numLeaves == (pEnd - pStart)) { 2071 for (p = pStart; p < pEnd; ++p) { 2072 PetscInt coneSize, supportSize; 2073 2074 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2075 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2076 if (!supportSize && coneSize) { 2077 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2078 } 2079 } 2080 } else { 2081 /* This might be slow since lookup is not fast */ 2082 for (p = pStart; p < pEnd; ++p) { 2083 PetscInt depth; 2084 2085 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2086 } 2087 } 2088 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2089 PetscFunctionReturn(0); 2090 } 2091 2092 #undef __FUNCT__ 2093 #define __FUNCT__ "DMPlexGetJoin" 2094 /*@C 2095 DMPlexGetJoin - Get an array for the join of the set of points 2096 2097 Not Collective 2098 2099 Input Parameters: 2100 + dm - The DMPlex object 2101 . numPoints - The number of input points for the join 2102 - points - The input points 2103 2104 Output Parameters: 2105 + numCoveredPoints - The number of points in the join 2106 - coveredPoints - The points in the join 2107 2108 Level: intermediate 2109 2110 Note: Currently, this is restricted to a single level join 2111 2112 .keywords: mesh 2113 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2114 @*/ 2115 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2116 { 2117 DM_Plex *mesh = (DM_Plex*) dm->data; 2118 PetscInt *join[2]; 2119 PetscInt joinSize, i = 0; 2120 PetscInt dof, off, p, c, m; 2121 PetscErrorCode ierr; 2122 2123 PetscFunctionBegin; 2124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2125 PetscValidPointer(points, 2); 2126 PetscValidPointer(numCoveredPoints, 3); 2127 PetscValidPointer(coveredPoints, 4); 2128 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2129 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2130 /* Copy in support of first point */ 2131 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2132 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2133 for (joinSize = 0; joinSize < dof; ++joinSize) { 2134 join[i][joinSize] = mesh->supports[off+joinSize]; 2135 } 2136 /* Check each successive support */ 2137 for (p = 1; p < numPoints; ++p) { 2138 PetscInt newJoinSize = 0; 2139 2140 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2141 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2142 for (c = 0; c < dof; ++c) { 2143 const PetscInt point = mesh->supports[off+c]; 2144 2145 for (m = 0; m < joinSize; ++m) { 2146 if (point == join[i][m]) { 2147 join[1-i][newJoinSize++] = point; 2148 break; 2149 } 2150 } 2151 } 2152 joinSize = newJoinSize; 2153 i = 1-i; 2154 } 2155 *numCoveredPoints = joinSize; 2156 *coveredPoints = join[i]; 2157 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2158 PetscFunctionReturn(0); 2159 } 2160 2161 #undef __FUNCT__ 2162 #define __FUNCT__ "DMPlexRestoreJoin" 2163 /*@C 2164 DMPlexRestoreJoin - Restore an array for the join of the set of points 2165 2166 Not Collective 2167 2168 Input Parameters: 2169 + dm - The DMPlex object 2170 . numPoints - The number of input points for the join 2171 - points - The input points 2172 2173 Output Parameters: 2174 + numCoveredPoints - The number of points in the join 2175 - coveredPoints - The points in the join 2176 2177 Level: intermediate 2178 2179 .keywords: mesh 2180 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2181 @*/ 2182 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2183 { 2184 PetscErrorCode ierr; 2185 2186 PetscFunctionBegin; 2187 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2188 PetscValidPointer(coveredPoints, 4); 2189 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2190 PetscFunctionReturn(0); 2191 } 2192 2193 #undef __FUNCT__ 2194 #define __FUNCT__ "DMPlexGetFullJoin" 2195 /*@C 2196 DMPlexGetFullJoin - Get an array for the join of the set of points 2197 2198 Not Collective 2199 2200 Input Parameters: 2201 + dm - The DMPlex object 2202 . numPoints - The number of input points for the join 2203 - points - The input points 2204 2205 Output Parameters: 2206 + numCoveredPoints - The number of points in the join 2207 - coveredPoints - The points in the join 2208 2209 Level: intermediate 2210 2211 .keywords: mesh 2212 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2213 @*/ 2214 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2215 { 2216 DM_Plex *mesh = (DM_Plex*) dm->data; 2217 PetscInt *offsets, **closures; 2218 PetscInt *join[2]; 2219 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2220 PetscInt p, d, c, m; 2221 PetscErrorCode ierr; 2222 2223 PetscFunctionBegin; 2224 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2225 PetscValidPointer(points, 2); 2226 PetscValidPointer(numCoveredPoints, 3); 2227 PetscValidPointer(coveredPoints, 4); 2228 2229 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2230 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2231 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2232 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2233 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2234 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2235 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2236 2237 for (p = 0; p < numPoints; ++p) { 2238 PetscInt closureSize; 2239 2240 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2241 2242 offsets[p*(depth+2)+0] = 0; 2243 for (d = 0; d < depth+1; ++d) { 2244 PetscInt pStart, pEnd, i; 2245 2246 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2247 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2248 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2249 offsets[p*(depth+2)+d+1] = i; 2250 break; 2251 } 2252 } 2253 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2254 } 2255 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); 2256 } 2257 for (d = 0; d < depth+1; ++d) { 2258 PetscInt dof; 2259 2260 /* Copy in support of first point */ 2261 dof = offsets[d+1] - offsets[d]; 2262 for (joinSize = 0; joinSize < dof; ++joinSize) { 2263 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2264 } 2265 /* Check each successive cone */ 2266 for (p = 1; p < numPoints && joinSize; ++p) { 2267 PetscInt newJoinSize = 0; 2268 2269 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2270 for (c = 0; c < dof; ++c) { 2271 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2272 2273 for (m = 0; m < joinSize; ++m) { 2274 if (point == join[i][m]) { 2275 join[1-i][newJoinSize++] = point; 2276 break; 2277 } 2278 } 2279 } 2280 joinSize = newJoinSize; 2281 i = 1-i; 2282 } 2283 if (joinSize) break; 2284 } 2285 *numCoveredPoints = joinSize; 2286 *coveredPoints = join[i]; 2287 for (p = 0; p < numPoints; ++p) { 2288 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2289 } 2290 ierr = PetscFree(closures);CHKERRQ(ierr); 2291 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2292 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2293 PetscFunctionReturn(0); 2294 } 2295 2296 #undef __FUNCT__ 2297 #define __FUNCT__ "DMPlexGetMeet" 2298 /*@C 2299 DMPlexGetMeet - Get an array for the meet of the set of points 2300 2301 Not Collective 2302 2303 Input Parameters: 2304 + dm - The DMPlex object 2305 . numPoints - The number of input points for the meet 2306 - points - The input points 2307 2308 Output Parameters: 2309 + numCoveredPoints - The number of points in the meet 2310 - coveredPoints - The points in the meet 2311 2312 Level: intermediate 2313 2314 Note: Currently, this is restricted to a single level meet 2315 2316 .keywords: mesh 2317 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2318 @*/ 2319 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2320 { 2321 DM_Plex *mesh = (DM_Plex*) dm->data; 2322 PetscInt *meet[2]; 2323 PetscInt meetSize, i = 0; 2324 PetscInt dof, off, p, c, m; 2325 PetscErrorCode ierr; 2326 2327 PetscFunctionBegin; 2328 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2329 PetscValidPointer(points, 2); 2330 PetscValidPointer(numCoveringPoints, 3); 2331 PetscValidPointer(coveringPoints, 4); 2332 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2333 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2334 /* Copy in cone of first point */ 2335 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2336 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2337 for (meetSize = 0; meetSize < dof; ++meetSize) { 2338 meet[i][meetSize] = mesh->cones[off+meetSize]; 2339 } 2340 /* Check each successive cone */ 2341 for (p = 1; p < numPoints; ++p) { 2342 PetscInt newMeetSize = 0; 2343 2344 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2345 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2346 for (c = 0; c < dof; ++c) { 2347 const PetscInt point = mesh->cones[off+c]; 2348 2349 for (m = 0; m < meetSize; ++m) { 2350 if (point == meet[i][m]) { 2351 meet[1-i][newMeetSize++] = point; 2352 break; 2353 } 2354 } 2355 } 2356 meetSize = newMeetSize; 2357 i = 1-i; 2358 } 2359 *numCoveringPoints = meetSize; 2360 *coveringPoints = meet[i]; 2361 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2362 PetscFunctionReturn(0); 2363 } 2364 2365 #undef __FUNCT__ 2366 #define __FUNCT__ "DMPlexRestoreMeet" 2367 /*@C 2368 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2369 2370 Not Collective 2371 2372 Input Parameters: 2373 + dm - The DMPlex object 2374 . numPoints - The number of input points for the meet 2375 - points - The input points 2376 2377 Output Parameters: 2378 + numCoveredPoints - The number of points in the meet 2379 - coveredPoints - The points in the meet 2380 2381 Level: intermediate 2382 2383 .keywords: mesh 2384 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2385 @*/ 2386 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2387 { 2388 PetscErrorCode ierr; 2389 2390 PetscFunctionBegin; 2391 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2392 PetscValidPointer(coveredPoints, 4); 2393 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2394 PetscFunctionReturn(0); 2395 } 2396 2397 #undef __FUNCT__ 2398 #define __FUNCT__ "DMPlexGetFullMeet" 2399 /*@C 2400 DMPlexGetFullMeet - Get an array for the meet of the set of points 2401 2402 Not Collective 2403 2404 Input Parameters: 2405 + dm - The DMPlex object 2406 . numPoints - The number of input points for the meet 2407 - points - The input points 2408 2409 Output Parameters: 2410 + numCoveredPoints - The number of points in the meet 2411 - coveredPoints - The points in the meet 2412 2413 Level: intermediate 2414 2415 .keywords: mesh 2416 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2417 @*/ 2418 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2419 { 2420 DM_Plex *mesh = (DM_Plex*) dm->data; 2421 PetscInt *offsets, **closures; 2422 PetscInt *meet[2]; 2423 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2424 PetscInt p, h, c, m; 2425 PetscErrorCode ierr; 2426 2427 PetscFunctionBegin; 2428 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2429 PetscValidPointer(points, 2); 2430 PetscValidPointer(numCoveredPoints, 3); 2431 PetscValidPointer(coveredPoints, 4); 2432 2433 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2434 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2435 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2436 maxSize = PetscPowInt(mesh->maxConeSize,height); 2437 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2438 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2439 2440 for (p = 0; p < numPoints; ++p) { 2441 PetscInt closureSize; 2442 2443 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2444 2445 offsets[p*(height+2)+0] = 0; 2446 for (h = 0; h < height+1; ++h) { 2447 PetscInt pStart, pEnd, i; 2448 2449 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2450 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2451 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2452 offsets[p*(height+2)+h+1] = i; 2453 break; 2454 } 2455 } 2456 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2457 } 2458 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); 2459 } 2460 for (h = 0; h < height+1; ++h) { 2461 PetscInt dof; 2462 2463 /* Copy in cone of first point */ 2464 dof = offsets[h+1] - offsets[h]; 2465 for (meetSize = 0; meetSize < dof; ++meetSize) { 2466 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2467 } 2468 /* Check each successive cone */ 2469 for (p = 1; p < numPoints && meetSize; ++p) { 2470 PetscInt newMeetSize = 0; 2471 2472 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2473 for (c = 0; c < dof; ++c) { 2474 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2475 2476 for (m = 0; m < meetSize; ++m) { 2477 if (point == meet[i][m]) { 2478 meet[1-i][newMeetSize++] = point; 2479 break; 2480 } 2481 } 2482 } 2483 meetSize = newMeetSize; 2484 i = 1-i; 2485 } 2486 if (meetSize) break; 2487 } 2488 *numCoveredPoints = meetSize; 2489 *coveredPoints = meet[i]; 2490 for (p = 0; p < numPoints; ++p) { 2491 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2492 } 2493 ierr = PetscFree(closures);CHKERRQ(ierr); 2494 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2495 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2496 PetscFunctionReturn(0); 2497 } 2498 2499 #undef __FUNCT__ 2500 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2501 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2502 { 2503 MPI_Comm comm = ((PetscObject) dm)->comm; 2504 PetscInt cellDim; 2505 PetscErrorCode ierr; 2506 2507 PetscFunctionBegin; 2508 PetscValidPointer(numFaceVertices,3); 2509 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2510 switch (cellDim) { 2511 case 0: 2512 *numFaceVertices = 0; 2513 break; 2514 case 1: 2515 *numFaceVertices = 1; 2516 break; 2517 case 2: 2518 switch (numCorners) { 2519 case 3: /* triangle */ 2520 *numFaceVertices = 2; /* Edge has 2 vertices */ 2521 break; 2522 case 4: /* quadrilateral */ 2523 *numFaceVertices = 2; /* Edge has 2 vertices */ 2524 break; 2525 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2526 *numFaceVertices = 3; /* Edge has 3 vertices */ 2527 break; 2528 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2529 *numFaceVertices = 3; /* Edge has 3 vertices */ 2530 break; 2531 default: 2532 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2533 } 2534 break; 2535 case 3: 2536 switch (numCorners) { 2537 case 4: /* tetradehdron */ 2538 *numFaceVertices = 3; /* Face has 3 vertices */ 2539 break; 2540 case 6: /* tet cohesive cells */ 2541 *numFaceVertices = 4; /* Face has 4 vertices */ 2542 break; 2543 case 8: /* hexahedron */ 2544 *numFaceVertices = 4; /* Face has 4 vertices */ 2545 break; 2546 case 9: /* tet cohesive Lagrange cells */ 2547 *numFaceVertices = 6; /* Face has 6 vertices */ 2548 break; 2549 case 10: /* quadratic tetrahedron */ 2550 *numFaceVertices = 6; /* Face has 6 vertices */ 2551 break; 2552 case 12: /* hex cohesive Lagrange cells */ 2553 *numFaceVertices = 6; /* Face has 6 vertices */ 2554 break; 2555 case 18: /* quadratic tet cohesive Lagrange cells */ 2556 *numFaceVertices = 6; /* Face has 6 vertices */ 2557 break; 2558 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2559 *numFaceVertices = 9; /* Face has 9 vertices */ 2560 break; 2561 default: 2562 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2563 } 2564 break; 2565 default: 2566 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2567 } 2568 PetscFunctionReturn(0); 2569 } 2570 2571 #undef __FUNCT__ 2572 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2573 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2574 { 2575 const PetscInt maxFaceCases = 30; 2576 PetscInt numFaceCases = 0; 2577 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2578 PetscInt *off, *adj; 2579 PetscInt *neighborCells, *tmpClosure; 2580 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2581 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2582 PetscErrorCode ierr; 2583 2584 PetscFunctionBegin; 2585 /* For parallel partitioning, I think you have to communicate supports */ 2586 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2587 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2588 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2589 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2590 if (cEnd - cStart == 0) { 2591 if (numVertices) *numVertices = 0; 2592 if (offsets) *offsets = PETSC_NULL; 2593 if (adjacency) *adjacency = PETSC_NULL; 2594 PetscFunctionReturn(0); 2595 } 2596 numCells = cEnd - cStart; 2597 /* Setup face recognition */ 2598 if (depth == 1) { 2599 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 */ 2600 2601 for (c = cStart; c < cEnd; ++c) { 2602 PetscInt corners; 2603 2604 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2605 if (!cornersSeen[corners]) { 2606 PetscInt nFV; 2607 2608 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2609 cornersSeen[corners] = 1; 2610 2611 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2612 2613 numFaceVertices[numFaceCases++] = nFV; 2614 } 2615 } 2616 } 2617 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2618 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2619 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2620 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2621 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2622 /* Count neighboring cells */ 2623 for (cell = cStart; cell < cEnd; ++cell) { 2624 PetscInt numNeighbors = maxNeighbors, n; 2625 2626 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2627 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2628 for (n = 0; n < numNeighbors; ++n) { 2629 PetscInt cellPair[2]; 2630 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2631 PetscInt meetSize = 0; 2632 const PetscInt *meet = PETSC_NULL; 2633 2634 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2635 if (cellPair[0] == cellPair[1]) continue; 2636 if (!found) { 2637 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2638 if (meetSize) { 2639 PetscInt f; 2640 2641 for (f = 0; f < numFaceCases; ++f) { 2642 if (numFaceVertices[f] == meetSize) { 2643 found = PETSC_TRUE; 2644 break; 2645 } 2646 } 2647 } 2648 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2649 } 2650 if (found) ++off[cell-cStart+1]; 2651 } 2652 } 2653 /* Prefix sum */ 2654 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2655 2656 if (adjacency) { 2657 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2658 /* Get neighboring cells */ 2659 for (cell = cStart; cell < cEnd; ++cell) { 2660 PetscInt numNeighbors = maxNeighbors, n; 2661 PetscInt cellOffset = 0; 2662 2663 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2664 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2665 for (n = 0; n < numNeighbors; ++n) { 2666 PetscInt cellPair[2]; 2667 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2668 PetscInt meetSize = 0; 2669 const PetscInt *meet = PETSC_NULL; 2670 2671 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2672 if (cellPair[0] == cellPair[1]) continue; 2673 if (!found) { 2674 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2675 if (meetSize) { 2676 PetscInt f; 2677 2678 for (f = 0; f < numFaceCases; ++f) { 2679 if (numFaceVertices[f] == meetSize) { 2680 found = PETSC_TRUE; 2681 break; 2682 } 2683 } 2684 } 2685 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2686 } 2687 if (found) { 2688 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2689 ++cellOffset; 2690 } 2691 } 2692 } 2693 } 2694 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2695 if (numVertices) *numVertices = numCells; 2696 if (offsets) *offsets = off; 2697 if (adjacency) *adjacency = adj; 2698 PetscFunctionReturn(0); 2699 } 2700 2701 #if defined(PETSC_HAVE_CHACO) 2702 #if defined(PETSC_HAVE_UNISTD_H) 2703 #include <unistd.h> 2704 #endif 2705 /* Chaco does not have an include file */ 2706 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2707 float *ewgts, float *x, float *y, float *z, char *outassignname, 2708 char *outfilename, short *assignment, int architecture, int ndims_tot, 2709 int mesh_dims[3], double *goal, int global_method, int local_method, 2710 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2711 2712 extern int FREE_GRAPH; 2713 2714 #undef __FUNCT__ 2715 #define __FUNCT__ "DMPlexPartition_Chaco" 2716 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2717 { 2718 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2719 MPI_Comm comm = ((PetscObject) dm)->comm; 2720 int nvtxs = numVertices; /* number of vertices in full graph */ 2721 int *vwgts = NULL; /* weights for all vertices */ 2722 float *ewgts = NULL; /* weights for all edges */ 2723 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2724 char *outassignname = NULL; /* name of assignment output file */ 2725 char *outfilename = NULL; /* output file name */ 2726 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2727 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2728 int mesh_dims[3]; /* dimensions of mesh of processors */ 2729 double *goal = NULL; /* desired set sizes for each set */ 2730 int global_method = 1; /* global partitioning algorithm */ 2731 int local_method = 1; /* local partitioning algorithm */ 2732 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2733 int vmax = 200; /* how many vertices to coarsen down to? */ 2734 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2735 double eigtol = 0.001; /* tolerance on eigenvectors */ 2736 long seed = 123636512; /* for random graph mutations */ 2737 short int *assignment; /* Output partition */ 2738 int fd_stdout, fd_pipe[2]; 2739 PetscInt *points; 2740 PetscMPIInt commSize; 2741 int i, v, p; 2742 PetscErrorCode ierr; 2743 2744 PetscFunctionBegin; 2745 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2746 if (!numVertices) { 2747 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2748 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2749 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2750 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2751 PetscFunctionReturn(0); 2752 } 2753 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2754 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2755 2756 if (global_method == INERTIAL_METHOD) { 2757 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2758 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2759 } 2760 mesh_dims[0] = commSize; 2761 mesh_dims[1] = 1; 2762 mesh_dims[2] = 1; 2763 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2764 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2765 /* TODO: check error codes for UNIX calls */ 2766 #if defined(PETSC_HAVE_UNISTD_H) 2767 { 2768 int piperet; 2769 piperet = pipe(fd_pipe); 2770 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2771 fd_stdout = dup(1); 2772 close(1); 2773 dup2(fd_pipe[1], 1); 2774 } 2775 #endif 2776 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2777 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2778 vmax, ndims, eigtol, seed); 2779 #if defined(PETSC_HAVE_UNISTD_H) 2780 { 2781 char msgLog[10000]; 2782 int count; 2783 2784 fflush(stdout); 2785 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2786 if (count < 0) count = 0; 2787 msgLog[count] = 0; 2788 close(1); 2789 dup2(fd_stdout, 1); 2790 close(fd_stdout); 2791 close(fd_pipe[0]); 2792 close(fd_pipe[1]); 2793 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2794 } 2795 #endif 2796 /* Convert to PetscSection+IS */ 2797 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2798 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2799 for (v = 0; v < nvtxs; ++v) { 2800 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2801 } 2802 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2803 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2804 for (p = 0, i = 0; p < commSize; ++p) { 2805 for (v = 0; v < nvtxs; ++v) { 2806 if (assignment[v] == p) points[i++] = v; 2807 } 2808 } 2809 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2810 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2811 if (global_method == INERTIAL_METHOD) { 2812 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2813 } 2814 ierr = PetscFree(assignment);CHKERRQ(ierr); 2815 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2816 PetscFunctionReturn(0); 2817 } 2818 #endif 2819 2820 #if defined(PETSC_HAVE_PARMETIS) 2821 #undef __FUNCT__ 2822 #define __FUNCT__ "DMPlexPartition_ParMetis" 2823 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2824 { 2825 PetscFunctionBegin; 2826 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2827 PetscFunctionReturn(0); 2828 } 2829 #endif 2830 2831 #undef __FUNCT__ 2832 #define __FUNCT__ "DMPlexEnlargePartition" 2833 /* Expand the partition by BFS on the adjacency graph */ 2834 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2835 { 2836 PetscHashI h; 2837 const PetscInt *points; 2838 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2839 PetscInt pStart, pEnd, part, q; 2840 PetscErrorCode ierr; 2841 2842 PetscFunctionBegin; 2843 PetscHashICreate(h); 2844 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2845 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2846 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2847 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2848 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2849 for (part = pStart; part < pEnd; ++part) { 2850 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2851 2852 PetscHashIClear(h); 2853 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2854 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2855 /* Add all existing points to h */ 2856 for (p = 0; p < numPoints; ++p) { 2857 const PetscInt point = points[off+p]; 2858 PetscHashIAdd(h, point, 1); 2859 } 2860 PetscHashISize(h, nP); 2861 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2862 /* Add all points in next BFS level */ 2863 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2864 for (p = 0; p < numPoints; ++p) { 2865 const PetscInt point = points[off+p]; 2866 PetscInt s = start[point], e = start[point+1], a; 2867 2868 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2869 } 2870 PetscHashISize(h, numNewPoints); 2871 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2872 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2873 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2874 totPoints += numNewPoints; 2875 } 2876 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2877 PetscHashIDestroy(h); 2878 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2879 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2880 for (part = pStart, q = 0; part < pEnd; ++part) { 2881 PetscInt numPoints, p; 2882 2883 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2884 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2885 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2886 } 2887 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2888 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2889 PetscFunctionReturn(0); 2890 } 2891 2892 #undef __FUNCT__ 2893 #define __FUNCT__ "DMPlexCreatePartition" 2894 /* 2895 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2896 2897 Collective on DM 2898 2899 Input Parameters: 2900 + dm - The DM 2901 . height - The height for points in the partition 2902 - enlarge - Expand each partition with neighbors 2903 2904 Output Parameters: 2905 + partSection - The PetscSection giving the division of points by partition 2906 . partition - The list of points by partition 2907 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2908 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2909 2910 Level: developer 2911 2912 .seealso DMPlexDistribute() 2913 */ 2914 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2915 { 2916 PetscMPIInt size; 2917 PetscErrorCode ierr; 2918 2919 PetscFunctionBegin; 2920 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2921 2922 *origPartSection = PETSC_NULL; 2923 *origPartition = PETSC_NULL; 2924 if (size == 1) { 2925 PetscInt *points; 2926 PetscInt cStart, cEnd, c; 2927 2928 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2929 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2930 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2931 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2932 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2933 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2934 for (c = cStart; c < cEnd; ++c) points[c] = c; 2935 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2936 PetscFunctionReturn(0); 2937 } 2938 if (height == 0) { 2939 PetscInt numVertices; 2940 PetscInt *start = PETSC_NULL; 2941 PetscInt *adjacency = PETSC_NULL; 2942 2943 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2944 if (1) { 2945 #if defined(PETSC_HAVE_CHACO) 2946 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2947 #endif 2948 } else { 2949 #if defined(PETSC_HAVE_PARMETIS) 2950 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2951 #endif 2952 } 2953 if (enlarge) { 2954 *origPartSection = *partSection; 2955 *origPartition = *partition; 2956 2957 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2958 } 2959 ierr = PetscFree(start);CHKERRQ(ierr); 2960 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2961 # if 0 2962 } else if (height == 1) { 2963 /* Build the dual graph for faces and partition the hypergraph */ 2964 PetscInt numEdges; 2965 2966 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2967 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2968 destroyCSR(numEdges, start, adjacency); 2969 #endif 2970 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2971 PetscFunctionReturn(0); 2972 } 2973 2974 #undef __FUNCT__ 2975 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2976 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2977 { 2978 /* const PetscInt height = 0; */ 2979 const PetscInt *partArray; 2980 PetscInt *allPoints, *partPoints = PETSC_NULL; 2981 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2982 PetscErrorCode ierr; 2983 2984 PetscFunctionBegin; 2985 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2986 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2987 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2988 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2989 for (rank = rStart; rank < rEnd; ++rank) { 2990 PetscInt partSize = 0; 2991 PetscInt numPoints, offset, p; 2992 2993 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2994 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2995 for (p = 0; p < numPoints; ++p) { 2996 PetscInt point = partArray[offset+p], closureSize, c; 2997 PetscInt *closure = PETSC_NULL; 2998 2999 /* TODO Include support for height > 0 case */ 3000 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3001 /* Merge into existing points */ 3002 if (partSize+closureSize > maxPartSize) { 3003 PetscInt *tmpPoints; 3004 3005 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 3006 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 3007 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3008 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3009 3010 partPoints = tmpPoints; 3011 } 3012 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3013 partSize += closureSize; 3014 3015 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3016 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3017 } 3018 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3019 } 3020 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3021 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3022 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3023 3024 for (rank = rStart; rank < rEnd; ++rank) { 3025 PetscInt partSize = 0, newOffset; 3026 PetscInt numPoints, offset, p; 3027 3028 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3029 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3030 for (p = 0; p < numPoints; ++p) { 3031 PetscInt point = partArray[offset+p], closureSize, c; 3032 PetscInt *closure = PETSC_NULL; 3033 3034 /* TODO Include support for height > 0 case */ 3035 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3036 /* Merge into existing points */ 3037 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3038 partSize += closureSize; 3039 3040 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3041 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3042 } 3043 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3044 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3045 } 3046 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3047 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3048 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3049 PetscFunctionReturn(0); 3050 } 3051 3052 #undef __FUNCT__ 3053 #define __FUNCT__ "DMPlexDistributeField" 3054 /* 3055 Input Parameters: 3056 . originalSection 3057 , originalVec 3058 3059 Output Parameters: 3060 . newSection 3061 . newVec 3062 */ 3063 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3064 { 3065 PetscSF fieldSF; 3066 PetscInt *remoteOffsets, fieldSize; 3067 PetscScalar *originalValues, *newValues; 3068 PetscErrorCode ierr; 3069 3070 PetscFunctionBegin; 3071 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3072 3073 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3074 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3075 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3076 3077 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3078 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3079 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3080 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3081 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3082 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3083 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3084 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3085 PetscFunctionReturn(0); 3086 } 3087 3088 #undef __FUNCT__ 3089 #define __FUNCT__ "DMPlexDistribute" 3090 /*@C 3091 DMPlexDistribute - Distributes the mesh and any associated sections. 3092 3093 Not Collective 3094 3095 Input Parameter: 3096 + dm - The original DMPlex object 3097 . partitioner - The partitioning package, or NULL for the default 3098 - overlap - The overlap of partitions, 0 is the default 3099 3100 Output Parameter: 3101 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3102 3103 Note: If the mesh was not distributed, the return value is PETSC_NULL 3104 3105 Level: intermediate 3106 3107 .keywords: mesh, elements 3108 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3109 @*/ 3110 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3111 { 3112 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3113 MPI_Comm comm = ((PetscObject) dm)->comm; 3114 const PetscInt height = 0; 3115 PetscInt dim, numRemoteRanks; 3116 IS origCellPart, cellPart, part; 3117 PetscSection origCellPartSection, cellPartSection, partSection; 3118 PetscSFNode *remoteRanks; 3119 PetscSF partSF, pointSF, coneSF; 3120 ISLocalToGlobalMapping renumbering; 3121 PetscSection originalConeSection, newConeSection; 3122 PetscInt *remoteOffsets; 3123 PetscInt *cones, *newCones, newConesSize; 3124 PetscBool flg; 3125 PetscMPIInt rank, numProcs, p; 3126 PetscErrorCode ierr; 3127 3128 PetscFunctionBegin; 3129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3130 PetscValidPointer(dmParallel,4); 3131 3132 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3133 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3134 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3135 3136 *dmParallel = PETSC_NULL; 3137 if (numProcs == 1) PetscFunctionReturn(0); 3138 3139 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3140 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3141 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3142 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3143 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3144 if (!rank) numRemoteRanks = numProcs; 3145 else numRemoteRanks = 0; 3146 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3147 for (p = 0; p < numRemoteRanks; ++p) { 3148 remoteRanks[p].rank = p; 3149 remoteRanks[p].index = 0; 3150 } 3151 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3152 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3153 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3154 if (flg) { 3155 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3156 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3157 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3158 if (origCellPart) { 3159 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3160 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3161 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3162 } 3163 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3164 } 3165 /* Close the partition over the mesh */ 3166 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3167 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3168 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3169 /* Create new mesh */ 3170 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3171 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3172 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3173 pmesh = (DM_Plex*) (*dmParallel)->data; 3174 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3175 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3176 if (flg) { 3177 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3178 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3179 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3180 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3181 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3182 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3183 } 3184 /* Distribute cone section */ 3185 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3186 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3187 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3188 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3189 { 3190 PetscInt pStart, pEnd, p; 3191 3192 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3193 for (p = pStart; p < pEnd; ++p) { 3194 PetscInt coneSize; 3195 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3196 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3197 } 3198 } 3199 /* Communicate and renumber cones */ 3200 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3201 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3202 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3203 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3204 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3205 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3206 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3207 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3208 if (flg) { 3209 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3210 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3211 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3212 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3213 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3214 } 3215 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3216 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3217 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3218 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3219 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3220 /* Create supports and stratify sieve */ 3221 { 3222 PetscInt pStart, pEnd; 3223 3224 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3225 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3226 } 3227 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3228 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3229 /* Distribute Coordinates */ 3230 { 3231 PetscSection originalCoordSection, newCoordSection; 3232 Vec originalCoordinates, newCoordinates; 3233 const char *name; 3234 3235 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3236 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3237 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3238 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3239 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3240 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3241 3242 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3243 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3244 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3245 } 3246 /* Distribute labels */ 3247 { 3248 DMLabel next = mesh->labels, newNext = pmesh->labels; 3249 PetscInt numLabels = 0, l; 3250 3251 /* Bcast number of labels */ 3252 while (next) { 3253 ++numLabels; next = next->next; 3254 } 3255 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3256 next = mesh->labels; 3257 for (l = 0; l < numLabels; ++l) { 3258 DMLabel newLabel; 3259 const PetscInt *partArray; 3260 char *name; 3261 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3262 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3263 PetscInt nameSize, s, p; 3264 PetscBool isdepth; 3265 size_t len = 0; 3266 3267 /* Bcast name (could filter for no points) */ 3268 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3269 nameSize = len; 3270 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3271 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3272 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3273 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3274 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3275 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3276 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3277 newLabel->name = name; 3278 /* Bcast numStrata (could filter for no points in stratum) */ 3279 if (!rank) newLabel->numStrata = next->numStrata; 3280 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3281 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3282 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3283 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3284 /* Bcast stratumValues (could filter for no points in stratum) */ 3285 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3286 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3287 /* Find size on each process and Scatter */ 3288 if (!rank) { 3289 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3290 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3291 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3292 for (s = 0; s < next->numStrata; ++s) { 3293 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3294 const PetscInt point = next->points[p]; 3295 PetscInt proc; 3296 3297 for (proc = 0; proc < numProcs; ++proc) { 3298 PetscInt dof, off, pPart; 3299 3300 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3301 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3302 for (pPart = off; pPart < off+dof; ++pPart) { 3303 if (partArray[pPart] == point) { 3304 ++stratumSizes[proc*next->numStrata+s]; 3305 break; 3306 } 3307 } 3308 } 3309 } 3310 } 3311 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3312 } 3313 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3314 /* Calculate stratumOffsets */ 3315 newLabel->stratumOffsets[0] = 0; 3316 for (s = 0; s < newLabel->numStrata; ++s) { 3317 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3318 } 3319 /* Pack points and Scatter */ 3320 if (!rank) { 3321 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3322 displs[0] = 0; 3323 for (p = 0; p < numProcs; ++p) { 3324 sendcnts[p] = 0; 3325 for (s = 0; s < next->numStrata; ++s) { 3326 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3327 } 3328 offsets[p] = displs[p]; 3329 displs[p+1] = displs[p] + sendcnts[p]; 3330 } 3331 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3332 for (s = 0; s < next->numStrata; ++s) { 3333 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3334 const PetscInt point = next->points[p]; 3335 PetscInt proc; 3336 3337 for (proc = 0; proc < numProcs; ++proc) { 3338 PetscInt dof, off, pPart; 3339 3340 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3341 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3342 for (pPart = off; pPart < off+dof; ++pPart) { 3343 if (partArray[pPart] == point) { 3344 points[offsets[proc]++] = point; 3345 break; 3346 } 3347 } 3348 } 3349 } 3350 } 3351 } 3352 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3353 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3354 ierr = PetscFree(points);CHKERRQ(ierr); 3355 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3356 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3357 /* Renumber points */ 3358 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3359 /* Sort points */ 3360 for (s = 0; s < newLabel->numStrata; ++s) { 3361 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3362 } 3363 /* Insert into list */ 3364 if (newNext) newNext->next = newLabel; 3365 else pmesh->labels = newLabel; 3366 newNext = newLabel; 3367 if (!rank) next = next->next; 3368 } 3369 } 3370 /* Cleanup Partition */ 3371 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3372 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3373 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3374 ierr = ISDestroy(&part);CHKERRQ(ierr); 3375 /* Create point SF for parallel mesh */ 3376 { 3377 const PetscInt *leaves; 3378 PetscSFNode *remotePoints, *rowners, *lowners; 3379 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3380 PetscInt pStart, pEnd; 3381 3382 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3383 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3384 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3385 for (p=0; p<numRoots; p++) { 3386 rowners[p].rank = -1; 3387 rowners[p].index = -1; 3388 } 3389 if (origCellPart) { 3390 /* Make sure cells in the original partition are not assigned to other procs */ 3391 const PetscInt *origCells; 3392 3393 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3394 for (p = 0; p < numProcs; ++p) { 3395 PetscInt dof, off, d; 3396 3397 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3398 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3399 for (d = off; d < off+dof; ++d) { 3400 rowners[origCells[d]].rank = p; 3401 } 3402 } 3403 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3404 } 3405 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3406 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3407 3408 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3409 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3410 for (p = 0; p < numLeaves; ++p) { 3411 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3412 lowners[p].rank = rank; 3413 lowners[p].index = leaves ? leaves[p] : p; 3414 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3415 lowners[p].rank = -2; 3416 lowners[p].index = -2; 3417 } 3418 } 3419 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3420 rowners[p].rank = -3; 3421 rowners[p].index = -3; 3422 } 3423 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3424 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3425 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3426 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3427 for (p = 0; p < numLeaves; ++p) { 3428 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3429 if (lowners[p].rank != rank) ++numGhostPoints; 3430 } 3431 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3432 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3433 for (p = 0, gp = 0; p < numLeaves; ++p) { 3434 if (lowners[p].rank != rank) { 3435 ghostPoints[gp] = leaves ? leaves[p] : p; 3436 remotePoints[gp].rank = lowners[p].rank; 3437 remotePoints[gp].index = lowners[p].index; 3438 ++gp; 3439 } 3440 } 3441 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3442 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3443 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3444 } 3445 /* Cleanup */ 3446 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3447 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3448 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3449 PetscFunctionReturn(0); 3450 } 3451 3452 #undef __FUNCT__ 3453 #define __FUNCT__ "DMPlexRenumber_Private" 3454 /* 3455 Reasons to renumber: 3456 3457 1) Permute points, e.g. bandwidth reduction (Renumber) 3458 3459 a) Must not mix strata 3460 3461 2) Shift numbers for point insertion (Shift) 3462 3463 a) Want operation brken into parts so that insertion can be interleaved 3464 3465 renumbering - An IS which provides the new numbering 3466 */ 3467 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3468 { 3469 PetscFunctionBegin; 3470 PetscFunctionReturn(0); 3471 } 3472 3473 #undef __FUNCT__ 3474 #define __FUNCT__ "DMPlexShiftPoint_Private" 3475 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3476 { 3477 if (depth < 0) return p; 3478 /* Cells */ if (p < depthEnd[depth]) return p; 3479 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3480 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3481 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3482 } 3483 3484 #undef __FUNCT__ 3485 #define __FUNCT__ "DMPlexShiftSizes_Private" 3486 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3487 { 3488 PetscInt *depthEnd; 3489 PetscInt depth = 0, d, pStart, pEnd, p; 3490 PetscErrorCode ierr; 3491 3492 PetscFunctionBegin; 3493 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3494 if (depth < 0) PetscFunctionReturn(0); 3495 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3496 /* Step 1: Expand chart */ 3497 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3498 for (d = 0; d <= depth; ++d) { 3499 pEnd += depthShift[d]; 3500 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3501 } 3502 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3503 /* Step 2: Set cone and support sizes */ 3504 for (d = 0; d <= depth; ++d) { 3505 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3506 for (p = pStart; p < pEnd; ++p) { 3507 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3508 PetscInt size; 3509 3510 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3511 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3512 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3513 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3514 } 3515 } 3516 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3517 PetscFunctionReturn(0); 3518 } 3519 3520 #undef __FUNCT__ 3521 #define __FUNCT__ "DMPlexShiftPoints_Private" 3522 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3523 { 3524 PetscInt *depthEnd, *newpoints; 3525 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3526 PetscErrorCode ierr; 3527 3528 PetscFunctionBegin; 3529 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3530 if (depth < 0) PetscFunctionReturn(0); 3531 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3532 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3533 for (d = 0; d <= depth; ++d) { 3534 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3535 } 3536 /* Step 5: Set cones and supports */ 3537 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3538 for (p = pStart; p < pEnd; ++p) { 3539 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3540 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3541 3542 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3543 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3544 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3545 for (i = 0; i < size; ++i) { 3546 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3547 } 3548 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3549 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3550 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3551 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3552 for (i = 0; i < size; ++i) { 3553 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3554 } 3555 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3556 } 3557 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3558 PetscFunctionReturn(0); 3559 } 3560 3561 #undef __FUNCT__ 3562 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3563 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3564 { 3565 PetscSection coordSection, newCoordSection; 3566 Vec coordinates, newCoordinates; 3567 PetscScalar *coords, *newCoords; 3568 PetscInt *depthEnd, coordSize; 3569 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3570 PetscErrorCode ierr; 3571 3572 PetscFunctionBegin; 3573 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3574 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3575 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3576 for (d = 0; d <= depth; ++d) { 3577 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3578 } 3579 /* Step 8: Convert coordinates */ 3580 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3581 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3582 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3583 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3584 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3585 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3586 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3587 for (v = vStartNew; v < vEndNew; ++v) { 3588 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3589 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3590 } 3591 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3592 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3593 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3594 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3595 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3596 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3597 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3598 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3599 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3600 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3601 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3602 for (v = vStart; v < vEnd; ++v) { 3603 PetscInt dof, off, noff, d; 3604 3605 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3606 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3607 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3608 for (d = 0; d < dof; ++d) { 3609 newCoords[noff+d] = coords[off+d]; 3610 } 3611 } 3612 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3613 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3614 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3615 PetscFunctionReturn(0); 3616 } 3617 3618 #undef __FUNCT__ 3619 #define __FUNCT__ "DMPlexShiftSF_Private" 3620 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3621 { 3622 PetscInt *depthEnd; 3623 PetscInt depth = 0, d; 3624 PetscSF sfPoint, sfPointNew; 3625 const PetscSFNode *remotePoints; 3626 PetscSFNode *gremotePoints; 3627 const PetscInt *localPoints; 3628 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3629 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3630 PetscMPIInt numProcs; 3631 PetscErrorCode ierr; 3632 3633 PetscFunctionBegin; 3634 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3635 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3636 for (d = 0; d <= depth; ++d) { 3637 totShift += depthShift[d]; 3638 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3639 } 3640 /* Step 9: Convert pointSF */ 3641 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3642 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3643 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3644 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3645 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3646 if (numRoots >= 0) { 3647 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3648 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3649 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3650 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3651 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3652 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3653 for (l = 0; l < numLeaves; ++l) { 3654 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3655 gremotePoints[l].rank = remotePoints[l].rank; 3656 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3657 } 3658 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3659 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3660 } 3661 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3662 PetscFunctionReturn(0); 3663 } 3664 3665 #undef __FUNCT__ 3666 #define __FUNCT__ "DMPlexShiftLabels_Private" 3667 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3668 { 3669 PetscSF sfPoint; 3670 DMLabel vtkLabel, ghostLabel; 3671 PetscInt *depthEnd; 3672 const PetscSFNode *leafRemote; 3673 const PetscInt *leafLocal; 3674 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3675 PetscMPIInt rank; 3676 PetscErrorCode ierr; 3677 3678 PetscFunctionBegin; 3679 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3680 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3681 for (d = 0; d <= depth; ++d) { 3682 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3683 } 3684 /* Step 10: Convert labels */ 3685 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3686 for (l = 0; l < numLabels; ++l) { 3687 DMLabel label, newlabel; 3688 const char *lname; 3689 PetscBool isDepth; 3690 IS valueIS; 3691 const PetscInt *values; 3692 PetscInt numValues, val; 3693 3694 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3695 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3696 if (isDepth) continue; 3697 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3698 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3699 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3700 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3701 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3702 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3703 for (val = 0; val < numValues; ++val) { 3704 IS pointIS; 3705 const PetscInt *points; 3706 PetscInt numPoints, p; 3707 3708 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3709 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3710 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3711 for (p = 0; p < numPoints; ++p) { 3712 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3713 3714 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3715 } 3716 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3717 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3718 } 3719 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3720 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3721 } 3722 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3723 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3724 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3725 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3726 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3727 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3728 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3729 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3730 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3731 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3732 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3733 for (; c < leafLocal[l] && c < cEnd; ++c) { 3734 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3735 } 3736 if (leafLocal[l] >= cEnd) break; 3737 if (leafRemote[l].rank == rank) { 3738 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3739 } else { 3740 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3741 } 3742 } 3743 for (; c < cEnd; ++c) { 3744 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3745 } 3746 if (0) { 3747 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3748 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3749 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3750 } 3751 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3752 for (f = fStart; f < fEnd; ++f) { 3753 PetscInt numCells; 3754 3755 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3756 if (numCells < 2) { 3757 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3758 } else { 3759 const PetscInt *cells = PETSC_NULL; 3760 PetscInt vA, vB; 3761 3762 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3763 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3764 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3765 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3766 } 3767 } 3768 if (0) { 3769 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3770 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3771 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3772 } 3773 PetscFunctionReturn(0); 3774 } 3775 3776 #undef __FUNCT__ 3777 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3778 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3779 { 3780 DMLabel label; 3781 IS valueIS; 3782 const PetscInt *values; 3783 PetscInt *depthShift; 3784 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3785 PetscErrorCode ierr; 3786 3787 PetscFunctionBegin; 3788 /* Count ghost cells */ 3789 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3790 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3791 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3792 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3793 3794 *numGhostCells = 0; 3795 for (fs = 0; fs < numFS; ++fs) { 3796 PetscInt numBdFaces; 3797 3798 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3799 3800 *numGhostCells += numBdFaces; 3801 } 3802 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3803 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3804 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3805 if (depth >= 0) depthShift[depth] = *numGhostCells; 3806 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3807 /* Step 3: Set cone/support sizes for new points */ 3808 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3809 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3810 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3811 } 3812 for (fs = 0; fs < numFS; ++fs) { 3813 IS faceIS; 3814 const PetscInt *faces; 3815 PetscInt numFaces, f; 3816 3817 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3818 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3819 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3820 for (f = 0; f < numFaces; ++f) { 3821 PetscInt size; 3822 3823 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3824 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3825 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3826 } 3827 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3828 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3829 } 3830 /* Step 4: Setup ghosted DM */ 3831 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3832 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3833 /* Step 6: Set cones and supports for new points */ 3834 ghostCell = cEnd; 3835 for (fs = 0; fs < numFS; ++fs) { 3836 IS faceIS; 3837 const PetscInt *faces; 3838 PetscInt numFaces, f; 3839 3840 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3841 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3842 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3843 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3844 PetscInt newFace = faces[f] + *numGhostCells; 3845 3846 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3847 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3848 } 3849 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3850 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3851 } 3852 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3853 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3854 /* Step 7: Stratify */ 3855 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3856 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3857 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3858 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3859 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3860 PetscFunctionReturn(0); 3861 } 3862 3863 #undef __FUNCT__ 3864 #define __FUNCT__ "DMPlexConstructGhostCells" 3865 /*@C 3866 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3867 3868 Collective on dm 3869 3870 Input Parameters: 3871 + dm - The original DM 3872 - labelName - The label specifying the boundary faces (this could be auto-generated) 3873 3874 Output Parameters: 3875 + numGhostCells - The number of ghost cells added to the DM 3876 - dmGhosted - The new DM 3877 3878 Level: developer 3879 3880 .seealso: DMCreate() 3881 */ 3882 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3883 { 3884 DM gdm; 3885 PetscInt dim; 3886 PetscErrorCode ierr; 3887 3888 PetscFunctionBegin; 3889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3890 PetscValidPointer(numGhostCells, 3); 3891 PetscValidPointer(dmGhosted, 4); 3892 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3893 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3894 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3895 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3896 switch (dim) { 3897 case 2: 3898 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3899 break; 3900 default: 3901 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3902 } 3903 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3904 *dmGhosted = gdm; 3905 PetscFunctionReturn(0); 3906 } 3907 3908 #undef __FUNCT__ 3909 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3910 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, const char labelName[], DM sdm) 3911 { 3912 MPI_Comm comm = ((PetscObject) dm)->comm; 3913 DMLabel label; 3914 IS valueIS, *pointIS; 3915 const PetscInt *values, **splitPoints; 3916 PetscSection coordSection; 3917 Vec coordinates; 3918 PetscScalar *coords; 3919 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3920 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3921 PetscErrorCode ierr; 3922 3923 PetscFunctionBegin; 3924 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3925 /* Count split points and add cohesive cells */ 3926 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 3927 if (label) { 3928 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3929 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3930 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3931 } 3932 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3933 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3934 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3935 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3936 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3937 for (d = 0; d <= depth; ++d) { 3938 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3939 numSplitPoints[d] = 0; 3940 splitPoints[d] = PETSC_NULL; 3941 pointIS[d] = PETSC_NULL; 3942 } 3943 for (sp = 0; sp < numSP; ++sp) { 3944 const PetscInt dep = values[sp]; 3945 3946 if ((dep < 0) || (dep > depth)) continue; 3947 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3948 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3949 if (pointIS[dep]) { 3950 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3951 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3952 } 3953 } 3954 if (depth >= 0) { 3955 /* Calculate number of additional points */ 3956 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3957 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3958 /* Calculate hybrid bound for each dimension */ 3959 pMaxNew[0] += depthShift[depth]; 3960 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3961 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3962 3963 /* Calculate point offset for each dimension */ 3964 depthOffset[depth] = 0; 3965 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3966 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3967 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3968 } 3969 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3970 /* Step 3: Set cone/support sizes for new points */ 3971 for (dep = 0; dep <= depth; ++dep) { 3972 for (p = 0; p < numSplitPoints[dep]; ++p) { 3973 const PetscInt oldp = splitPoints[dep][p]; 3974 const PetscInt newp = depthOffset[dep] + oldp; 3975 const PetscInt splitp = pMaxNew[dep] + p; 3976 const PetscInt *support; 3977 PetscInt coneSize, supportSize, q, e; 3978 3979 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3980 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3981 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3982 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3983 if (dep == depth-1) { 3984 const PetscInt ccell = pMaxNew[depth] + p; 3985 /* Add cohesive cells, they are prisms */ 3986 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3987 } else if (dep == 0) { 3988 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3989 3990 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3991 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3992 for (e = 0, q = 0; e < supportSize; ++e) { 3993 PetscInt val; 3994 3995 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3996 if ((val == 1) || (val == (shift + 1))) ++q; 3997 } 3998 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3999 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4000 for (e = 0, q = 0; e < supportSize; ++e) { 4001 PetscInt val; 4002 4003 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4004 if ((val == 1) || (val == -(shift + 1))) ++q; 4005 } 4006 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 4007 /* Add cohesive edges */ 4008 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 4009 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 4010 } else if (dep == dim-2) { 4011 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4012 /* Split old edge: Faces in positive side cells and old split faces */ 4013 for (e = 0, q = 0; e < supportSize; ++e) { 4014 PetscInt val; 4015 4016 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4017 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4018 } 4019 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4020 /* Split new edge: Faces in negative side cells and new split faces */ 4021 for (e = 0, q = 0; e < supportSize; ++e) { 4022 PetscInt val; 4023 4024 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4025 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4026 } 4027 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4028 } 4029 } 4030 } 4031 /* Step 4: Setup split DM */ 4032 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4033 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4034 /* Step 6: Set cones and supports for new points */ 4035 for (dep = 0; dep <= depth; ++dep) { 4036 for (p = 0; p < numSplitPoints[dep]; ++p) { 4037 const PetscInt oldp = splitPoints[dep][p]; 4038 const PetscInt newp = depthOffset[dep] + oldp; 4039 const PetscInt splitp = pMaxNew[dep] + p; 4040 const PetscInt *cone, *support, *ornt; 4041 PetscInt coneSize, supportSize, q, v, e, s; 4042 4043 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4044 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4045 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4046 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4047 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4048 if (dep == depth-1) { 4049 const PetscInt ccell = pMaxNew[depth] + p; 4050 const PetscInt *supportF; 4051 4052 /* Split face: copy in old face to new face to start */ 4053 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4054 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4055 /* Split old face: old vertices/edges in cone so no change */ 4056 /* Split new face: new vertices/edges in cone */ 4057 for (q = 0; q < coneSize; ++q) { 4058 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4059 4060 coneNew[2+q] = pMaxNew[dim-2] + v; 4061 } 4062 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4063 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4064 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4065 coneNew[0] = newp; 4066 coneNew[1] = splitp; 4067 for (q = 0; q < coneSize; ++q) { 4068 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4069 } 4070 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4071 4072 4073 for (s = 0; s < supportSize; ++s) { 4074 PetscInt val; 4075 4076 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4077 if (val < 0) { 4078 /* Split old face: Replace negative side cell with cohesive cell */ 4079 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4080 } else { 4081 /* Split new face: Replace positive side cell with cohesive cell */ 4082 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4083 } 4084 } 4085 } else if (dep == 0) { 4086 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4087 4088 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4089 for (e = 0, q = 0; e < supportSize; ++e) { 4090 PetscInt val; 4091 4092 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4093 if ((val == 1) || (val == (shift + 1))) { 4094 supportNew[q++] = depthOffset[1] + support[e]; 4095 } 4096 } 4097 supportNew[q] = cedge; 4098 4099 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4100 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4101 for (e = 0, q = 0; e < supportSize; ++e) { 4102 PetscInt val, edge; 4103 4104 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4105 if (val == 1) { 4106 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4107 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4108 supportNew[q++] = pMaxNew[1] + edge; 4109 } else if (val == -(shift + 1)) { 4110 supportNew[q++] = depthOffset[1] + support[e]; 4111 } 4112 } 4113 supportNew[q] = cedge; 4114 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4115 /* Cohesive edge: Old and new split vertex, punting on support */ 4116 coneNew[0] = newp; 4117 coneNew[1] = splitp; 4118 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4119 } else if (dep == dim-2) { 4120 /* Split old edge: old vertices in cone so no change */ 4121 /* Split new edge: new vertices in cone */ 4122 for (q = 0; q < coneSize; ++q) { 4123 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4124 4125 coneNew[q] = pMaxNew[dim-3] + v; 4126 } 4127 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4128 /* Split old edge: Faces in positive side cells and old split faces */ 4129 for (e = 0, q = 0; e < supportSize; ++e) { 4130 PetscInt val; 4131 4132 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4133 if ((val == dim-1) || (val == (shift + dim-1))) { 4134 supportNew[q++] = depthOffset[dim-1] + support[e]; 4135 } 4136 } 4137 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4138 /* Split new edge: Faces in negative side cells and new split faces */ 4139 for(e = 0, q = 0; e < supportSize; ++e) { 4140 PetscInt val, face; 4141 4142 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4143 if (val == dim-1) { 4144 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4145 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4146 supportNew[q++] = pMaxNew[dim-1] + face; 4147 } else if (val == -(shift + dim-1)) { 4148 supportNew[q++] = depthOffset[dim-1] + support[e]; 4149 } 4150 } 4151 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4152 } 4153 } 4154 } 4155 /* Step 6b: Replace split points in negative side cones */ 4156 for (sp = 0; sp < numSP; ++sp) { 4157 PetscInt dep = values[sp]; 4158 IS pIS; 4159 PetscInt numPoints; 4160 const PetscInt *points; 4161 4162 if (dep >= 0) continue; 4163 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4164 if (!pIS) continue; 4165 dep = -dep - shift; 4166 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4167 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4168 for (p = 0; p < numPoints; ++p) { 4169 const PetscInt oldp = points[p]; 4170 const PetscInt newp = depthOffset[dep] + oldp; 4171 const PetscInt *cone; 4172 PetscInt coneSize, c; 4173 PetscBool replaced = PETSC_FALSE; 4174 4175 /* Negative edge: replace split vertex */ 4176 /* Negative cell: replace split face */ 4177 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4178 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4179 for (c = 0; c < coneSize; ++c) { 4180 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4181 PetscInt csplitp, cp, val; 4182 4183 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4184 if (val == dep-1) { 4185 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4186 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4187 csplitp = pMaxNew[dep-1] + cp; 4188 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4189 replaced = PETSC_TRUE; 4190 } 4191 } 4192 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4193 } 4194 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4195 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4196 } 4197 /* Step 7: Stratify */ 4198 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4199 /* Step 8: Coordinates */ 4200 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4201 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4202 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4203 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4204 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4205 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4206 const PetscInt splitp = pMaxNew[0] + v; 4207 PetscInt dof, off, soff, d; 4208 4209 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4210 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4211 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4212 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4213 } 4214 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4215 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4216 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4217 /* Step 10: Labels */ 4218 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4219 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4220 for (dep = 0; dep <= depth; ++dep) { 4221 for (p = 0; p < numSplitPoints[dep]; ++p) { 4222 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4223 const PetscInt splitp = pMaxNew[dep] + p; 4224 PetscInt l; 4225 4226 for (l = 0; l < numLabels; ++l) { 4227 DMLabel label; 4228 const char *lname; 4229 PetscInt val; 4230 4231 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4232 ierr = DMPlexGetLabel(sdm, lname, &label);CHKERRQ(ierr); 4233 ierr = DMLabelGetValue(label, newp, &val);CHKERRQ(ierr); 4234 if (val >= 0) { 4235 ierr = DMLabelSetValue(label, splitp, val);CHKERRQ(ierr); 4236 if (dep == 0) { 4237 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4238 ierr = DMLabelSetValue(label, cedge, val);CHKERRQ(ierr); 4239 } 4240 } 4241 } 4242 } 4243 } 4244 for (sp = 0; sp < numSP; ++sp) { 4245 const PetscInt dep = values[sp]; 4246 4247 if ((dep < 0) || (dep > depth)) continue; 4248 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4249 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4250 } 4251 if (label) { 4252 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4253 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4254 } 4255 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4256 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4257 PetscFunctionReturn(0); 4258 } 4259 4260 #undef __FUNCT__ 4261 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4262 /*@C 4263 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4264 4265 Collective on dm 4266 4267 Input Parameters: 4268 + dm - The original DM 4269 - labelName - The label specifying the boundary faces (this could be auto-generated) 4270 4271 Output Parameters: 4272 - dmSplit - The new DM 4273 4274 Level: developer 4275 4276 .seealso: DMCreate() 4277 */ 4278 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, const char labelName[], DM *dmSplit) 4279 { 4280 DM sdm; 4281 PetscInt dim; 4282 PetscErrorCode ierr; 4283 4284 PetscFunctionBegin; 4285 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4286 PetscValidPointer(dmSplit, 4); 4287 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4288 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4289 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4290 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4291 switch (dim) { 4292 case 2: 4293 case 3: 4294 ierr = DMPlexConstructCohesiveCells_Private(dm, labelName, sdm);CHKERRQ(ierr); 4295 break; 4296 default: 4297 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4298 } 4299 *dmSplit = sdm; 4300 PetscFunctionReturn(0); 4301 } 4302 4303 #undef __FUNCT__ 4304 #define __FUNCT__ "DMLabelCohesiveComplete" 4305 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4306 { 4307 IS dimIS; 4308 const PetscInt *points; 4309 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4310 PetscErrorCode ierr; 4311 4312 PetscFunctionBegin; 4313 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4314 /* Cell orientation for face gives the side of the fault */ 4315 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4316 if (!dimIS) PetscFunctionReturn(0); 4317 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4318 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4319 for (p = 0; p < numPoints; ++p) { 4320 const PetscInt *support; 4321 PetscInt supportSize, s; 4322 4323 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4324 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4325 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4326 for (s = 0; s < supportSize; ++s) { 4327 const PetscInt *cone, *ornt; 4328 PetscInt coneSize, c; 4329 PetscBool pos = PETSC_TRUE; 4330 4331 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4332 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4333 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4334 for(c = 0; c < coneSize; ++c) { 4335 if (cone[c] == points[p]) { 4336 if (ornt[c] >= 0) { 4337 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4338 } else { 4339 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4340 pos = PETSC_FALSE; 4341 } 4342 break; 4343 } 4344 } 4345 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]); 4346 /* Put faces touching the fault in the label */ 4347 for (c = 0; c < coneSize; ++c) { 4348 const PetscInt point = cone[c]; 4349 4350 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4351 if (val == -1) { 4352 PetscInt *closure = PETSC_NULL; 4353 PetscInt closureSize, cl; 4354 4355 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4356 for (cl = 0; cl < closureSize*2; cl += 2) { 4357 const PetscInt clp = closure[cl]; 4358 4359 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4360 if ((val >= 0) && (val < dim-1)) { 4361 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4362 break; 4363 } 4364 } 4365 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4366 } 4367 } 4368 } 4369 } 4370 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4371 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4372 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4373 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4374 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4375 if (!dimIS) PetscFunctionReturn(0); 4376 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4377 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4378 for (p = 0; p < numPoints; ++p) { 4379 PetscInt *star = PETSC_NULL; 4380 PetscInt starSize, s; 4381 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4382 4383 /* First mark cells connected to the fault */ 4384 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4385 while (again) { 4386 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4387 again = 0; 4388 for (s = 0; s < starSize*2; s += 2) { 4389 const PetscInt point = star[s]; 4390 const PetscInt *cone; 4391 PetscInt coneSize, c; 4392 4393 if ((point < cStart) || (point >= cEnd)) continue; 4394 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4395 if (val != -1) continue; 4396 again = 2; 4397 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4398 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4399 for (c = 0; c < coneSize; ++c) { 4400 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4401 if (val != -1) { 4402 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); 4403 if (val > 0) { 4404 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4405 } else { 4406 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4407 } 4408 again = 1; 4409 break; 4410 } 4411 } 4412 } 4413 } 4414 /* Classify the rest by cell membership */ 4415 for (s = 0; s < starSize*2; s += 2) { 4416 const PetscInt point = star[s]; 4417 4418 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4419 if (val == -1) { 4420 PetscInt *sstar = PETSC_NULL; 4421 PetscInt sstarSize, ss; 4422 PetscBool marked = PETSC_FALSE; 4423 4424 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4425 for (ss = 0; ss < sstarSize*2; ss += 2) { 4426 const PetscInt spoint = sstar[ss]; 4427 4428 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4429 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4430 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4431 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4432 if (val > 0) { 4433 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4434 } else { 4435 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4436 } 4437 marked = PETSC_TRUE; 4438 break; 4439 } 4440 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4441 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4442 } 4443 } 4444 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4445 } 4446 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4447 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4448 PetscFunctionReturn(0); 4449 } 4450 4451 #undef __FUNCT__ 4452 #define __FUNCT__ "DMPlexInterpolate_2D" 4453 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4454 { 4455 DM idm; 4456 DM_Plex *mesh; 4457 PetscHashIJ edgeTable; 4458 PetscInt *off; 4459 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4460 PetscInt numEdges, firstEdge, edge, e; 4461 PetscErrorCode ierr; 4462 4463 PetscFunctionBegin; 4464 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4465 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4466 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4467 numCells = cEnd - cStart; 4468 numVertices = vEnd - vStart; 4469 firstEdge = numCells + numVertices; 4470 numEdges = 0; 4471 /* Count edges using algorithm from CreateNeighborCSR */ 4472 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4473 if (off) { 4474 PetscInt numCorners = 0; 4475 4476 numEdges = off[numCells]/2; 4477 #if 0 4478 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4479 numEdges += 3*numCells - off[numCells]; 4480 #else 4481 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4482 for (c = cStart; c < cEnd; ++c) { 4483 PetscInt coneSize; 4484 4485 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4486 numCorners += coneSize; 4487 } 4488 numEdges += numCorners - off[numCells]; 4489 #endif 4490 } 4491 #if 0 4492 /* Check Euler characteristic V - E + F = 1 */ 4493 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4494 #endif 4495 /* Create interpolated mesh */ 4496 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4497 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4498 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4499 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4500 for (c = 0; c < numCells; ++c) { 4501 PetscInt numCorners; 4502 4503 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4504 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4505 } 4506 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4507 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4508 } 4509 ierr = DMSetUp(idm);CHKERRQ(ierr); 4510 /* Get edge cones from subsets of cell vertices */ 4511 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4512 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4513 4514 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4515 const PetscInt *cellFaces; 4516 PetscInt numCellFaces, faceSize, cf; 4517 4518 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4519 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4520 for (cf = 0; cf < numCellFaces; ++cf) { 4521 #if 1 4522 PetscHashIJKey key; 4523 4524 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4525 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4526 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4527 if (e < 0) { 4528 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4529 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4530 e = edge++; 4531 } 4532 #else 4533 PetscBool found = PETSC_FALSE; 4534 4535 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4536 for (e = firstEdge; e < edge; ++e) { 4537 const PetscInt *cone; 4538 4539 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4540 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4541 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4542 found = PETSC_TRUE; 4543 break; 4544 } 4545 } 4546 if (!found) { 4547 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4548 ++edge; 4549 } 4550 #endif 4551 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4552 } 4553 } 4554 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4555 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4556 ierr = PetscFree(off);CHKERRQ(ierr); 4557 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4558 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4559 mesh = (DM_Plex*) (idm)->data; 4560 /* Orient edges */ 4561 for (c = 0; c < numCells; ++c) { 4562 const PetscInt *cone = PETSC_NULL, *cellFaces; 4563 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4564 4565 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4566 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4567 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4568 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4569 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4570 for (cf = 0; cf < numCellFaces; ++cf) { 4571 const PetscInt *econe = PETSC_NULL; 4572 PetscInt esize; 4573 4574 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4575 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4576 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]); 4577 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4578 /* Correctly oriented */ 4579 mesh->coneOrientations[coff+cf] = 0; 4580 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4581 /* Start at index 1, and reverse orientation */ 4582 mesh->coneOrientations[coff+cf] = -(1+1); 4583 } 4584 } 4585 } 4586 *dmInt = idm; 4587 PetscFunctionReturn(0); 4588 } 4589 4590 #undef __FUNCT__ 4591 #define __FUNCT__ "DMPlexInterpolate_3D" 4592 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4593 { 4594 DM idm, fdm; 4595 DM_Plex *mesh; 4596 PetscInt *off; 4597 const PetscInt numCorners = 4; 4598 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4599 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4600 PetscErrorCode ierr; 4601 4602 PetscFunctionBegin; 4603 { 4604 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4605 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4606 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4607 } 4608 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4609 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4610 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4611 numCells = cEnd - cStart; 4612 numVertices = vEnd - vStart; 4613 firstFace = numCells + numVertices; 4614 numFaces = 0; 4615 /* Count faces using algorithm from CreateNeighborCSR */ 4616 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4617 if (off) { 4618 numFaces = off[numCells]/2; 4619 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4620 numFaces += 4*numCells - off[numCells]; 4621 } 4622 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4623 firstEdge = firstFace + numFaces; 4624 numEdges = numVertices + numFaces - numCells - 1; 4625 /* Create interpolated mesh */ 4626 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4627 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4628 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4629 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4630 for (c = 0; c < numCells; ++c) { 4631 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4632 } 4633 for (f = firstFace; f < firstFace+numFaces; ++f) { 4634 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4635 } 4636 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4637 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4638 } 4639 ierr = DMSetUp(idm);CHKERRQ(ierr); 4640 /* Get face cones from subsets of cell vertices */ 4641 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4642 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4643 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4644 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4645 for (f = firstFace; f < firstFace+numFaces; ++f) { 4646 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4647 } 4648 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4649 for (c = 0, face = firstFace; c < numCells; ++c) { 4650 const PetscInt *cellFaces; 4651 PetscInt numCellFaces, faceSize, cf; 4652 4653 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4654 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4655 for (cf = 0; cf < numCellFaces; ++cf) { 4656 PetscBool found = PETSC_FALSE; 4657 4658 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4659 for (f = firstFace; f < face; ++f) { 4660 const PetscInt *cone = PETSC_NULL; 4661 4662 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4663 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4664 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4665 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4666 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4667 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4668 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4669 found = PETSC_TRUE; 4670 break; 4671 } 4672 } 4673 if (!found) { 4674 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4675 /* Save the vertices for orientation calculation */ 4676 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4677 ++face; 4678 } 4679 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4680 } 4681 } 4682 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4683 /* Get edge cones from subsets of face vertices */ 4684 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4685 const PetscInt *cellFaces; 4686 PetscInt numCellFaces, faceSize, cf; 4687 4688 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4689 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4690 for (cf = 0; cf < numCellFaces; ++cf) { 4691 PetscBool found = PETSC_FALSE; 4692 4693 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4694 for (e = firstEdge; e < edge; ++e) { 4695 const PetscInt *cone = PETSC_NULL; 4696 4697 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4698 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4699 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4700 found = PETSC_TRUE; 4701 break; 4702 } 4703 } 4704 if (!found) { 4705 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4706 ++edge; 4707 } 4708 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4709 } 4710 } 4711 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4712 ierr = PetscFree(off);CHKERRQ(ierr); 4713 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4714 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4715 mesh = (DM_Plex*) (idm)->data; 4716 /* Orient edges */ 4717 for (f = firstFace; f < firstFace+numFaces; ++f) { 4718 const PetscInt *cone, *cellFaces; 4719 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4720 4721 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4722 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4723 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4724 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4725 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4726 for (cf = 0; cf < numCellFaces; ++cf) { 4727 const PetscInt *econe; 4728 PetscInt esize; 4729 4730 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4731 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4732 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]); 4733 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4734 /* Correctly oriented */ 4735 mesh->coneOrientations[coff+cf] = 0; 4736 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4737 /* Start at index 1, and reverse orientation */ 4738 mesh->coneOrientations[coff+cf] = -(1+1); 4739 } 4740 } 4741 } 4742 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4743 /* Orient faces */ 4744 for (c = 0; c < numCells; ++c) { 4745 const PetscInt *cone, *cellFaces; 4746 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4747 4748 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4749 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4750 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4751 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4752 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4753 for (cf = 0; cf < numCellFaces; ++cf) { 4754 PetscInt *origClosure = PETSC_NULL, *closure; 4755 PetscInt closureSize, i; 4756 4757 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4758 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4759 for (i = 4; i < 7; ++i) { 4760 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); 4761 } 4762 closure = &origClosure[4*2]; 4763 /* Remember that this is the orientation for edges, not vertices */ 4764 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4765 /* Correctly oriented */ 4766 mesh->coneOrientations[coff+cf] = 0; 4767 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4768 /* Shifted by 1 */ 4769 mesh->coneOrientations[coff+cf] = 1; 4770 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4771 /* Shifted by 2 */ 4772 mesh->coneOrientations[coff+cf] = 2; 4773 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4774 /* Start at edge 1, and reverse orientation */ 4775 mesh->coneOrientations[coff+cf] = -(1+1); 4776 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4777 /* Start at index 0, and reverse orientation */ 4778 mesh->coneOrientations[coff+cf] = -(0+1); 4779 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4780 /* Start at index 2, and reverse orientation */ 4781 mesh->coneOrientations[coff+cf] = -(2+1); 4782 } 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); 4783 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4784 } 4785 } 4786 { 4787 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4788 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4789 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4790 } 4791 *dmInt = idm; 4792 PetscFunctionReturn(0); 4793 } 4794 4795 #undef __FUNCT__ 4796 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4797 /* 4798 This takes as input the common mesh generator output, a list of the vertices for each cell 4799 */ 4800 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4801 { 4802 PetscInt *cone, c, p; 4803 PetscErrorCode ierr; 4804 4805 PetscFunctionBegin; 4806 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4807 for (c = 0; c < numCells; ++c) { 4808 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4809 } 4810 ierr = DMSetUp(dm);CHKERRQ(ierr); 4811 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4812 for (c = 0; c < numCells; ++c) { 4813 for (p = 0; p < numCorners; ++p) { 4814 cone[p] = cells[c*numCorners+p]+numCells; 4815 } 4816 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4817 } 4818 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4819 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4820 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4821 PetscFunctionReturn(0); 4822 } 4823 4824 #undef __FUNCT__ 4825 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4826 /* 4827 This takes as input the coordinates for each vertex 4828 */ 4829 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4830 { 4831 PetscSection coordSection; 4832 Vec coordinates; 4833 PetscScalar *coords; 4834 PetscInt coordSize, v, d; 4835 PetscErrorCode ierr; 4836 4837 PetscFunctionBegin; 4838 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4839 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4840 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4841 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4842 for (v = numCells; v < numCells+numVertices; ++v) { 4843 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4844 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4845 } 4846 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4847 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4848 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4849 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4850 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4851 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4852 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4853 for (v = 0; v < numVertices; ++v) { 4854 for (d = 0; d < spaceDim; ++d) { 4855 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4856 } 4857 } 4858 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4859 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4860 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4861 PetscFunctionReturn(0); 4862 } 4863 4864 #undef __FUNCT__ 4865 #define __FUNCT__ "DMPlexCreateFromCellList" 4866 /* 4867 This takes as input the common mesh generator output, a list of the vertices for each cell 4868 */ 4869 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4870 { 4871 PetscErrorCode ierr; 4872 4873 PetscFunctionBegin; 4874 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4875 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4876 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4877 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4878 if (interpolate) { 4879 DM idm; 4880 4881 switch (dim) { 4882 case 2: 4883 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4884 case 3: 4885 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4886 default: 4887 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4888 } 4889 ierr = DMDestroy(dm);CHKERRQ(ierr); 4890 *dm = idm; 4891 } 4892 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4893 PetscFunctionReturn(0); 4894 } 4895 4896 #if defined(PETSC_HAVE_TRIANGLE) 4897 #include <triangle.h> 4898 4899 #undef __FUNCT__ 4900 #define __FUNCT__ "InitInput_Triangle" 4901 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4902 { 4903 PetscFunctionBegin; 4904 inputCtx->numberofpoints = 0; 4905 inputCtx->numberofpointattributes = 0; 4906 inputCtx->pointlist = PETSC_NULL; 4907 inputCtx->pointattributelist = PETSC_NULL; 4908 inputCtx->pointmarkerlist = PETSC_NULL; 4909 inputCtx->numberofsegments = 0; 4910 inputCtx->segmentlist = PETSC_NULL; 4911 inputCtx->segmentmarkerlist = PETSC_NULL; 4912 inputCtx->numberoftriangleattributes = 0; 4913 inputCtx->trianglelist = PETSC_NULL; 4914 inputCtx->numberofholes = 0; 4915 inputCtx->holelist = PETSC_NULL; 4916 inputCtx->numberofregions = 0; 4917 inputCtx->regionlist = PETSC_NULL; 4918 PetscFunctionReturn(0); 4919 } 4920 4921 #undef __FUNCT__ 4922 #define __FUNCT__ "InitOutput_Triangle" 4923 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4924 { 4925 PetscFunctionBegin; 4926 outputCtx->numberofpoints = 0; 4927 outputCtx->pointlist = PETSC_NULL; 4928 outputCtx->pointattributelist = PETSC_NULL; 4929 outputCtx->pointmarkerlist = PETSC_NULL; 4930 outputCtx->numberoftriangles = 0; 4931 outputCtx->trianglelist = PETSC_NULL; 4932 outputCtx->triangleattributelist = PETSC_NULL; 4933 outputCtx->neighborlist = PETSC_NULL; 4934 outputCtx->segmentlist = PETSC_NULL; 4935 outputCtx->segmentmarkerlist = PETSC_NULL; 4936 outputCtx->numberofedges = 0; 4937 outputCtx->edgelist = PETSC_NULL; 4938 outputCtx->edgemarkerlist = PETSC_NULL; 4939 PetscFunctionReturn(0); 4940 } 4941 4942 #undef __FUNCT__ 4943 #define __FUNCT__ "FiniOutput_Triangle" 4944 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4945 { 4946 PetscFunctionBegin; 4947 free(outputCtx->pointmarkerlist); 4948 free(outputCtx->edgelist); 4949 free(outputCtx->edgemarkerlist); 4950 free(outputCtx->trianglelist); 4951 free(outputCtx->neighborlist); 4952 PetscFunctionReturn(0); 4953 } 4954 4955 #undef __FUNCT__ 4956 #define __FUNCT__ "DMPlexGenerate_Triangle" 4957 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4958 { 4959 MPI_Comm comm = ((PetscObject) boundary)->comm; 4960 PetscInt dim = 2; 4961 const PetscBool createConvexHull = PETSC_FALSE; 4962 const PetscBool constrained = PETSC_FALSE; 4963 struct triangulateio in; 4964 struct triangulateio out; 4965 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4966 PetscMPIInt rank; 4967 PetscErrorCode ierr; 4968 4969 PetscFunctionBegin; 4970 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4971 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4972 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4973 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4974 4975 in.numberofpoints = vEnd - vStart; 4976 if (in.numberofpoints > 0) { 4977 PetscSection coordSection; 4978 Vec coordinates; 4979 PetscScalar *array; 4980 4981 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4982 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4983 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4984 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4985 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4986 for (v = vStart; v < vEnd; ++v) { 4987 const PetscInt idx = v - vStart; 4988 PetscInt off, d; 4989 4990 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4991 for (d = 0; d < dim; ++d) { 4992 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4993 } 4994 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4995 } 4996 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4997 } 4998 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4999 in.numberofsegments = eEnd - eStart; 5000 if (in.numberofsegments > 0) { 5001 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 5002 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 5003 for (e = eStart; e < eEnd; ++e) { 5004 const PetscInt idx = e - eStart; 5005 const PetscInt *cone; 5006 5007 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 5008 5009 in.segmentlist[idx*2+0] = cone[0] - vStart; 5010 in.segmentlist[idx*2+1] = cone[1] - vStart; 5011 5012 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 5013 } 5014 } 5015 #if 0 /* Do not currently support holes */ 5016 PetscReal *holeCoords; 5017 PetscInt h, d; 5018 5019 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5020 if (in.numberofholes > 0) { 5021 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5022 for (h = 0; h < in.numberofholes; ++h) { 5023 for (d = 0; d < dim; ++d) { 5024 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5025 } 5026 } 5027 } 5028 #endif 5029 if (!rank) { 5030 char args[32]; 5031 5032 /* Take away 'Q' for verbose output */ 5033 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5034 if (createConvexHull) { 5035 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5036 } 5037 if (constrained) { 5038 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5039 } 5040 triangulate(args, &in, &out, PETSC_NULL); 5041 } 5042 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5043 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5044 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5045 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5046 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5047 5048 { 5049 const PetscInt numCorners = 3; 5050 const PetscInt numCells = out.numberoftriangles; 5051 const PetscInt numVertices = out.numberofpoints; 5052 const int *cells = out.trianglelist; 5053 const double *meshCoords = out.pointlist; 5054 5055 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5056 /* Set labels */ 5057 for (v = 0; v < numVertices; ++v) { 5058 if (out.pointmarkerlist[v]) { 5059 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5060 } 5061 } 5062 if (interpolate) { 5063 for (e = 0; e < out.numberofedges; e++) { 5064 if (out.edgemarkerlist[e]) { 5065 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5066 const PetscInt *edges; 5067 PetscInt numEdges; 5068 5069 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5070 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5071 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5072 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5073 } 5074 } 5075 } 5076 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5077 } 5078 #if 0 /* Do not currently support holes */ 5079 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5080 #endif 5081 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5082 PetscFunctionReturn(0); 5083 } 5084 5085 #undef __FUNCT__ 5086 #define __FUNCT__ "DMPlexRefine_Triangle" 5087 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5088 { 5089 MPI_Comm comm = ((PetscObject) dm)->comm; 5090 PetscInt dim = 2; 5091 struct triangulateio in; 5092 struct triangulateio out; 5093 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5094 PetscMPIInt rank; 5095 PetscErrorCode ierr; 5096 5097 PetscFunctionBegin; 5098 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5099 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5100 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5101 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5102 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5103 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5104 5105 in.numberofpoints = vEnd - vStart; 5106 if (in.numberofpoints > 0) { 5107 PetscSection coordSection; 5108 Vec coordinates; 5109 PetscScalar *array; 5110 5111 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5112 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5113 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5114 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5115 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5116 for (v = vStart; v < vEnd; ++v) { 5117 const PetscInt idx = v - vStart; 5118 PetscInt off, d; 5119 5120 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5121 for (d = 0; d < dim; ++d) { 5122 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5123 } 5124 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5125 } 5126 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5127 } 5128 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5129 5130 in.numberofcorners = 3; 5131 in.numberoftriangles = cEnd - cStart; 5132 5133 in.trianglearealist = (double*) maxVolumes; 5134 if (in.numberoftriangles > 0) { 5135 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5136 for (c = cStart; c < cEnd; ++c) { 5137 const PetscInt idx = c - cStart; 5138 PetscInt *closure = PETSC_NULL; 5139 PetscInt closureSize; 5140 5141 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5142 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5143 for (v = 0; v < 3; ++v) { 5144 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5145 } 5146 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5147 } 5148 } 5149 /* TODO: Segment markers are missing on input */ 5150 #if 0 /* Do not currently support holes */ 5151 PetscReal *holeCoords; 5152 PetscInt h, d; 5153 5154 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5155 if (in.numberofholes > 0) { 5156 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5157 for (h = 0; h < in.numberofholes; ++h) { 5158 for (d = 0; d < dim; ++d) { 5159 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5160 } 5161 } 5162 } 5163 #endif 5164 if (!rank) { 5165 char args[32]; 5166 5167 /* Take away 'Q' for verbose output */ 5168 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5169 triangulate(args, &in, &out, PETSC_NULL); 5170 } 5171 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5172 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5173 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5174 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5175 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5176 5177 { 5178 const PetscInt numCorners = 3; 5179 const PetscInt numCells = out.numberoftriangles; 5180 const PetscInt numVertices = out.numberofpoints; 5181 const int *cells = out.trianglelist; 5182 const double *meshCoords = out.pointlist; 5183 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5184 5185 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5186 /* Set labels */ 5187 for (v = 0; v < numVertices; ++v) { 5188 if (out.pointmarkerlist[v]) { 5189 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5190 } 5191 } 5192 if (interpolate) { 5193 PetscInt e; 5194 5195 for (e = 0; e < out.numberofedges; e++) { 5196 if (out.edgemarkerlist[e]) { 5197 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5198 const PetscInt *edges; 5199 PetscInt numEdges; 5200 5201 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5202 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5203 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5204 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5205 } 5206 } 5207 } 5208 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5209 } 5210 #if 0 /* Do not currently support holes */ 5211 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5212 #endif 5213 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5214 PetscFunctionReturn(0); 5215 } 5216 #endif 5217 5218 #if defined(PETSC_HAVE_TETGEN) 5219 #include <tetgen.h> 5220 #undef __FUNCT__ 5221 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5222 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5223 { 5224 MPI_Comm comm = ((PetscObject) boundary)->comm; 5225 const PetscInt dim = 3; 5226 ::tetgenio in; 5227 ::tetgenio out; 5228 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5229 PetscMPIInt rank; 5230 PetscErrorCode ierr; 5231 5232 PetscFunctionBegin; 5233 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5234 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5235 in.numberofpoints = vEnd - vStart; 5236 if (in.numberofpoints > 0) { 5237 PetscSection coordSection; 5238 Vec coordinates; 5239 PetscScalar *array; 5240 5241 in.pointlist = new double[in.numberofpoints*dim]; 5242 in.pointmarkerlist = new int[in.numberofpoints]; 5243 5244 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5245 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5246 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5247 for (v = vStart; v < vEnd; ++v) { 5248 const PetscInt idx = v - vStart; 5249 PetscInt off, d; 5250 5251 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5252 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5253 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5254 } 5255 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5256 } 5257 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5258 5259 in.numberoffacets = fEnd - fStart; 5260 if (in.numberoffacets > 0) { 5261 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5262 in.facetmarkerlist = new int[in.numberoffacets]; 5263 for (f = fStart; f < fEnd; ++f) { 5264 const PetscInt idx = f - fStart; 5265 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5266 5267 in.facetlist[idx].numberofpolygons = 1; 5268 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5269 in.facetlist[idx].numberofholes = 0; 5270 in.facetlist[idx].holelist = NULL; 5271 5272 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5273 for (p = 0; p < numPoints*2; p += 2) { 5274 const PetscInt point = points[p]; 5275 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5276 } 5277 5278 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5279 poly->numberofvertices = numVertices; 5280 poly->vertexlist = new int[poly->numberofvertices]; 5281 for (v = 0; v < numVertices; ++v) { 5282 const PetscInt vIdx = points[v] - vStart; 5283 poly->vertexlist[v] = vIdx; 5284 } 5285 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5286 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5287 } 5288 } 5289 if (!rank) { 5290 char args[32]; 5291 5292 /* Take away 'Q' for verbose output */ 5293 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5294 ::tetrahedralize(args, &in, &out); 5295 } 5296 { 5297 const PetscInt numCorners = 4; 5298 const PetscInt numCells = out.numberoftetrahedra; 5299 const PetscInt numVertices = out.numberofpoints; 5300 const int *cells = out.tetrahedronlist; 5301 const double *meshCoords = out.pointlist; 5302 5303 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5304 /* Set labels */ 5305 for (v = 0; v < numVertices; ++v) { 5306 if (out.pointmarkerlist[v]) { 5307 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5308 } 5309 } 5310 if (interpolate) { 5311 PetscInt e; 5312 5313 for (e = 0; e < out.numberofedges; e++) { 5314 if (out.edgemarkerlist[e]) { 5315 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5316 const PetscInt *edges; 5317 PetscInt numEdges; 5318 5319 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5320 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5321 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5322 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5323 } 5324 } 5325 for (f = 0; f < out.numberoftrifaces; f++) { 5326 if (out.trifacemarkerlist[f]) { 5327 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5328 const PetscInt *faces; 5329 PetscInt numFaces; 5330 5331 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5332 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5333 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5334 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5335 } 5336 } 5337 } 5338 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5339 } 5340 PetscFunctionReturn(0); 5341 } 5342 5343 #undef __FUNCT__ 5344 #define __FUNCT__ "DMPlexRefine_Tetgen" 5345 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5346 { 5347 MPI_Comm comm = ((PetscObject) dm)->comm; 5348 const PetscInt dim = 3; 5349 ::tetgenio in; 5350 ::tetgenio out; 5351 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5352 PetscMPIInt rank; 5353 PetscErrorCode ierr; 5354 5355 PetscFunctionBegin; 5356 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5357 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5358 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5359 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5360 5361 in.numberofpoints = vEnd - vStart; 5362 if (in.numberofpoints > 0) { 5363 PetscSection coordSection; 5364 Vec coordinates; 5365 PetscScalar *array; 5366 5367 in.pointlist = new double[in.numberofpoints*dim]; 5368 in.pointmarkerlist = new int[in.numberofpoints]; 5369 5370 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5371 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5372 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5373 for (v = vStart; v < vEnd; ++v) { 5374 const PetscInt idx = v - vStart; 5375 PetscInt off, d; 5376 5377 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5378 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 5379 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5380 } 5381 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5382 } 5383 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5384 5385 in.numberofcorners = 4; 5386 in.numberoftetrahedra = cEnd - cStart; 5387 in.tetrahedronvolumelist = (double*) maxVolumes; 5388 if (in.numberoftetrahedra > 0) { 5389 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5390 for (c = cStart; c < cEnd; ++c) { 5391 const PetscInt idx = c - cStart; 5392 PetscInt *closure = PETSC_NULL; 5393 PetscInt closureSize; 5394 5395 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5396 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5397 for (v = 0; v < 4; ++v) { 5398 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5399 } 5400 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5401 } 5402 } 5403 /* TODO: Put in boundary faces with markers */ 5404 if (!rank) { 5405 char args[32]; 5406 5407 /* Take away 'Q' for verbose output */ 5408 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5409 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5410 ::tetrahedralize(args, &in, &out); 5411 } 5412 in.tetrahedronvolumelist = NULL; 5413 5414 { 5415 const PetscInt numCorners = 4; 5416 const PetscInt numCells = out.numberoftetrahedra; 5417 const PetscInt numVertices = out.numberofpoints; 5418 const int *cells = out.tetrahedronlist; 5419 const double *meshCoords = out.pointlist; 5420 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5421 5422 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5423 /* Set labels */ 5424 for (v = 0; v < numVertices; ++v) { 5425 if (out.pointmarkerlist[v]) { 5426 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5427 } 5428 } 5429 if (interpolate) { 5430 PetscInt e, f; 5431 5432 for (e = 0; e < out.numberofedges; e++) { 5433 if (out.edgemarkerlist[e]) { 5434 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5435 const PetscInt *edges; 5436 PetscInt numEdges; 5437 5438 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5439 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5440 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5441 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5442 } 5443 } 5444 for (f = 0; f < out.numberoftrifaces; f++) { 5445 if (out.trifacemarkerlist[f]) { 5446 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5447 const PetscInt *faces; 5448 PetscInt numFaces; 5449 5450 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5451 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5452 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5453 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5454 } 5455 } 5456 } 5457 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5458 } 5459 PetscFunctionReturn(0); 5460 } 5461 #endif 5462 5463 #if defined(PETSC_HAVE_CTETGEN) 5464 #include "ctetgen.h" 5465 5466 #undef __FUNCT__ 5467 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5468 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5469 { 5470 MPI_Comm comm = ((PetscObject) boundary)->comm; 5471 const PetscInt dim = 3; 5472 PLC *in, *out; 5473 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5474 PetscMPIInt rank; 5475 PetscErrorCode ierr; 5476 5477 PetscFunctionBegin; 5478 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5479 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5480 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5481 ierr = PLCCreate(&in);CHKERRQ(ierr); 5482 ierr = PLCCreate(&out);CHKERRQ(ierr); 5483 5484 in->numberofpoints = vEnd - vStart; 5485 if (in->numberofpoints > 0) { 5486 PetscSection coordSection; 5487 Vec coordinates; 5488 PetscScalar *array; 5489 5490 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5491 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5492 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5493 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5494 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5495 for (v = vStart; v < vEnd; ++v) { 5496 const PetscInt idx = v - vStart; 5497 PetscInt off, d, m; 5498 5499 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5500 for (d = 0; d < dim; ++d) { 5501 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5502 } 5503 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5504 5505 in->pointmarkerlist[idx] = (int) m; 5506 } 5507 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5508 } 5509 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5510 5511 in->numberoffacets = fEnd - fStart; 5512 if (in->numberoffacets > 0) { 5513 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5514 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5515 for (f = fStart; f < fEnd; ++f) { 5516 const PetscInt idx = f - fStart; 5517 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5518 polygon *poly; 5519 5520 in->facetlist[idx].numberofpolygons = 1; 5521 5522 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5523 5524 in->facetlist[idx].numberofholes = 0; 5525 in->facetlist[idx].holelist = PETSC_NULL; 5526 5527 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5528 for (p = 0; p < numPoints*2; p += 2) { 5529 const PetscInt point = points[p]; 5530 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5531 } 5532 5533 poly = in->facetlist[idx].polygonlist; 5534 poly->numberofvertices = numVertices; 5535 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5536 for (v = 0; v < numVertices; ++v) { 5537 const PetscInt vIdx = points[v] - vStart; 5538 poly->vertexlist[v] = vIdx; 5539 } 5540 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5541 in->facetmarkerlist[idx] = (int) m; 5542 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5543 } 5544 } 5545 if (!rank) { 5546 TetGenOpts t; 5547 5548 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5549 t.in = boundary; /* Should go away */ 5550 t.plc = 1; 5551 t.quality = 1; 5552 t.edgesout = 1; 5553 t.zeroindex = 1; 5554 t.quiet = 1; 5555 t.verbose = verbose; 5556 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5557 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5558 } 5559 { 5560 const PetscInt numCorners = 4; 5561 const PetscInt numCells = out->numberoftetrahedra; 5562 const PetscInt numVertices = out->numberofpoints; 5563 const int *cells = out->tetrahedronlist; 5564 const double *meshCoords = out->pointlist; 5565 5566 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5567 /* Set labels */ 5568 for (v = 0; v < numVertices; ++v) { 5569 if (out->pointmarkerlist[v]) { 5570 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5571 } 5572 } 5573 if (interpolate) { 5574 PetscInt e; 5575 5576 for (e = 0; e < out->numberofedges; e++) { 5577 if (out->edgemarkerlist[e]) { 5578 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5579 const PetscInt *edges; 5580 PetscInt numEdges; 5581 5582 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5583 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5584 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5585 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5586 } 5587 } 5588 for (f = 0; f < out->numberoftrifaces; f++) { 5589 if (out->trifacemarkerlist[f]) { 5590 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5591 const PetscInt *faces; 5592 PetscInt numFaces; 5593 5594 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5595 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5596 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5597 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5598 } 5599 } 5600 } 5601 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5602 } 5603 5604 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5605 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5606 PetscFunctionReturn(0); 5607 } 5608 5609 #undef __FUNCT__ 5610 #define __FUNCT__ "DMPlexRefine_CTetgen" 5611 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5612 { 5613 MPI_Comm comm = ((PetscObject) dm)->comm; 5614 const PetscInt dim = 3; 5615 PLC *in, *out; 5616 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5617 PetscMPIInt rank; 5618 PetscErrorCode ierr; 5619 5620 PetscFunctionBegin; 5621 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5622 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5623 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5624 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5625 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5626 ierr = PLCCreate(&in);CHKERRQ(ierr); 5627 ierr = PLCCreate(&out);CHKERRQ(ierr); 5628 5629 in->numberofpoints = vEnd - vStart; 5630 if (in->numberofpoints > 0) { 5631 PetscSection coordSection; 5632 Vec coordinates; 5633 PetscScalar *array; 5634 5635 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5636 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5637 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5638 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5639 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5640 for (v = vStart; v < vEnd; ++v) { 5641 const PetscInt idx = v - vStart; 5642 PetscInt off, d, m; 5643 5644 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5645 for (d = 0; d < dim; ++d) { 5646 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5647 } 5648 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5649 5650 in->pointmarkerlist[idx] = (int) m; 5651 } 5652 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5653 } 5654 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5655 5656 in->numberofcorners = 4; 5657 in->numberoftetrahedra = cEnd - cStart; 5658 in->tetrahedronvolumelist = maxVolumes; 5659 if (in->numberoftetrahedra > 0) { 5660 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5661 for (c = cStart; c < cEnd; ++c) { 5662 const PetscInt idx = c - cStart; 5663 PetscInt *closure = PETSC_NULL; 5664 PetscInt closureSize; 5665 5666 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5667 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5668 for (v = 0; v < 4; ++v) { 5669 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5670 } 5671 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5672 } 5673 } 5674 if (!rank) { 5675 TetGenOpts t; 5676 5677 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5678 5679 t.in = dm; /* Should go away */ 5680 t.refine = 1; 5681 t.varvolume = 1; 5682 t.quality = 1; 5683 t.edgesout = 1; 5684 t.zeroindex = 1; 5685 t.quiet = 1; 5686 t.verbose = verbose; /* Change this */ 5687 5688 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5689 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5690 } 5691 { 5692 const PetscInt numCorners = 4; 5693 const PetscInt numCells = out->numberoftetrahedra; 5694 const PetscInt numVertices = out->numberofpoints; 5695 const int *cells = out->tetrahedronlist; 5696 const double *meshCoords = out->pointlist; 5697 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5698 5699 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5700 /* Set labels */ 5701 for (v = 0; v < numVertices; ++v) { 5702 if (out->pointmarkerlist[v]) { 5703 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5704 } 5705 } 5706 if (interpolate) { 5707 PetscInt e, f; 5708 5709 for (e = 0; e < out->numberofedges; e++) { 5710 if (out->edgemarkerlist[e]) { 5711 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5712 const PetscInt *edges; 5713 PetscInt numEdges; 5714 5715 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5716 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5717 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5718 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5719 } 5720 } 5721 for (f = 0; f < out->numberoftrifaces; f++) { 5722 if (out->trifacemarkerlist[f]) { 5723 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5724 const PetscInt *faces; 5725 PetscInt numFaces; 5726 5727 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5728 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5729 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5730 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5731 } 5732 } 5733 } 5734 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5735 } 5736 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5737 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5738 PetscFunctionReturn(0); 5739 } 5740 #endif 5741 5742 #undef __FUNCT__ 5743 #define __FUNCT__ "DMPlexGenerate" 5744 /*@C 5745 DMPlexGenerate - Generates a mesh. 5746 5747 Not Collective 5748 5749 Input Parameters: 5750 + boundary - The DMPlex boundary object 5751 . name - The mesh generation package name 5752 - interpolate - Flag to create intermediate mesh elements 5753 5754 Output Parameter: 5755 . mesh - The DMPlex object 5756 5757 Level: intermediate 5758 5759 .keywords: mesh, elements 5760 .seealso: DMPlexCreate(), DMRefine() 5761 @*/ 5762 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5763 { 5764 PetscInt dim; 5765 char genname[1024]; 5766 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5767 PetscErrorCode ierr; 5768 5769 PetscFunctionBegin; 5770 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5771 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5772 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5773 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5774 if (flg) name = genname; 5775 if (name) { 5776 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5777 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5778 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5779 } 5780 switch (dim) { 5781 case 1: 5782 if (!name || isTriangle) { 5783 #if defined(PETSC_HAVE_TRIANGLE) 5784 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5785 #else 5786 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5787 #endif 5788 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5789 break; 5790 case 2: 5791 if (!name || isCTetgen) { 5792 #if defined(PETSC_HAVE_CTETGEN) 5793 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5794 #else 5795 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5796 #endif 5797 } else if (isTetgen) { 5798 #if defined(PETSC_HAVE_TETGEN) 5799 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5800 #else 5801 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5802 #endif 5803 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5804 break; 5805 default: 5806 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5807 } 5808 PetscFunctionReturn(0); 5809 } 5810 5811 typedef PetscInt CellRefiner; 5812 5813 #undef __FUNCT__ 5814 #define __FUNCT__ "GetDepthStart_Private" 5815 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5816 { 5817 PetscFunctionBegin; 5818 if (cStart) *cStart = 0; 5819 if (vStart) *vStart = depthSize[depth]; 5820 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5821 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5822 PetscFunctionReturn(0); 5823 } 5824 5825 #undef __FUNCT__ 5826 #define __FUNCT__ "GetDepthEnd_Private" 5827 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5828 { 5829 PetscFunctionBegin; 5830 if (cEnd) *cEnd = depthSize[depth]; 5831 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5832 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5833 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5834 PetscFunctionReturn(0); 5835 } 5836 5837 #undef __FUNCT__ 5838 #define __FUNCT__ "CellRefinerGetSizes" 5839 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5840 { 5841 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5842 PetscErrorCode ierr; 5843 5844 PetscFunctionBegin; 5845 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5846 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5847 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5848 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5849 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5850 switch (refiner) { 5851 case 1: 5852 /* Simplicial 2D */ 5853 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5854 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5855 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5856 break; 5857 case 3: 5858 /* Hybrid 2D */ 5859 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5860 cMax = PetscMin(cEnd, cMax); 5861 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5862 fMax = PetscMin(fEnd, fMax); 5863 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5864 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 */ 5865 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5866 break; 5867 case 2: 5868 /* Hex 2D */ 5869 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5870 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5871 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5872 break; 5873 default: 5874 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5875 } 5876 PetscFunctionReturn(0); 5877 } 5878 5879 #undef __FUNCT__ 5880 #define __FUNCT__ "CellRefinerSetConeSizes" 5881 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5882 { 5883 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5884 PetscErrorCode ierr; 5885 5886 PetscFunctionBegin; 5887 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5888 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5889 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5890 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5891 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5892 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5893 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5894 switch (refiner) { 5895 case 1: 5896 /* Simplicial 2D */ 5897 /* All cells have 3 faces */ 5898 for (c = cStart; c < cEnd; ++c) { 5899 for (r = 0; r < 4; ++r) { 5900 const PetscInt newp = (c - cStart)*4 + r; 5901 5902 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5903 } 5904 } 5905 /* Split faces have 2 vertices and the same cells as the parent */ 5906 for (f = fStart; f < fEnd; ++f) { 5907 for (r = 0; r < 2; ++r) { 5908 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5909 PetscInt size; 5910 5911 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5912 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5913 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5914 } 5915 } 5916 /* Interior faces have 2 vertices and 2 cells */ 5917 for (c = cStart; c < cEnd; ++c) { 5918 for (r = 0; r < 3; ++r) { 5919 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5920 5921 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5922 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5923 } 5924 } 5925 /* Old vertices have identical supports */ 5926 for (v = vStart; v < vEnd; ++v) { 5927 const PetscInt newp = vStartNew + (v - vStart); 5928 PetscInt size; 5929 5930 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5931 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5932 } 5933 /* Face vertices have 2 + cells*2 supports */ 5934 for (f = fStart; f < fEnd; ++f) { 5935 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5936 PetscInt size; 5937 5938 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5939 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5940 } 5941 break; 5942 case 2: 5943 /* Hex 2D */ 5944 /* All cells have 4 faces */ 5945 for (c = cStart; c < cEnd; ++c) { 5946 for (r = 0; r < 4; ++r) { 5947 const PetscInt newp = (c - cStart)*4 + r; 5948 5949 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5950 } 5951 } 5952 /* Split faces have 2 vertices and the same cells as the parent */ 5953 for (f = fStart; f < fEnd; ++f) { 5954 for (r = 0; r < 2; ++r) { 5955 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5956 PetscInt size; 5957 5958 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5959 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5960 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5961 } 5962 } 5963 /* Interior faces have 2 vertices and 2 cells */ 5964 for (c = cStart; c < cEnd; ++c) { 5965 for (r = 0; r < 4; ++r) { 5966 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5967 5968 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5969 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5970 } 5971 } 5972 /* Old vertices have identical supports */ 5973 for (v = vStart; v < vEnd; ++v) { 5974 const PetscInt newp = vStartNew + (v - vStart); 5975 PetscInt size; 5976 5977 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5978 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5979 } 5980 /* Face vertices have 2 + cells supports */ 5981 for (f = fStart; f < fEnd; ++f) { 5982 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5983 PetscInt size; 5984 5985 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5986 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5987 } 5988 /* Cell vertices have 4 supports */ 5989 for (c = cStart; c < cEnd; ++c) { 5990 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5991 5992 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5993 } 5994 break; 5995 case 3: 5996 /* Hybrid 2D */ 5997 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5998 cMax = PetscMin(cEnd, cMax); 5999 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6000 fMax = PetscMin(fEnd, fMax); 6001 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6002 /* Interior cells have 3 faces */ 6003 for (c = cStart; c < cMax; ++c) { 6004 for (r = 0; r < 4; ++r) { 6005 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 6006 6007 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 6008 } 6009 } 6010 /* Hybrid cells have 4 faces */ 6011 for (c = cMax; c < cEnd; ++c) { 6012 for (r = 0; r < 2; ++r) { 6013 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 6014 6015 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 6016 } 6017 } 6018 /* Interior split faces have 2 vertices and the same cells as the parent */ 6019 for (f = fStart; f < fMax; ++f) { 6020 for (r = 0; r < 2; ++r) { 6021 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6022 PetscInt size; 6023 6024 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6025 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6026 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6027 } 6028 } 6029 /* Interior cell faces have 2 vertices and 2 cells */ 6030 for (c = cStart; c < cMax; ++c) { 6031 for (r = 0; r < 3; ++r) { 6032 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6033 6034 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6035 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6036 } 6037 } 6038 /* Hybrid faces have 2 vertices and the same cells */ 6039 for (f = fMax; f < fEnd; ++f) { 6040 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6041 PetscInt size; 6042 6043 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6044 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6045 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6046 } 6047 /* Hybrid cell faces have 2 vertices and 2 cells */ 6048 for (c = cMax; c < cEnd; ++c) { 6049 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6050 6051 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6052 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6053 } 6054 /* Old vertices have identical supports */ 6055 for (v = vStart; v < vEnd; ++v) { 6056 const PetscInt newp = vStartNew + (v - vStart); 6057 PetscInt size; 6058 6059 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6060 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6061 } 6062 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6063 for (f = fStart; f < fMax; ++f) { 6064 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6065 const PetscInt *support; 6066 PetscInt size, newSize = 2, s; 6067 6068 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6069 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6070 for (s = 0; s < size; ++s) { 6071 if (support[s] >= cMax) newSize += 1; 6072 else newSize += 2; 6073 } 6074 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6075 } 6076 break; 6077 default: 6078 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6079 } 6080 PetscFunctionReturn(0); 6081 } 6082 6083 #undef __FUNCT__ 6084 #define __FUNCT__ "CellRefinerSetCones" 6085 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6086 { 6087 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; 6088 PetscInt maxSupportSize, *supportRef; 6089 PetscErrorCode ierr; 6090 6091 PetscFunctionBegin; 6092 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6093 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6094 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6095 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6096 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6097 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6098 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6099 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6100 switch (refiner) { 6101 case 1: 6102 /* Simplicial 2D */ 6103 /* 6104 2 6105 |\ 6106 | \ 6107 | \ 6108 | \ 6109 | C \ 6110 | \ 6111 | \ 6112 2---1---1 6113 |\ D / \ 6114 | 2 0 \ 6115 |A \ / B \ 6116 0---0-------1 6117 */ 6118 /* All cells have 3 faces */ 6119 for (c = cStart; c < cEnd; ++c) { 6120 const PetscInt newp = cStartNew + (c - cStart)*4; 6121 const PetscInt *cone, *ornt; 6122 PetscInt coneNew[3], orntNew[3]; 6123 6124 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6125 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6126 /* A triangle */ 6127 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6128 orntNew[0] = ornt[0]; 6129 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6130 orntNew[1] = -2; 6131 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6132 orntNew[2] = ornt[2]; 6133 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6134 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6135 #if 1 6136 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); 6137 for (p = 0; p < 3; ++p) { 6138 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); 6139 } 6140 #endif 6141 /* B triangle */ 6142 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6143 orntNew[0] = ornt[0]; 6144 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6145 orntNew[1] = ornt[1]; 6146 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6147 orntNew[2] = -2; 6148 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6149 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6150 #if 1 6151 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); 6152 for (p = 0; p < 3; ++p) { 6153 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); 6154 } 6155 #endif 6156 /* C triangle */ 6157 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6158 orntNew[0] = -2; 6159 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6160 orntNew[1] = ornt[1]; 6161 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6162 orntNew[2] = ornt[2]; 6163 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6164 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6165 #if 1 6166 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); 6167 for (p = 0; p < 3; ++p) { 6168 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); 6169 } 6170 #endif 6171 /* D triangle */ 6172 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6173 orntNew[0] = 0; 6174 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6175 orntNew[1] = 0; 6176 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6177 orntNew[2] = 0; 6178 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6179 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6180 #if 1 6181 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); 6182 for (p = 0; p < 3; ++p) { 6183 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6184 } 6185 #endif 6186 } 6187 /* Split faces have 2 vertices and the same cells as the parent */ 6188 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6189 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6190 for (f = fStart; f < fEnd; ++f) { 6191 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6192 6193 for (r = 0; r < 2; ++r) { 6194 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6195 const PetscInt *cone, *support; 6196 PetscInt coneNew[2], coneSize, c, supportSize, s; 6197 6198 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6199 coneNew[0] = vStartNew + (cone[0] - vStart); 6200 coneNew[1] = vStartNew + (cone[1] - vStart); 6201 coneNew[(r+1)%2] = newv; 6202 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6203 #if 1 6204 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6205 for (p = 0; p < 2; ++p) { 6206 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); 6207 } 6208 #endif 6209 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6210 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6211 for (s = 0; s < supportSize; ++s) { 6212 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6213 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6214 for (c = 0; c < coneSize; ++c) { 6215 if (cone[c] == f) break; 6216 } 6217 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6218 } 6219 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6220 #if 1 6221 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6222 for (p = 0; p < supportSize; ++p) { 6223 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); 6224 } 6225 #endif 6226 } 6227 } 6228 /* Interior faces have 2 vertices and 2 cells */ 6229 for (c = cStart; c < cEnd; ++c) { 6230 const PetscInt *cone; 6231 6232 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6233 for (r = 0; r < 3; ++r) { 6234 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6235 PetscInt coneNew[2]; 6236 PetscInt supportNew[2]; 6237 6238 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6239 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6240 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6241 #if 1 6242 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6243 for (p = 0; p < 2; ++p) { 6244 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); 6245 } 6246 #endif 6247 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6248 supportNew[1] = (c - cStart)*4 + 3; 6249 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6250 #if 1 6251 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6252 for (p = 0; p < 2; ++p) { 6253 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); 6254 } 6255 #endif 6256 } 6257 } 6258 /* Old vertices have identical supports */ 6259 for (v = vStart; v < vEnd; ++v) { 6260 const PetscInt newp = vStartNew + (v - vStart); 6261 const PetscInt *support, *cone; 6262 PetscInt size, s; 6263 6264 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6265 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6266 for (s = 0; s < size; ++s) { 6267 PetscInt r = 0; 6268 6269 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6270 if (cone[1] == v) r = 1; 6271 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6272 } 6273 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6274 #if 1 6275 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6276 for (p = 0; p < size; ++p) { 6277 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); 6278 } 6279 #endif 6280 } 6281 /* Face vertices have 2 + cells*2 supports */ 6282 for (f = fStart; f < fEnd; ++f) { 6283 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6284 const PetscInt *cone, *support; 6285 PetscInt size, s; 6286 6287 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6288 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6289 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6290 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6291 for (s = 0; s < size; ++s) { 6292 PetscInt r = 0; 6293 6294 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6295 if (cone[1] == f) r = 1; 6296 else if (cone[2] == f) r = 2; 6297 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6298 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6299 } 6300 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6301 #if 1 6302 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6303 for (p = 0; p < 2+size*2; ++p) { 6304 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); 6305 } 6306 #endif 6307 } 6308 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6309 break; 6310 case 2: 6311 /* Hex 2D */ 6312 /* 6313 3---------2---------2 6314 | | | 6315 | D 2 C | 6316 | | | 6317 3----3----0----1----1 6318 | | | 6319 | A 0 B | 6320 | | | 6321 0---------0---------1 6322 */ 6323 /* All cells have 4 faces */ 6324 for (c = cStart; c < cEnd; ++c) { 6325 const PetscInt newp = (c - cStart)*4; 6326 const PetscInt *cone, *ornt; 6327 PetscInt coneNew[4], orntNew[4]; 6328 6329 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6330 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6331 /* A quad */ 6332 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6333 orntNew[0] = ornt[0]; 6334 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6335 orntNew[1] = 0; 6336 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6337 orntNew[2] = -2; 6338 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6339 orntNew[3] = ornt[3]; 6340 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6341 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6342 #if 1 6343 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); 6344 for (p = 0; p < 4; ++p) { 6345 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); 6346 } 6347 #endif 6348 /* B quad */ 6349 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6350 orntNew[0] = ornt[0]; 6351 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6352 orntNew[1] = ornt[1]; 6353 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6354 orntNew[2] = 0; 6355 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6356 orntNew[3] = -2; 6357 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6358 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6359 #if 1 6360 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); 6361 for (p = 0; p < 4; ++p) { 6362 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); 6363 } 6364 #endif 6365 /* C quad */ 6366 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6367 orntNew[0] = -2; 6368 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6369 orntNew[1] = ornt[1]; 6370 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6371 orntNew[2] = ornt[2]; 6372 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6373 orntNew[3] = 0; 6374 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6375 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6376 #if 1 6377 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); 6378 for (p = 0; p < 4; ++p) { 6379 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); 6380 } 6381 #endif 6382 /* D quad */ 6383 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6384 orntNew[0] = 0; 6385 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6386 orntNew[1] = -2; 6387 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6388 orntNew[2] = ornt[2]; 6389 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6390 orntNew[3] = ornt[3]; 6391 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6392 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6393 #if 1 6394 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); 6395 for (p = 0; p < 4; ++p) { 6396 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6397 } 6398 #endif 6399 } 6400 /* Split faces have 2 vertices and the same cells as the parent */ 6401 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6402 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6403 for (f = fStart; f < fEnd; ++f) { 6404 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6405 6406 for (r = 0; r < 2; ++r) { 6407 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6408 const PetscInt *cone, *support; 6409 PetscInt coneNew[2], coneSize, c, supportSize, s; 6410 6411 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6412 coneNew[0] = vStartNew + (cone[0] - vStart); 6413 coneNew[1] = vStartNew + (cone[1] - vStart); 6414 coneNew[(r+1)%2] = newv; 6415 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6416 #if 1 6417 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6418 for (p = 0; p < 2; ++p) { 6419 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); 6420 } 6421 #endif 6422 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6423 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6424 for (s = 0; s < supportSize; ++s) { 6425 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6426 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6427 for (c = 0; c < coneSize; ++c) { 6428 if (cone[c] == f) break; 6429 } 6430 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6431 } 6432 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6433 #if 1 6434 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6435 for (p = 0; p < supportSize; ++p) { 6436 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); 6437 } 6438 #endif 6439 } 6440 } 6441 /* Interior faces have 2 vertices and 2 cells */ 6442 for (c = cStart; c < cEnd; ++c) { 6443 const PetscInt *cone; 6444 PetscInt coneNew[2], supportNew[2]; 6445 6446 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6447 for (r = 0; r < 4; ++r) { 6448 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6449 6450 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6451 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6452 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6453 #if 1 6454 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6455 for (p = 0; p < 2; ++p) { 6456 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); 6457 } 6458 #endif 6459 supportNew[0] = (c - cStart)*4 + r; 6460 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6461 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6462 #if 1 6463 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6464 for (p = 0; p < 2; ++p) { 6465 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); 6466 } 6467 #endif 6468 } 6469 } 6470 /* Old vertices have identical supports */ 6471 for (v = vStart; v < vEnd; ++v) { 6472 const PetscInt newp = vStartNew + (v - vStart); 6473 const PetscInt *support, *cone; 6474 PetscInt size, s; 6475 6476 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6477 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6478 for (s = 0; s < size; ++s) { 6479 PetscInt r = 0; 6480 6481 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6482 if (cone[1] == v) r = 1; 6483 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6484 } 6485 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6486 #if 1 6487 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6488 for (p = 0; p < size; ++p) { 6489 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); 6490 } 6491 #endif 6492 } 6493 /* Face vertices have 2 + cells supports */ 6494 for (f = fStart; f < fEnd; ++f) { 6495 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6496 const PetscInt *cone, *support; 6497 PetscInt size, s; 6498 6499 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6500 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6501 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6502 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6503 for (s = 0; s < size; ++s) { 6504 PetscInt r = 0; 6505 6506 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6507 if (cone[1] == f) r = 1; 6508 else if (cone[2] == f) r = 2; 6509 else if (cone[3] == f) r = 3; 6510 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6511 } 6512 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6513 #if 1 6514 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6515 for (p = 0; p < 2+size; ++p) { 6516 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); 6517 } 6518 #endif 6519 } 6520 /* Cell vertices have 4 supports */ 6521 for (c = cStart; c < cEnd; ++c) { 6522 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6523 PetscInt supportNew[4]; 6524 6525 for (r = 0; r < 4; ++r) { 6526 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6527 } 6528 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6529 } 6530 break; 6531 case 3: 6532 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6533 cMax = PetscMin(cEnd, cMax); 6534 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6535 fMax = PetscMin(fEnd, fMax); 6536 /* Interior cells have 3 faces */ 6537 for (c = cStart; c < cMax; ++c) { 6538 const PetscInt newp = cStartNew + (c - cStart)*4; 6539 const PetscInt *cone, *ornt; 6540 PetscInt coneNew[3], orntNew[3]; 6541 6542 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6543 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6544 /* A triangle */ 6545 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6546 orntNew[0] = ornt[0]; 6547 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6548 orntNew[1] = -2; 6549 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6550 orntNew[2] = ornt[2]; 6551 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6552 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6553 #if 1 6554 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); 6555 for (p = 0; p < 3; ++p) { 6556 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); 6557 } 6558 #endif 6559 /* B triangle */ 6560 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6561 orntNew[0] = ornt[0]; 6562 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6563 orntNew[1] = ornt[1]; 6564 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6565 orntNew[2] = -2; 6566 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6567 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6568 #if 1 6569 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); 6570 for (p = 0; p < 3; ++p) { 6571 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); 6572 } 6573 #endif 6574 /* C triangle */ 6575 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6576 orntNew[0] = -2; 6577 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6578 orntNew[1] = ornt[1]; 6579 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6580 orntNew[2] = ornt[2]; 6581 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6582 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6583 #if 1 6584 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); 6585 for (p = 0; p < 3; ++p) { 6586 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); 6587 } 6588 #endif 6589 /* D triangle */ 6590 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6591 orntNew[0] = 0; 6592 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6593 orntNew[1] = 0; 6594 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6595 orntNew[2] = 0; 6596 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6597 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6598 #if 1 6599 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); 6600 for (p = 0; p < 3; ++p) { 6601 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); 6602 } 6603 #endif 6604 } 6605 /* 6606 2----3----3 6607 | | 6608 | B | 6609 | | 6610 0----4--- 1 6611 | | 6612 | A | 6613 | | 6614 0----2----1 6615 */ 6616 /* Hybrid cells have 4 faces */ 6617 for (c = cMax; c < cEnd; ++c) { 6618 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6619 const PetscInt *cone, *ornt; 6620 PetscInt coneNew[4], orntNew[4]; 6621 6622 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6623 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6624 /* A quad */ 6625 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6626 orntNew[0] = ornt[0]; 6627 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6628 orntNew[1] = ornt[1]; 6629 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6630 orntNew[2] = 0; 6631 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6632 orntNew[3] = 0; 6633 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6634 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6635 #if 1 6636 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); 6637 for (p = 0; p < 4; ++p) { 6638 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); 6639 } 6640 #endif 6641 /* B quad */ 6642 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6643 orntNew[0] = ornt[0]; 6644 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6645 orntNew[1] = ornt[1]; 6646 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6647 orntNew[2] = 0; 6648 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6649 orntNew[3] = 0; 6650 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6651 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6652 #if 1 6653 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); 6654 for (p = 0; p < 4; ++p) { 6655 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); 6656 } 6657 #endif 6658 } 6659 /* Interior split faces have 2 vertices and the same cells as the parent */ 6660 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6661 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6662 for (f = fStart; f < fMax; ++f) { 6663 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6664 6665 for (r = 0; r < 2; ++r) { 6666 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6667 const PetscInt *cone, *support; 6668 PetscInt coneNew[2], coneSize, c, supportSize, s; 6669 6670 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6671 coneNew[0] = vStartNew + (cone[0] - vStart); 6672 coneNew[1] = vStartNew + (cone[1] - vStart); 6673 coneNew[(r+1)%2] = newv; 6674 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6675 #if 1 6676 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6677 for (p = 0; p < 2; ++p) { 6678 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); 6679 } 6680 #endif 6681 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6682 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6683 for (s = 0; s < supportSize; ++s) { 6684 if (support[s] >= cMax) { 6685 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6686 } else { 6687 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6688 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6689 for (c = 0; c < coneSize; ++c) { 6690 if (cone[c] == f) break; 6691 } 6692 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6693 } 6694 } 6695 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6696 #if 1 6697 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6698 for (p = 0; p < supportSize; ++p) { 6699 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); 6700 } 6701 #endif 6702 } 6703 } 6704 /* Interior cell faces have 2 vertices and 2 cells */ 6705 for (c = cStart; c < cMax; ++c) { 6706 const PetscInt *cone; 6707 6708 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6709 for (r = 0; r < 3; ++r) { 6710 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6711 PetscInt coneNew[2]; 6712 PetscInt supportNew[2]; 6713 6714 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6715 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6716 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6717 #if 1 6718 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6719 for (p = 0; p < 2; ++p) { 6720 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); 6721 } 6722 #endif 6723 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6724 supportNew[1] = (c - cStart)*4 + 3; 6725 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6726 #if 1 6727 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6728 for (p = 0; p < 2; ++p) { 6729 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); 6730 } 6731 #endif 6732 } 6733 } 6734 /* Interior hybrid faces have 2 vertices and the same cells */ 6735 for (f = fMax; f < fEnd; ++f) { 6736 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6737 const PetscInt *cone; 6738 const PetscInt *support; 6739 PetscInt coneNew[2]; 6740 PetscInt supportNew[2]; 6741 PetscInt size, s, r; 6742 6743 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6744 coneNew[0] = vStartNew + (cone[0] - vStart); 6745 coneNew[1] = vStartNew + (cone[1] - vStart); 6746 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6747 #if 1 6748 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6749 for (p = 0; p < 2; ++p) { 6750 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); 6751 } 6752 #endif 6753 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6754 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6755 for (s = 0; s < size; ++s) { 6756 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6757 for (r = 0; r < 2; ++r) { 6758 if (cone[r+2] == f) break; 6759 } 6760 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6761 } 6762 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6763 #if 1 6764 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6765 for (p = 0; p < size; ++p) { 6766 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); 6767 } 6768 #endif 6769 } 6770 /* Cell hybrid faces have 2 vertices and 2 cells */ 6771 for (c = cMax; c < cEnd; ++c) { 6772 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6773 const PetscInt *cone; 6774 PetscInt coneNew[2]; 6775 PetscInt supportNew[2]; 6776 6777 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6778 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6779 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6780 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6781 #if 1 6782 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6783 for (p = 0; p < 2; ++p) { 6784 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); 6785 } 6786 #endif 6787 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6788 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6789 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6790 #if 1 6791 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6792 for (p = 0; p < 2; ++p) { 6793 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); 6794 } 6795 #endif 6796 } 6797 /* Old vertices have identical supports */ 6798 for (v = vStart; v < vEnd; ++v) { 6799 const PetscInt newp = vStartNew + (v - vStart); 6800 const PetscInt *support, *cone; 6801 PetscInt size, s; 6802 6803 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6804 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6805 for (s = 0; s < size; ++s) { 6806 if (support[s] >= fMax) { 6807 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6808 } else { 6809 PetscInt r = 0; 6810 6811 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6812 if (cone[1] == v) r = 1; 6813 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6814 } 6815 } 6816 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6817 #if 1 6818 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6819 for (p = 0; p < size; ++p) { 6820 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); 6821 } 6822 #endif 6823 } 6824 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6825 for (f = fStart; f < fMax; ++f) { 6826 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6827 const PetscInt *cone, *support; 6828 PetscInt size, newSize = 2, s; 6829 6830 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6831 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6832 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6833 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6834 for (s = 0; s < size; ++s) { 6835 PetscInt r = 0; 6836 6837 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6838 if (support[s] >= cMax) { 6839 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6840 6841 newSize += 1; 6842 } else { 6843 if (cone[1] == f) r = 1; 6844 else if (cone[2] == f) r = 2; 6845 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6846 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6847 6848 newSize += 2; 6849 } 6850 } 6851 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6852 #if 1 6853 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6854 for (p = 0; p < newSize; ++p) { 6855 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); 6856 } 6857 #endif 6858 } 6859 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6860 break; 6861 default: 6862 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6863 } 6864 PetscFunctionReturn(0); 6865 } 6866 6867 #undef __FUNCT__ 6868 #define __FUNCT__ "CellRefinerSetCoordinates" 6869 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6870 { 6871 PetscSection coordSection, coordSectionNew; 6872 Vec coordinates, coordinatesNew; 6873 PetscScalar *coords, *coordsNew; 6874 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6875 PetscErrorCode ierr; 6876 6877 PetscFunctionBegin; 6878 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6879 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6880 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6881 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6882 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6883 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6884 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6885 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6886 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6887 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6888 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6889 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6890 if (fMax < 0) fMax = fEnd; 6891 switch (refiner) { 6892 case 1: 6893 case 2: 6894 case 3: 6895 /* Simplicial and Hex 2D */ 6896 /* All vertices have the dim coordinates */ 6897 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6898 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6899 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6900 } 6901 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6902 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6903 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6904 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6905 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6906 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6907 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6908 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6909 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6910 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6911 /* Old vertices have the same coordinates */ 6912 for (v = vStart; v < vEnd; ++v) { 6913 const PetscInt newv = vStartNew + (v - vStart); 6914 PetscInt off, offnew, d; 6915 6916 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6917 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6918 for (d = 0; d < dim; ++d) { 6919 coordsNew[offnew+d] = coords[off+d]; 6920 } 6921 } 6922 /* Face vertices have the average of endpoint coordinates */ 6923 for (f = fStart; f < fMax; ++f) { 6924 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6925 const PetscInt *cone; 6926 PetscInt coneSize, offA, offB, offnew, d; 6927 6928 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6929 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6930 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6931 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6932 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6933 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6934 for (d = 0; d < dim; ++d) { 6935 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6936 } 6937 } 6938 /* Just Hex 2D */ 6939 if (refiner == 2) { 6940 /* Cell vertices have the average of corner coordinates */ 6941 for (c = cStart; c < cEnd; ++c) { 6942 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6943 PetscInt *cone = PETSC_NULL; 6944 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6945 6946 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6947 for (p = 0; p < closureSize*2; p += 2) { 6948 const PetscInt point = cone[p]; 6949 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6950 } 6951 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6952 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6953 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6954 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6955 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6956 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6957 for (d = 0; d < dim; ++d) { 6958 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6959 } 6960 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6961 } 6962 } 6963 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6964 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6965 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6966 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6967 break; 6968 default: 6969 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6970 } 6971 PetscFunctionReturn(0); 6972 } 6973 6974 #undef __FUNCT__ 6975 #define __FUNCT__ "DMPlexCreateProcessSF" 6976 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6977 { 6978 PetscInt numRoots, numLeaves, l; 6979 const PetscInt *localPoints; 6980 const PetscSFNode *remotePoints; 6981 PetscInt *localPointsNew; 6982 PetscSFNode *remotePointsNew; 6983 PetscInt *ranks, *ranksNew; 6984 PetscErrorCode ierr; 6985 6986 PetscFunctionBegin; 6987 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6988 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6989 for (l = 0; l < numLeaves; ++l) { 6990 ranks[l] = remotePoints[l].rank; 6991 } 6992 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6993 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6994 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6995 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6996 for (l = 0; l < numLeaves; ++l) { 6997 ranksNew[l] = ranks[l]; 6998 localPointsNew[l] = l; 6999 remotePointsNew[l].index = 0; 7000 remotePointsNew[l].rank = ranksNew[l]; 7001 } 7002 ierr = PetscFree(ranks);CHKERRQ(ierr); 7003 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 7004 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 7005 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 7006 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7007 PetscFunctionReturn(0); 7008 } 7009 7010 #undef __FUNCT__ 7011 #define __FUNCT__ "CellRefinerCreateSF" 7012 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7013 { 7014 PetscSF sf, sfNew, sfProcess; 7015 IS processRanks; 7016 MPI_Datatype depthType; 7017 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7018 const PetscInt *localPoints, *neighbors; 7019 const PetscSFNode *remotePoints; 7020 PetscInt *localPointsNew; 7021 PetscSFNode *remotePointsNew; 7022 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7023 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7024 PetscErrorCode ierr; 7025 7026 PetscFunctionBegin; 7027 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7028 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7029 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7030 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7031 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7032 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7033 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7034 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7035 switch (refiner) { 7036 case 3: 7037 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7038 cMax = PetscMin(cEnd, cMax); 7039 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7040 fMax = PetscMin(fEnd, fMax); 7041 } 7042 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7043 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7044 /* Caculate size of new SF */ 7045 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7046 if (numRoots < 0) PetscFunctionReturn(0); 7047 for (l = 0; l < numLeaves; ++l) { 7048 const PetscInt p = localPoints[l]; 7049 7050 switch (refiner) { 7051 case 1: 7052 /* Simplicial 2D */ 7053 if ((p >= vStart) && (p < vEnd)) { 7054 /* Old vertices stay the same */ 7055 ++numLeavesNew; 7056 } else if ((p >= fStart) && (p < fEnd)) { 7057 /* Old faces add new faces and vertex */ 7058 numLeavesNew += 1 + 2; 7059 } else if ((p >= cStart) && (p < cEnd)) { 7060 /* Old cells add new cells and interior faces */ 7061 numLeavesNew += 4 + 3; 7062 } 7063 break; 7064 case 2: 7065 /* Hex 2D */ 7066 if ((p >= vStart) && (p < vEnd)) { 7067 /* Old vertices stay the same */ 7068 ++numLeavesNew; 7069 } else if ((p >= fStart) && (p < fEnd)) { 7070 /* Old faces add new faces and vertex */ 7071 numLeavesNew += 1 + 2; 7072 } else if ((p >= cStart) && (p < cEnd)) { 7073 /* Old cells add new cells and interior faces */ 7074 numLeavesNew += 4 + 4; 7075 } 7076 break; 7077 default: 7078 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7079 } 7080 } 7081 /* Communicate depthSizes for each remote rank */ 7082 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7083 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7084 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7085 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); 7086 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7087 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7088 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7089 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7090 for (n = 0; n < numNeighbors; ++n) { 7091 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7092 } 7093 depthSizeOld[depth] = cMax; 7094 depthSizeOld[0] = vMax; 7095 depthSizeOld[depth-1] = fMax; 7096 depthSizeOld[1] = eMax; 7097 7098 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7099 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7100 7101 depthSizeOld[depth] = cEnd - cStart; 7102 depthSizeOld[0] = vEnd - vStart; 7103 depthSizeOld[depth-1] = fEnd - fStart; 7104 depthSizeOld[1] = eEnd - eStart; 7105 7106 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7107 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7108 for (n = 0; n < numNeighbors; ++n) { 7109 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7110 } 7111 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7112 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7113 /* Calculate new point SF */ 7114 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7115 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7116 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7117 for (l = 0, m = 0; l < numLeaves; ++l) { 7118 PetscInt p = localPoints[l]; 7119 PetscInt rp = remotePoints[l].index, n; 7120 PetscMPIInt rrank = remotePoints[l].rank; 7121 7122 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7123 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7124 switch (refiner) { 7125 case 1: 7126 /* Simplicial 2D */ 7127 if ((p >= vStart) && (p < vEnd)) { 7128 /* Old vertices stay the same */ 7129 localPointsNew[m] = vStartNew + (p - vStart); 7130 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7131 remotePointsNew[m].rank = rrank; 7132 ++m; 7133 } else if ((p >= fStart) && (p < fEnd)) { 7134 /* Old faces add new faces and vertex */ 7135 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7136 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7137 remotePointsNew[m].rank = rrank; 7138 ++m; 7139 for (r = 0; r < 2; ++r, ++m) { 7140 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7141 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7142 remotePointsNew[m].rank = rrank; 7143 } 7144 } else if ((p >= cStart) && (p < cEnd)) { 7145 /* Old cells add new cells and interior faces */ 7146 for (r = 0; r < 4; ++r, ++m) { 7147 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7148 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7149 remotePointsNew[m].rank = rrank; 7150 } 7151 for (r = 0; r < 3; ++r, ++m) { 7152 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7153 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7154 remotePointsNew[m].rank = rrank; 7155 } 7156 } 7157 break; 7158 case 2: 7159 /* Hex 2D */ 7160 if ((p >= vStart) && (p < vEnd)) { 7161 /* Old vertices stay the same */ 7162 localPointsNew[m] = vStartNew + (p - vStart); 7163 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7164 remotePointsNew[m].rank = rrank; 7165 ++m; 7166 } else if ((p >= fStart) && (p < fEnd)) { 7167 /* Old faces add new faces and vertex */ 7168 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7169 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7170 remotePointsNew[m].rank = rrank; 7171 ++m; 7172 for (r = 0; r < 2; ++r, ++m) { 7173 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7174 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7175 remotePointsNew[m].rank = rrank; 7176 } 7177 } else if ((p >= cStart) && (p < cEnd)) { 7178 /* Old cells add new cells and interior faces */ 7179 for (r = 0; r < 4; ++r, ++m) { 7180 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7181 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7182 remotePointsNew[m].rank = rrank; 7183 } 7184 for (r = 0; r < 4; ++r, ++m) { 7185 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7186 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7187 remotePointsNew[m].rank = rrank; 7188 } 7189 } 7190 break; 7191 case 3: 7192 /* Hybrid simplicial 2D */ 7193 if ((p >= vStart) && (p < vEnd)) { 7194 /* Old vertices stay the same */ 7195 localPointsNew[m] = vStartNew + (p - vStart); 7196 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7197 remotePointsNew[m].rank = rrank; 7198 ++m; 7199 } else if ((p >= fStart) && (p < fMax)) { 7200 /* Old interior faces add new faces and vertex */ 7201 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7202 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7203 remotePointsNew[m].rank = rrank; 7204 ++m; 7205 for (r = 0; r < 2; ++r, ++m) { 7206 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7207 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7208 remotePointsNew[m].rank = rrank; 7209 } 7210 } else if ((p >= fMax) && (p < fEnd)) { 7211 /* Old hybrid faces stay the same */ 7212 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7213 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7214 remotePointsNew[m].rank = rrank; 7215 ++m; 7216 } else if ((p >= cStart) && (p < cMax)) { 7217 /* Old interior cells add new cells and interior faces */ 7218 for (r = 0; r < 4; ++r, ++m) { 7219 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7220 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7221 remotePointsNew[m].rank = rrank; 7222 } 7223 for (r = 0; r < 3; ++r, ++m) { 7224 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7225 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7226 remotePointsNew[m].rank = rrank; 7227 } 7228 } else if ((p >= cStart) && (p < cMax)) { 7229 /* Old hybrid cells add new cells and hybrid face */ 7230 for (r = 0; r < 2; ++r, ++m) { 7231 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7232 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7233 remotePointsNew[m].rank = rrank; 7234 } 7235 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7236 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]); 7237 remotePointsNew[m].rank = rrank; 7238 ++m; 7239 } 7240 break; 7241 default: 7242 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7243 } 7244 } 7245 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7246 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7247 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7248 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7249 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7250 PetscFunctionReturn(0); 7251 } 7252 7253 #undef __FUNCT__ 7254 #define __FUNCT__ "CellRefinerCreateLabels" 7255 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7256 { 7257 PetscInt numLabels, l; 7258 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7259 PetscErrorCode ierr; 7260 7261 PetscFunctionBegin; 7262 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7263 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7264 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7265 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7266 7267 cStartNew = 0; 7268 vStartNew = depthSize[2]; 7269 fStartNew = depthSize[2] + depthSize[0]; 7270 7271 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7272 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7273 switch (refiner) { 7274 case 3: 7275 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7276 cMax = PetscMin(cEnd, cMax); 7277 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7278 fMax = PetscMin(fEnd, fMax); 7279 } 7280 for (l = 0; l < numLabels; ++l) { 7281 DMLabel label, labelNew; 7282 const char *lname; 7283 PetscBool isDepth; 7284 IS valueIS; 7285 const PetscInt *values; 7286 PetscInt numValues, val; 7287 7288 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7289 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7290 if (isDepth) continue; 7291 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7292 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7293 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7294 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7295 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7296 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7297 for (val = 0; val < numValues; ++val) { 7298 IS pointIS; 7299 const PetscInt *points; 7300 PetscInt numPoints, n; 7301 7302 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7303 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7304 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7305 for (n = 0; n < numPoints; ++n) { 7306 const PetscInt p = points[n]; 7307 switch (refiner) { 7308 case 1: 7309 /* Simplicial 2D */ 7310 if ((p >= vStart) && (p < vEnd)) { 7311 /* Old vertices stay the same */ 7312 newp = vStartNew + (p - vStart); 7313 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7314 } else if ((p >= fStart) && (p < fEnd)) { 7315 /* Old faces add new faces and vertex */ 7316 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7317 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7318 for (r = 0; r < 2; ++r) { 7319 newp = fStartNew + (p - fStart)*2 + r; 7320 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7321 } 7322 } else if ((p >= cStart) && (p < cEnd)) { 7323 /* Old cells add new cells and interior faces */ 7324 for (r = 0; r < 4; ++r) { 7325 newp = cStartNew + (p - cStart)*4 + r; 7326 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7327 } 7328 for (r = 0; r < 3; ++r) { 7329 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7330 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7331 } 7332 } 7333 break; 7334 case 2: 7335 /* Hex 2D */ 7336 if ((p >= vStart) && (p < vEnd)) { 7337 /* Old vertices stay the same */ 7338 newp = vStartNew + (p - vStart); 7339 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7340 } else if ((p >= fStart) && (p < fEnd)) { 7341 /* Old faces add new faces and vertex */ 7342 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7343 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7344 for (r = 0; r < 2; ++r) { 7345 newp = fStartNew + (p - fStart)*2 + r; 7346 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7347 } 7348 } else if ((p >= cStart) && (p < cEnd)) { 7349 /* Old cells add new cells and interior faces and vertex */ 7350 for (r = 0; r < 4; ++r) { 7351 newp = cStartNew + (p - cStart)*4 + r; 7352 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7353 } 7354 for (r = 0; r < 4; ++r) { 7355 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7356 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7357 } 7358 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7359 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7360 } 7361 break; 7362 case 3: 7363 /* Hybrid simplicial 2D */ 7364 if ((p >= vStart) && (p < vEnd)) { 7365 /* Old vertices stay the same */ 7366 newp = vStartNew + (p - vStart); 7367 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7368 } else if ((p >= fStart) && (p < fMax)) { 7369 /* Old interior faces add new faces and vertex */ 7370 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7371 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7372 for (r = 0; r < 2; ++r) { 7373 newp = fStartNew + (p - fStart)*2 + r; 7374 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7375 } 7376 } else if ((p >= fMax) && (p < fEnd)) { 7377 /* Old hybrid faces stay the same */ 7378 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7379 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7380 } else if ((p >= cStart) && (p < cMax)) { 7381 /* Old interior cells add new cells and interior faces */ 7382 for (r = 0; r < 4; ++r) { 7383 newp = cStartNew + (p - cStart)*4 + r; 7384 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7385 } 7386 for (r = 0; r < 3; ++r) { 7387 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7388 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7389 } 7390 } else if ((p >= cMax) && (p < cEnd)) { 7391 /* Old hybrid cells add new cells and hybrid face */ 7392 for (r = 0; r < 2; ++r) { 7393 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7394 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7395 } 7396 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7397 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7398 } 7399 break; 7400 default: 7401 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7402 } 7403 } 7404 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7405 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7406 } 7407 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7408 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7409 if (0) { 7410 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7411 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7412 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7413 } 7414 } 7415 PetscFunctionReturn(0); 7416 } 7417 7418 #undef __FUNCT__ 7419 #define __FUNCT__ "DMPlexRefine_Uniform" 7420 /* This will only work for interpolated meshes */ 7421 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7422 { 7423 DM rdm; 7424 PetscInt *depthSize; 7425 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7426 PetscErrorCode ierr; 7427 7428 PetscFunctionBegin; 7429 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7430 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7431 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7432 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7433 /* Calculate number of new points of each depth */ 7434 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7435 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7436 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7437 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7438 /* Step 1: Set chart */ 7439 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 7440 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7441 /* Step 2: Set cone/support sizes */ 7442 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7443 /* Step 3: Setup refined DM */ 7444 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7445 /* Step 4: Set cones and supports */ 7446 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7447 /* Step 5: Stratify */ 7448 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7449 /* Step 6: Set coordinates for vertices */ 7450 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7451 /* Step 7: Create pointSF */ 7452 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7453 /* Step 8: Create labels */ 7454 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7455 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7456 7457 *dmRefined = rdm; 7458 #if 0 7459 DM_Plex *mesh = (DM_Plex*) dm->data; 7460 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 7461 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 7462 7463 PetscFunctionBegin; 7464 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7465 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 7466 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7467 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7468 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 7469 7470 /* Count number of new cells which are normal and extra */ 7471 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 7472 7473 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 7474 for (c = cStart; c < cEnd2; ++c) { 7475 PetscInt n; 7476 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7477 7478 newNumCellsNormal += n; 7479 } 7480 for (c = cEnd2; c < cEnd; ++c) { 7481 PetscInt n; 7482 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7483 7484 newNumCellsExtra += n; 7485 } 7486 newNumCells = newNumCellsNormal + newNumCellsExtra; 7487 /* Count number of new vertices which are normal and extra */ 7488 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 7489 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 7490 for (c = cStart; c < cEnd; ++c) { 7491 PetscInt *closure = PETSC_NULL; 7492 PetscInt closureSize, numCorners = 0, p; 7493 7494 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7495 for (p = 0; p < closureSize*2; p += 2) { 7496 const PetscInt point = closure[p]; 7497 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 7498 } 7499 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 7500 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7501 } 7502 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 7503 for (c = cEnd2; c < cEnd; ++c) { 7504 PetscInt *closure = PETSC_NULL; 7505 PetscInt closureSize, numCorners = 0, p; 7506 7507 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7508 for (p = 0; p < closureSize*2; p += 2) { 7509 const PetscInt point = closure[p]; 7510 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 7511 } 7512 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 7513 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7514 } /* for */ 7515 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 7516 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 7517 7518 #if 1 7519 PetscInt oldNumCellsNormal = cEnd2 - cStart; 7520 PetscInt oldNumCellsExtra = cEnd - cEnd2; 7521 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 7522 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 7523 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 7524 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 7525 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 7526 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 7527 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 7528 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 7529 ierr = PetscSynchronizedFlush(comm); 7530 #endif 7531 7532 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 7533 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 7534 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 7535 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 7536 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 7537 /* Set cone and support sizes for new normal cells */ 7538 PetscInt newCell = 0; 7539 for (c = cStart; c < cEnd2; ++c) { 7540 PetscInt coneSize, n, i; 7541 7542 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7543 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7544 for (i = 0; i < n; ++i, ++newCell) { 7545 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 7546 } 7547 7548 PetscInt *closure = PETSC_NULL; 7549 PetscInt closureSize, numCorners = 0, p; 7550 7551 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7552 for (p = 0; p < closureSize*2; p += 2) { 7553 const PetscInt point = closure[p]; 7554 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 7555 } 7556 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); */ /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7557 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7558 } 7559 7560 /* Reset current new cell value and loop over censored cells. */ 7561 curNewCell = _orderNewMesh->cellsCensored().min(); 7562 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7563 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7564 /* Set new cone and support sizes */ 7565 cV.clear(); 7566 sieve->cone(*c_iter, cV); 7567 const point_type * cone = cV.getPoints(); 7568 const int coneSize = cV.getSize(); 7569 7570 const point_type * newCells; 7571 int numNewCells = 0; 7572 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7573 7574 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7575 newSieve->setConeSize(curNewCell, coneSize); 7576 for (int iVertex=0; iVertex < coneSize; ++iVertex) { 7577 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7578 } /* for */ 7579 } /* for */ 7580 } /* for */ 7581 newSieve->allocate(); 7582 7583 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7584 7585 /* Create refined cells in new sieve. */ 7586 curNewCell = _orderNewMesh->cellsNormal().min(); 7587 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7588 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7589 cV.clear(); 7590 sieve->cone(*c_iter, cV); 7591 const point_type *cone = cV.getPoints(); 7592 const int coneSize = cV.getSize(); 7593 7594 const point_type * newCells; 7595 int numNewCells = 0; 7596 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7597 7598 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7599 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7600 } /* for */ 7601 } /* for */ 7602 curNewCell = _orderNewMesh->cellsCensored().min(); 7603 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7604 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7605 cV.clear(); 7606 sieve->cone(*c_iter, cV); 7607 const point_type *cone = cV.getPoints(); 7608 const int coneSize = cV.getSize(); 7609 7610 const point_type *newCells; 7611 int numNewCells = 0; 7612 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7613 7614 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7615 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7616 } /* for */ 7617 } /* for */ 7618 newSieve->symmetrize(); 7619 7620 /* Set coordinates in refined mesh. */ 7621 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7622 assert(!coordinates.isNull()); 7623 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7624 assert(!newCoordinates.isNull()); 7625 7626 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7627 assert(vertices->size() > 0); 7628 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7629 assert(spaceDim > 0); 7630 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7631 7632 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7633 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7634 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7635 } /* for */ 7636 newCoordinates->allocatePoint(); 7637 7638 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7639 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7640 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7641 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7642 } /* for */ 7643 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7644 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7645 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7646 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7647 } /* for */ 7648 7649 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7650 7651 /* Create sensored depth */ 7652 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7653 assert(!censoredLabel.isNull()); 7654 7655 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7656 7657 newSieve->roots(depthVisitor); 7658 while (depthVisitor.isModified()) { 7659 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7660 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7661 7662 depthVisitor.clear(); 7663 newSieve->support(modifiedPoints, depthVisitor); 7664 } /* while */ 7665 7666 /* Stratify refined mesh */ 7667 /* Calculate new point SF */ 7668 _calcNewOverlap(newMesh, mesh, refiner); 7669 /* Calculate new labels */ 7670 _createLabels(newMesh, mesh, refiner); 7671 #endif 7672 PetscFunctionReturn(0); 7673 } 7674 7675 #undef __FUNCT__ 7676 #define __FUNCT__ "DMPlexSetRefinementUniform" 7677 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7678 { 7679 DM_Plex *mesh = (DM_Plex*) dm->data; 7680 7681 PetscFunctionBegin; 7682 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7683 mesh->refinementUniform = refinementUniform; 7684 PetscFunctionReturn(0); 7685 } 7686 7687 #undef __FUNCT__ 7688 #define __FUNCT__ "DMPlexGetRefinementUniform" 7689 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7690 { 7691 DM_Plex *mesh = (DM_Plex*) dm->data; 7692 7693 PetscFunctionBegin; 7694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7695 PetscValidPointer(refinementUniform, 2); 7696 *refinementUniform = mesh->refinementUniform; 7697 PetscFunctionReturn(0); 7698 } 7699 7700 #undef __FUNCT__ 7701 #define __FUNCT__ "DMPlexSetRefinementLimit" 7702 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7703 { 7704 DM_Plex *mesh = (DM_Plex*) dm->data; 7705 7706 PetscFunctionBegin; 7707 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7708 mesh->refinementLimit = refinementLimit; 7709 PetscFunctionReturn(0); 7710 } 7711 7712 #undef __FUNCT__ 7713 #define __FUNCT__ "DMPlexGetRefinementLimit" 7714 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7715 { 7716 DM_Plex *mesh = (DM_Plex*) dm->data; 7717 7718 PetscFunctionBegin; 7719 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7720 PetscValidPointer(refinementLimit, 2); 7721 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7722 *refinementLimit = mesh->refinementLimit; 7723 PetscFunctionReturn(0); 7724 } 7725 7726 #undef __FUNCT__ 7727 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7728 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7729 { 7730 PetscInt dim, cStart, coneSize, cMax; 7731 PetscErrorCode ierr; 7732 7733 PetscFunctionBegin; 7734 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7735 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7736 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7737 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7738 switch (dim) { 7739 case 2: 7740 switch (coneSize) { 7741 case 3: 7742 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7743 else *cellRefiner = 1; /* Triangular */ 7744 break; 7745 case 4: 7746 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7747 else *cellRefiner = 2; /* Quadrilateral */ 7748 break; 7749 default: 7750 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7751 } 7752 break; 7753 default: 7754 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7755 } 7756 PetscFunctionReturn(0); 7757 } 7758 7759 #undef __FUNCT__ 7760 #define __FUNCT__ "DMRefine_Plex" 7761 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7762 { 7763 PetscReal refinementLimit; 7764 PetscInt dim, cStart, cEnd; 7765 char genname[1024], *name = PETSC_NULL; 7766 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7767 PetscErrorCode ierr; 7768 7769 PetscFunctionBegin; 7770 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7771 if (isUniform) { 7772 CellRefiner cellRefiner; 7773 7774 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7775 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7776 PetscFunctionReturn(0); 7777 } 7778 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7779 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7780 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7781 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7782 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7783 if (flg) name = genname; 7784 if (name) { 7785 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7786 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7787 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7788 } 7789 switch (dim) { 7790 case 2: 7791 if (!name || isTriangle) { 7792 #if defined(PETSC_HAVE_TRIANGLE) 7793 double *maxVolumes; 7794 PetscInt c; 7795 7796 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7797 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7798 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7799 #else 7800 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7801 #endif 7802 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7803 break; 7804 case 3: 7805 if (!name || isCTetgen) { 7806 #if defined(PETSC_HAVE_CTETGEN) 7807 PetscReal *maxVolumes; 7808 PetscInt c; 7809 7810 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7811 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7812 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7813 #else 7814 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7815 #endif 7816 } else if (isTetgen) { 7817 #if defined(PETSC_HAVE_TETGEN) 7818 double *maxVolumes; 7819 PetscInt c; 7820 7821 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7822 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7823 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7824 #else 7825 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7826 #endif 7827 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7828 break; 7829 default: 7830 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7831 } 7832 PetscFunctionReturn(0); 7833 } 7834 7835 #undef __FUNCT__ 7836 #define __FUNCT__ "DMPlexGetDepth" 7837 /*@ 7838 DMPlexGetDepth - get the number of strata 7839 7840 Not Collective 7841 7842 Input Parameters: 7843 . dm - The DMPlex object 7844 7845 Output Parameters: 7846 . depth - number of strata 7847 7848 Level: developer 7849 7850 Notes: 7851 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7852 7853 .keywords: mesh, points 7854 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7855 @*/ 7856 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7857 { 7858 PetscInt d; 7859 PetscErrorCode ierr; 7860 7861 PetscFunctionBegin; 7862 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7863 PetscValidPointer(depth, 2); 7864 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7865 *depth = d-1; 7866 PetscFunctionReturn(0); 7867 } 7868 7869 #undef __FUNCT__ 7870 #define __FUNCT__ "DMPlexGetDepthStratum" 7871 /*@ 7872 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7873 7874 Not Collective 7875 7876 Input Parameters: 7877 + dm - The DMPlex object 7878 - stratumValue - The requested depth 7879 7880 Output Parameters: 7881 + start - The first point at this depth 7882 - end - One beyond the last point at this depth 7883 7884 Level: developer 7885 7886 .keywords: mesh, points 7887 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7888 @*/ 7889 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7890 { 7891 DM_Plex *mesh = (DM_Plex*) dm->data; 7892 DMLabel next = mesh->labels; 7893 PetscBool flg = PETSC_FALSE; 7894 PetscInt depth; 7895 PetscErrorCode ierr; 7896 7897 PetscFunctionBegin; 7898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7899 if (stratumValue < 0) { 7900 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7901 PetscFunctionReturn(0); 7902 } else { 7903 PetscInt pStart, pEnd; 7904 7905 if (start) *start = 0; 7906 if (end) *end = 0; 7907 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7908 if (pStart == pEnd) PetscFunctionReturn(0); 7909 } 7910 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7911 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7912 /* We should have a generic GetLabel() and a Label class */ 7913 while (next) { 7914 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7915 if (flg) break; 7916 next = next->next; 7917 } 7918 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7919 depth = stratumValue; 7920 if ((depth < 0) || (depth >= next->numStrata)) { 7921 if (start) *start = 0; 7922 if (end) *end = 0; 7923 } else { 7924 if (start) *start = next->points[next->stratumOffsets[depth]]; 7925 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7926 } 7927 PetscFunctionReturn(0); 7928 } 7929 7930 #undef __FUNCT__ 7931 #define __FUNCT__ "DMPlexGetHeightStratum" 7932 /*@ 7933 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7934 7935 Not Collective 7936 7937 Input Parameters: 7938 + dm - The DMPlex object 7939 - stratumValue - The requested height 7940 7941 Output Parameters: 7942 + start - The first point at this height 7943 - end - One beyond the last point at this height 7944 7945 Level: developer 7946 7947 .keywords: mesh, points 7948 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7949 @*/ 7950 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7951 { 7952 DM_Plex *mesh = (DM_Plex*) dm->data; 7953 DMLabel next = mesh->labels; 7954 PetscBool flg = PETSC_FALSE; 7955 PetscInt depth; 7956 PetscErrorCode ierr; 7957 7958 PetscFunctionBegin; 7959 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7960 if (stratumValue < 0) { 7961 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7962 } else { 7963 PetscInt pStart, pEnd; 7964 7965 if (start) *start = 0; 7966 if (end) *end = 0; 7967 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7968 if (pStart == pEnd) PetscFunctionReturn(0); 7969 } 7970 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7971 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7972 /* We should have a generic GetLabel() and a Label class */ 7973 while (next) { 7974 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7975 if (flg) break; 7976 next = next->next; 7977 } 7978 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7979 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7980 if ((depth < 0) || (depth >= next->numStrata)) { 7981 if (start) *start = 0; 7982 if (end) *end = 0; 7983 } else { 7984 if (start) *start = next->points[next->stratumOffsets[depth]]; 7985 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7986 } 7987 PetscFunctionReturn(0); 7988 } 7989 7990 #undef __FUNCT__ 7991 #define __FUNCT__ "DMPlexCreateSectionInitial" 7992 /* Set the number of dof on each point and separate by fields */ 7993 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7994 { 7995 PetscInt *numDofTot; 7996 PetscInt pStart = 0, pEnd = 0; 7997 PetscInt p, d, f; 7998 PetscErrorCode ierr; 7999 8000 PetscFunctionBegin; 8001 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 8002 for (d = 0; d <= dim; ++d) { 8003 numDofTot[d] = 0; 8004 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 8005 } 8006 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 8007 if (numFields > 0) { 8008 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 8009 if (numComp) { 8010 for (f = 0; f < numFields; ++f) { 8011 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 8012 } 8013 } 8014 } 8015 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8016 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 8017 for (d = 0; d <= dim; ++d) { 8018 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 8019 for (p = pStart; p < pEnd; ++p) { 8020 for (f = 0; f < numFields; ++f) { 8021 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 8022 } 8023 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 8024 } 8025 } 8026 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 8027 PetscFunctionReturn(0); 8028 } 8029 8030 #undef __FUNCT__ 8031 #define __FUNCT__ "DMPlexCreateSectionBCDof" 8032 /* Set the number of dof on each point and separate by fields 8033 If constDof is PETSC_DETERMINE, constrain every dof on the point 8034 */ 8035 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 8036 { 8037 PetscInt numFields; 8038 PetscInt bc; 8039 PetscErrorCode ierr; 8040 8041 PetscFunctionBegin; 8042 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8043 for (bc = 0; bc < numBC; ++bc) { 8044 PetscInt field = 0; 8045 const PetscInt *idx; 8046 PetscInt n, i; 8047 8048 if (numFields) field = bcField[bc]; 8049 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 8050 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8051 for (i = 0; i < n; ++i) { 8052 const PetscInt p = idx[i]; 8053 PetscInt numConst = constDof; 8054 8055 /* Constrain every dof on the point */ 8056 if (numConst < 0) { 8057 if (numFields) { 8058 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 8059 } else { 8060 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 8061 } 8062 } 8063 if (numFields) { 8064 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 8065 } 8066 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 8067 } 8068 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8069 } 8070 PetscFunctionReturn(0); 8071 } 8072 8073 #undef __FUNCT__ 8074 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 8075 /* Set the constrained indices on each point and separate by fields */ 8076 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 8077 { 8078 PetscInt *maxConstraints; 8079 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 8080 PetscErrorCode ierr; 8081 8082 PetscFunctionBegin; 8083 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8084 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8085 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 8086 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 8087 for (p = pStart; p < pEnd; ++p) { 8088 PetscInt cdof; 8089 8090 if (numFields) { 8091 for (f = 0; f < numFields; ++f) { 8092 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 8093 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 8094 } 8095 } else { 8096 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8097 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 8098 } 8099 } 8100 for (f = 0; f < numFields; ++f) { 8101 maxConstraints[numFields] += maxConstraints[f]; 8102 } 8103 if (maxConstraints[numFields]) { 8104 PetscInt *indices; 8105 8106 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8107 for (p = pStart; p < pEnd; ++p) { 8108 PetscInt cdof, d; 8109 8110 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8111 if (cdof) { 8112 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 8113 if (numFields) { 8114 PetscInt numConst = 0, foff = 0; 8115 8116 for (f = 0; f < numFields; ++f) { 8117 PetscInt cfdof, fdof; 8118 8119 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8120 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 8121 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 8122 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 8123 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 8124 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 8125 numConst += cfdof; 8126 foff += fdof; 8127 } 8128 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8129 } else { 8130 for (d = 0; d < cdof; ++d) indices[d] = d; 8131 } 8132 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8133 } 8134 } 8135 ierr = PetscFree(indices);CHKERRQ(ierr); 8136 } 8137 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 8138 PetscFunctionReturn(0); 8139 } 8140 8141 #undef __FUNCT__ 8142 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 8143 /* Set the constrained field indices on each point */ 8144 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 8145 { 8146 const PetscInt *points, *indices; 8147 PetscInt numFields, maxDof, numPoints, p, numConstraints; 8148 PetscErrorCode ierr; 8149 8150 PetscFunctionBegin; 8151 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8152 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 8153 8154 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 8155 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 8156 if (!constraintIndices) { 8157 PetscInt *idx, i; 8158 8159 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8160 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 8161 for (i = 0; i < maxDof; ++i) idx[i] = i; 8162 for (p = 0; p < numPoints; ++p) { 8163 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 8164 } 8165 ierr = PetscFree(idx);CHKERRQ(ierr); 8166 } else { 8167 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 8168 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 8169 for (p = 0; p < numPoints; ++p) { 8170 PetscInt fcdof; 8171 8172 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 8173 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); 8174 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 8175 } 8176 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 8177 } 8178 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 8179 PetscFunctionReturn(0); 8180 } 8181 8182 #undef __FUNCT__ 8183 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 8184 /* Set the constrained indices on each point and separate by fields */ 8185 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 8186 { 8187 PetscInt *indices; 8188 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 8189 PetscErrorCode ierr; 8190 8191 PetscFunctionBegin; 8192 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8193 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8194 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8195 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 8196 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8197 for (p = pStart; p < pEnd; ++p) { 8198 PetscInt cdof, d; 8199 8200 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8201 if (cdof) { 8202 PetscInt numConst = 0, foff = 0; 8203 8204 for (f = 0; f < numFields; ++f) { 8205 const PetscInt *fcind; 8206 PetscInt fdof, fcdof; 8207 8208 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8209 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8210 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 8211 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8212 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 8213 foff += fdof; 8214 numConst += fcdof; 8215 } 8216 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8217 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8218 } 8219 } 8220 ierr = PetscFree(indices);CHKERRQ(ierr); 8221 PetscFunctionReturn(0); 8222 } 8223 8224 #undef __FUNCT__ 8225 #define __FUNCT__ "DMPlexCreateSection" 8226 /*@C 8227 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8228 8229 Not Collective 8230 8231 Input Parameters: 8232 + dm - The DMPlex object 8233 . dim - The spatial dimension of the problem 8234 . numFields - The number of fields in the problem 8235 . numComp - An array of size numFields that holds the number of components for each field 8236 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8237 . numBC - The number of boundary conditions 8238 . bcField - An array of size numBC giving the field number for each boundry condition 8239 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8240 8241 Output Parameter: 8242 . section - The PetscSection object 8243 8244 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 8245 nubmer of dof for field 0 on each edge. 8246 8247 Level: developer 8248 8249 .keywords: mesh, elements 8250 .seealso: DMPlexCreate(), PetscSectionCreate() 8251 @*/ 8252 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8253 { 8254 PetscErrorCode ierr; 8255 8256 PetscFunctionBegin; 8257 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8258 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8259 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8260 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8261 { 8262 PetscBool view = PETSC_FALSE; 8263 8264 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8265 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8266 } 8267 PetscFunctionReturn(0); 8268 } 8269 8270 #undef __FUNCT__ 8271 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8272 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8273 { 8274 PetscSection section; 8275 PetscErrorCode ierr; 8276 8277 PetscFunctionBegin; 8278 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8279 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8280 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8281 PetscFunctionReturn(0); 8282 } 8283 8284 #undef __FUNCT__ 8285 #define __FUNCT__ "DMPlexGetCoordinateSection" 8286 /*@ 8287 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8288 8289 Not Collective 8290 8291 Input Parameter: 8292 . dm - The DMPlex object 8293 8294 Output Parameter: 8295 . section - The PetscSection object 8296 8297 Level: intermediate 8298 8299 .keywords: mesh, coordinates 8300 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8301 @*/ 8302 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8303 { 8304 DM cdm; 8305 PetscErrorCode ierr; 8306 8307 PetscFunctionBegin; 8308 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8309 PetscValidPointer(section, 2); 8310 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8311 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8312 PetscFunctionReturn(0); 8313 } 8314 8315 #undef __FUNCT__ 8316 #define __FUNCT__ "DMPlexSetCoordinateSection" 8317 /*@ 8318 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8319 8320 Not Collective 8321 8322 Input Parameters: 8323 + dm - The DMPlex object 8324 - section - The PetscSection object 8325 8326 Level: intermediate 8327 8328 .keywords: mesh, coordinates 8329 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8330 @*/ 8331 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8332 { 8333 DM cdm; 8334 PetscErrorCode ierr; 8335 8336 PetscFunctionBegin; 8337 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8338 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8339 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8340 PetscFunctionReturn(0); 8341 } 8342 8343 #undef __FUNCT__ 8344 #define __FUNCT__ "DMPlexGetConeSection" 8345 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8346 { 8347 DM_Plex *mesh = (DM_Plex*) dm->data; 8348 8349 PetscFunctionBegin; 8350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8351 if (section) *section = mesh->coneSection; 8352 PetscFunctionReturn(0); 8353 } 8354 8355 #undef __FUNCT__ 8356 #define __FUNCT__ "DMPlexGetCones" 8357 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8358 { 8359 DM_Plex *mesh = (DM_Plex*) dm->data; 8360 8361 PetscFunctionBegin; 8362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8363 if (cones) *cones = mesh->cones; 8364 PetscFunctionReturn(0); 8365 } 8366 8367 #undef __FUNCT__ 8368 #define __FUNCT__ "DMPlexGetConeOrientations" 8369 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8370 { 8371 DM_Plex *mesh = (DM_Plex*) dm->data; 8372 8373 PetscFunctionBegin; 8374 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8375 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8376 PetscFunctionReturn(0); 8377 } 8378 8379 #undef __FUNCT__ 8380 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8381 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8382 { 8383 const PetscInt embedDim = 2; 8384 PetscReal x = PetscRealPart(point[0]); 8385 PetscReal y = PetscRealPart(point[1]); 8386 PetscReal v0[2], J[4], invJ[4], detJ; 8387 PetscReal xi, eta; 8388 PetscErrorCode ierr; 8389 8390 PetscFunctionBegin; 8391 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8392 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8393 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8394 8395 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8396 else *cell = -1; 8397 PetscFunctionReturn(0); 8398 } 8399 8400 #undef __FUNCT__ 8401 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8402 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8403 { 8404 PetscSection coordSection; 8405 Vec coordsLocal; 8406 const PetscScalar *coords; 8407 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8408 PetscReal x = PetscRealPart(point[0]); 8409 PetscReal y = PetscRealPart(point[1]); 8410 PetscInt crossings = 0, f; 8411 PetscErrorCode ierr; 8412 8413 PetscFunctionBegin; 8414 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8415 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8416 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8417 for (f = 0; f < 4; ++f) { 8418 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8419 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8420 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8421 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8422 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8423 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8424 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8425 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8426 if ((cond1 || cond2) && above) ++crossings; 8427 } 8428 if (crossings % 2) *cell = c; 8429 else *cell = -1; 8430 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8431 PetscFunctionReturn(0); 8432 } 8433 8434 #undef __FUNCT__ 8435 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8436 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8437 { 8438 const PetscInt embedDim = 3; 8439 PetscReal v0[3], J[9], invJ[9], detJ; 8440 PetscReal x = PetscRealPart(point[0]); 8441 PetscReal y = PetscRealPart(point[1]); 8442 PetscReal z = PetscRealPart(point[2]); 8443 PetscReal xi, eta, zeta; 8444 PetscErrorCode ierr; 8445 8446 PetscFunctionBegin; 8447 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8448 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8449 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8450 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8451 8452 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8453 else *cell = -1; 8454 PetscFunctionReturn(0); 8455 } 8456 8457 #undef __FUNCT__ 8458 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8459 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8460 { 8461 PetscSection coordSection; 8462 Vec coordsLocal; 8463 const PetscScalar *coords; 8464 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8465 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8466 PetscBool found = PETSC_TRUE; 8467 PetscInt f; 8468 PetscErrorCode ierr; 8469 8470 PetscFunctionBegin; 8471 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8472 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8473 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8474 for (f = 0; f < 6; ++f) { 8475 /* Check the point is under plane */ 8476 /* Get face normal */ 8477 PetscReal v_i[3]; 8478 PetscReal v_j[3]; 8479 PetscReal normal[3]; 8480 PetscReal pp[3]; 8481 PetscReal dot; 8482 8483 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8484 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8485 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8486 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8487 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8488 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8489 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8490 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8491 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8492 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8493 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8494 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8495 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8496 8497 /* Check that projected point is in face (2D location problem) */ 8498 if (dot < 0.0) { 8499 found = PETSC_FALSE; 8500 break; 8501 } 8502 } 8503 if (found) *cell = c; 8504 else *cell = -1; 8505 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8506 PetscFunctionReturn(0); 8507 } 8508 8509 #undef __FUNCT__ 8510 #define __FUNCT__ "DMLocatePoints_Plex" 8511 /* 8512 Need to implement using the guess 8513 */ 8514 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8515 { 8516 PetscInt cell = -1 /*, guess = -1*/; 8517 PetscInt bs, numPoints, p; 8518 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8519 PetscInt *cells; 8520 PetscScalar *a; 8521 PetscErrorCode ierr; 8522 8523 PetscFunctionBegin; 8524 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8525 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8526 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8527 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8528 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8529 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8530 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8531 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); 8532 numPoints /= bs; 8533 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8534 for (p = 0; p < numPoints; ++p) { 8535 const PetscScalar *point = &a[p*bs]; 8536 8537 switch (dim) { 8538 case 2: 8539 for (c = cStart; c < cEnd; ++c) { 8540 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8541 switch (coneSize) { 8542 case 3: 8543 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8544 break; 8545 case 4: 8546 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8547 break; 8548 default: 8549 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8550 } 8551 if (cell >= 0) break; 8552 } 8553 break; 8554 case 3: 8555 for (c = cStart; c < cEnd; ++c) { 8556 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8557 switch (coneSize) { 8558 case 4: 8559 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8560 break; 8561 case 8: 8562 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8563 break; 8564 default: 8565 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8566 } 8567 if (cell >= 0) break; 8568 } 8569 break; 8570 default: 8571 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8572 } 8573 cells[p] = cell; 8574 } 8575 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8576 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8577 PetscFunctionReturn(0); 8578 } 8579 8580 /******************************** FEM Support **********************************/ 8581 8582 #undef __FUNCT__ 8583 #define __FUNCT__ "DMPlexVecGetClosure" 8584 /*@C 8585 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8586 8587 Not collective 8588 8589 Input Parameters: 8590 + dm - The DM 8591 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8592 . v - The local vector 8593 - point - The sieve point in the DM 8594 8595 Output Parameters: 8596 + csize - The number of values in the closure, or PETSC_NULL 8597 - values - The array of values, which is a borrowed array and should not be freed 8598 8599 Level: intermediate 8600 8601 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8602 @*/ 8603 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8604 { 8605 PetscScalar *array, *vArray; 8606 PetscInt *points = PETSC_NULL; 8607 PetscInt offsets[32]; 8608 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8609 PetscErrorCode ierr; 8610 8611 PetscFunctionBegin; 8612 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8613 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8614 if (!section) { 8615 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8616 } 8617 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8618 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8619 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8620 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8621 /* Compress out points not in the section */ 8622 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8623 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8624 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8625 points[q*2] = points[p]; 8626 points[q*2+1] = points[p+1]; 8627 ++q; 8628 } 8629 } 8630 numPoints = q; 8631 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8632 PetscInt dof, fdof; 8633 8634 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8635 for (f = 0; f < numFields; ++f) { 8636 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8637 offsets[f+1] += fdof; 8638 } 8639 size += dof; 8640 } 8641 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8642 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8643 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8644 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8645 for (p = 0; p < numPoints*2; p += 2) { 8646 PetscInt o = points[p+1]; 8647 PetscInt dof, off, d; 8648 PetscScalar *varr; 8649 8650 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8651 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8652 varr = &vArray[off]; 8653 if (numFields) { 8654 PetscInt fdof, foff, fcomp, f, c; 8655 8656 for (f = 0, foff = 0; f < numFields; ++f) { 8657 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8658 if (o >= 0) { 8659 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8660 array[offsets[f]] = varr[foff+d]; 8661 } 8662 } else { 8663 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8664 for (d = fdof/fcomp-1; d >= 0; --d) { 8665 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8666 array[offsets[f]] = varr[foff+d*fcomp+c]; 8667 } 8668 } 8669 } 8670 foff += fdof; 8671 } 8672 } else { 8673 if (o >= 0) { 8674 for (d = 0; d < dof; ++d, ++offsets[0]) { 8675 array[offsets[0]] = varr[d]; 8676 } 8677 } else { 8678 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8679 array[offsets[0]] = varr[d]; 8680 } 8681 } 8682 } 8683 } 8684 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8685 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8686 if (csize) *csize = size; 8687 *values = array; 8688 PetscFunctionReturn(0); 8689 } 8690 8691 #undef __FUNCT__ 8692 #define __FUNCT__ "DMPlexVecRestoreClosure" 8693 /*@C 8694 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8695 8696 Not collective 8697 8698 Input Parameters: 8699 + dm - The DM 8700 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8701 . v - The local vector 8702 . point - The sieve point in the DM 8703 . csize - The number of values in the closure, or PETSC_NULL 8704 - values - The array of values, which is a borrowed array and should not be freed 8705 8706 Level: intermediate 8707 8708 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8709 @*/ 8710 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8711 { 8712 PetscInt size = 0; 8713 PetscErrorCode ierr; 8714 8715 PetscFunctionBegin; 8716 /* Should work without recalculating size */ 8717 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8718 PetscFunctionReturn(0); 8719 } 8720 8721 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8722 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8723 8724 #undef __FUNCT__ 8725 #define __FUNCT__ "updatePoint_private" 8726 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8727 { 8728 PetscInt cdof; /* The number of constraints on this point */ 8729 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8730 PetscScalar *a; 8731 PetscInt off, cind = 0, k; 8732 PetscErrorCode ierr; 8733 8734 PetscFunctionBegin; 8735 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8736 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8737 a = &array[off]; 8738 if (!cdof || setBC) { 8739 if (orientation >= 0) { 8740 for (k = 0; k < dof; ++k) { 8741 fuse(&a[k], values[k]); 8742 } 8743 } else { 8744 for (k = 0; k < dof; ++k) { 8745 fuse(&a[k], values[dof-k-1]); 8746 } 8747 } 8748 } else { 8749 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8750 if (orientation >= 0) { 8751 for (k = 0; k < dof; ++k) { 8752 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8753 fuse(&a[k], values[k]); 8754 } 8755 } else { 8756 for (k = 0; k < dof; ++k) { 8757 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8758 fuse(&a[k], values[dof-k-1]); 8759 } 8760 } 8761 } 8762 PetscFunctionReturn(0); 8763 } 8764 8765 #undef __FUNCT__ 8766 #define __FUNCT__ "updatePointFields_private" 8767 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8768 { 8769 PetscScalar *a; 8770 PetscInt numFields, off, foff, f; 8771 PetscErrorCode ierr; 8772 8773 PetscFunctionBegin; 8774 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8775 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8776 a = &array[off]; 8777 for (f = 0, foff = 0; f < numFields; ++f) { 8778 PetscInt fdof, fcomp, fcdof; 8779 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8780 PetscInt cind = 0, k, c; 8781 8782 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8783 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8784 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8785 if (!fcdof || setBC) { 8786 if (orientation >= 0) { 8787 for (k = 0; k < fdof; ++k) { 8788 fuse(&a[foff+k], values[foffs[f]+k]); 8789 } 8790 } else { 8791 for (k = fdof/fcomp-1; k >= 0; --k) { 8792 for (c = 0; c < fcomp; ++c) { 8793 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8794 } 8795 } 8796 } 8797 } else { 8798 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8799 if (orientation >= 0) { 8800 for (k = 0; k < fdof; ++k) { 8801 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8802 fuse(&a[foff+k], values[foffs[f]+k]); 8803 } 8804 } else { 8805 for (k = fdof/fcomp-1; k >= 0; --k) { 8806 for (c = 0; c < fcomp; ++c) { 8807 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8808 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8809 } 8810 } 8811 } 8812 } 8813 foff += fdof; 8814 foffs[f] += fdof; 8815 } 8816 PetscFunctionReturn(0); 8817 } 8818 8819 #undef __FUNCT__ 8820 #define __FUNCT__ "DMPlexVecSetClosure" 8821 /*@C 8822 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8823 8824 Not collective 8825 8826 Input Parameters: 8827 + dm - The DM 8828 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8829 . v - The local vector 8830 . point - The sieve point in the DM 8831 . values - The array of values, which is a borrowed array and should not be freed 8832 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8833 8834 Level: intermediate 8835 8836 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8837 @*/ 8838 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8839 { 8840 PetscScalar *array; 8841 PetscInt *points = PETSC_NULL; 8842 PetscInt offsets[32]; 8843 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8844 PetscErrorCode ierr; 8845 8846 PetscFunctionBegin; 8847 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8848 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8849 if (!section) { 8850 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8851 } 8852 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8853 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8854 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8855 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8856 /* Compress out points not in the section */ 8857 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8858 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8859 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8860 points[q*2] = points[p]; 8861 points[q*2+1] = points[p+1]; 8862 ++q; 8863 } 8864 } 8865 numPoints = q; 8866 for (p = 0; p < numPoints*2; p += 2) { 8867 PetscInt fdof; 8868 8869 for (f = 0; f < numFields; ++f) { 8870 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8871 offsets[f+1] += fdof; 8872 } 8873 } 8874 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8875 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8876 if (numFields) { 8877 switch (mode) { 8878 case INSERT_VALUES: 8879 for (p = 0; p < numPoints*2; p += 2) { 8880 PetscInt o = points[p+1]; 8881 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8882 } break; 8883 case INSERT_ALL_VALUES: 8884 for (p = 0; p < numPoints*2; p += 2) { 8885 PetscInt o = points[p+1]; 8886 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8887 } break; 8888 case ADD_VALUES: 8889 for (p = 0; p < numPoints*2; p += 2) { 8890 PetscInt o = points[p+1]; 8891 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8892 } break; 8893 case ADD_ALL_VALUES: 8894 for (p = 0; p < numPoints*2; p += 2) { 8895 PetscInt o = points[p+1]; 8896 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8897 } break; 8898 default: 8899 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8900 } 8901 } else { 8902 switch (mode) { 8903 case INSERT_VALUES: 8904 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8905 PetscInt o = points[p+1]; 8906 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8907 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8908 } break; 8909 case INSERT_ALL_VALUES: 8910 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8911 PetscInt o = points[p+1]; 8912 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8913 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8914 } break; 8915 case ADD_VALUES: 8916 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8917 PetscInt o = points[p+1]; 8918 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8919 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8920 } break; 8921 case ADD_ALL_VALUES: 8922 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8923 PetscInt o = points[p+1]; 8924 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8925 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8926 } break; 8927 default: 8928 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8929 } 8930 } 8931 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8932 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8933 PetscFunctionReturn(0); 8934 } 8935 8936 #undef __FUNCT__ 8937 #define __FUNCT__ "DMPlexPrintMatSetValues" 8938 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8939 { 8940 PetscMPIInt rank; 8941 PetscInt i, j; 8942 PetscErrorCode ierr; 8943 8944 PetscFunctionBegin; 8945 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8946 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8947 for (i = 0; i < numIndices; i++) { 8948 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8949 } 8950 for (i = 0; i < numIndices; i++) { 8951 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8952 for (j = 0; j < numIndices; j++) { 8953 #if defined(PETSC_USE_COMPLEX) 8954 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8955 #else 8956 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8957 #endif 8958 } 8959 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8960 } 8961 PetscFunctionReturn(0); 8962 } 8963 8964 #undef __FUNCT__ 8965 #define __FUNCT__ "indicesPoint_private" 8966 /* . off - The global offset of this point */ 8967 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8968 { 8969 PetscInt cdof; /* The number of constraints on this point */ 8970 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8971 PetscInt cind = 0, k; 8972 PetscErrorCode ierr; 8973 8974 PetscFunctionBegin; 8975 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8976 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8977 if (!cdof || setBC) { 8978 if (orientation >= 0) { 8979 for (k = 0; k < dof; ++k) indices[k] = off+k; 8980 } else { 8981 for (k = 0; k < dof; ++k) indices[dof-k-1] = off+k; 8982 } 8983 } else { 8984 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8985 if (orientation >= 0) { 8986 for (k = 0; k < dof; ++k) { 8987 if ((cind < cdof) && (k == cdofs[cind])) { 8988 /* Insert check for returning constrained indices */ 8989 indices[k] = -(off+k+1); 8990 ++cind; 8991 } else { 8992 indices[k] = off+k-cind; 8993 } 8994 } 8995 } else { 8996 for (k = 0; k < dof; ++k) { 8997 if ((cind < cdof) && (k == cdofs[cind])) { 8998 /* Insert check for returning constrained indices */ 8999 indices[dof-k-1] = -(off+k+1); 9000 ++cind; 9001 } else { 9002 indices[dof-k-1] = off+k-cind; 9003 } 9004 } 9005 } 9006 } 9007 PetscFunctionReturn(0); 9008 } 9009 9010 #undef __FUNCT__ 9011 #define __FUNCT__ "indicesPointFields_private" 9012 /* . off - The global offset of this point */ 9013 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 9014 { 9015 PetscInt numFields, foff, f; 9016 PetscErrorCode ierr; 9017 9018 PetscFunctionBegin; 9019 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9020 for (f = 0, foff = 0; f < numFields; ++f) { 9021 PetscInt fdof, fcomp, cfdof; 9022 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 9023 PetscInt cind = 0, k, c; 9024 9025 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 9026 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 9027 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 9028 if (!cfdof || setBC) { 9029 if (orientation >= 0) { 9030 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 9031 } else { 9032 for (k = fdof/fcomp-1; k >= 0; --k) { 9033 for (c = 0; c < fcomp; ++c) { 9034 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 9035 } 9036 } 9037 } 9038 } else { 9039 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 9040 if (orientation >= 0) { 9041 for (k = 0; k < fdof; ++k) { 9042 if ((cind < cfdof) && (k == fcdofs[cind])) { 9043 indices[foffs[f]+k] = -(off+foff+k+1); 9044 ++cind; 9045 } else { 9046 indices[foffs[f]+k] = off+foff+k-cind; 9047 } 9048 } 9049 } else { 9050 for (k = fdof/fcomp-1; k >= 0; --k) { 9051 for (c = 0; c < fcomp; ++c) { 9052 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 9053 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 9054 ++cind; 9055 } else { 9056 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 9057 } 9058 } 9059 } 9060 } 9061 } 9062 foff += fdof - cfdof; 9063 foffs[f] += fdof; 9064 } 9065 PetscFunctionReturn(0); 9066 } 9067 9068 #undef __FUNCT__ 9069 #define __FUNCT__ "DMPlexMatSetClosure" 9070 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 9071 { 9072 DM_Plex *mesh = (DM_Plex*) dm->data; 9073 PetscInt *points = PETSC_NULL; 9074 PetscInt *indices; 9075 PetscInt offsets[32]; 9076 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 9077 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 9078 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 9079 PetscErrorCode ierr; 9080 9081 PetscFunctionBegin; 9082 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9083 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 9084 if (useDefault) { 9085 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9086 } 9087 if (useGlobalDefault) { 9088 if (useDefault) { 9089 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 9090 } else { 9091 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9092 } 9093 } 9094 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9095 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 9096 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 9097 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9098 /* Compress out points not in the section */ 9099 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 9100 for (p = 0, q = 0; p < numPoints*2; p += 2) { 9101 if ((points[p] >= pStart) && (points[p] < pEnd)) { 9102 points[q*2] = points[p]; 9103 points[q*2+1] = points[p+1]; 9104 ++q; 9105 } 9106 } 9107 numPoints = q; 9108 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 9109 PetscInt fdof; 9110 9111 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 9112 for (f = 0; f < numFields; ++f) { 9113 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 9114 offsets[f+1] += fdof; 9115 } 9116 numIndices += dof; 9117 } 9118 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 9119 9120 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 9121 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9122 if (numFields) { 9123 for (p = 0; p < numPoints*2; p += 2) { 9124 PetscInt o = points[p+1]; 9125 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9126 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 9127 } 9128 } else { 9129 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 9130 PetscInt o = points[p+1]; 9131 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9132 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 9133 } 9134 } 9135 if (useGlobalDefault && !useDefault) { 9136 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9137 } 9138 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 9139 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 9140 if (ierr) { 9141 PetscMPIInt rank; 9142 PetscErrorCode ierr2; 9143 9144 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 9145 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 9146 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 9147 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 9148 CHKERRQ(ierr); 9149 } 9150 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9151 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9152 PetscFunctionReturn(0); 9153 } 9154 9155 #undef __FUNCT__ 9156 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 9157 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9158 { 9159 PetscSection coordSection; 9160 Vec coordinates; 9161 const PetscScalar *coords; 9162 const PetscInt dim = 2; 9163 PetscInt d, f; 9164 PetscErrorCode ierr; 9165 9166 PetscFunctionBegin; 9167 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9168 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9169 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9170 if (v0) { 9171 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9172 } 9173 if (J) { 9174 for (d = 0; d < dim; d++) { 9175 for (f = 0; f < dim; f++) { 9176 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9177 } 9178 } 9179 *detJ = J[0]*J[3] - J[1]*J[2]; 9180 #if 0 9181 if (detJ < 0.0) { 9182 const PetscReal xLength = mesh->periodicity[0]; 9183 9184 if (xLength != 0.0) { 9185 PetscReal v0x = coords[0*dim+0]; 9186 9187 if (v0x == 0.0) v0x = v0[0] = xLength; 9188 for (f = 0; f < dim; f++) { 9189 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 9190 9191 J[0*dim+f] = 0.5*(px - v0x); 9192 } 9193 } 9194 detJ = J[0]*J[3] - J[1]*J[2]; 9195 } 9196 #endif 9197 PetscLogFlops(8.0 + 3.0); 9198 } 9199 if (invJ) { 9200 const PetscReal invDet = 1.0/(*detJ); 9201 9202 invJ[0] = invDet*J[3]; 9203 invJ[1] = -invDet*J[1]; 9204 invJ[2] = -invDet*J[2]; 9205 invJ[3] = invDet*J[0]; 9206 PetscLogFlops(5.0); 9207 } 9208 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9209 PetscFunctionReturn(0); 9210 } 9211 9212 #undef __FUNCT__ 9213 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9214 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9215 { 9216 PetscSection coordSection; 9217 Vec coordinates; 9218 const PetscScalar *coords; 9219 const PetscInt dim = 2; 9220 PetscInt d, f; 9221 PetscErrorCode ierr; 9222 9223 PetscFunctionBegin; 9224 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9225 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9226 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9227 if (v0) { 9228 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9229 } 9230 if (J) { 9231 for (d = 0; d < dim; d++) { 9232 for (f = 0; f < dim; f++) { 9233 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9234 } 9235 } 9236 *detJ = J[0]*J[3] - J[1]*J[2]; 9237 PetscLogFlops(8.0 + 3.0); 9238 } 9239 if (invJ) { 9240 const PetscReal invDet = 1.0/(*detJ); 9241 9242 invJ[0] = invDet*J[3]; 9243 invJ[1] = -invDet*J[1]; 9244 invJ[2] = -invDet*J[2]; 9245 invJ[3] = invDet*J[0]; 9246 PetscLogFlops(5.0); 9247 } 9248 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9249 PetscFunctionReturn(0); 9250 } 9251 9252 #undef __FUNCT__ 9253 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9254 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9255 { 9256 PetscSection coordSection; 9257 Vec coordinates; 9258 const PetscScalar *coords; 9259 const PetscInt dim = 3; 9260 PetscInt d, f; 9261 PetscErrorCode ierr; 9262 9263 PetscFunctionBegin; 9264 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9265 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9266 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9267 if (v0) { 9268 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9269 } 9270 if (J) { 9271 for (d = 0; d < dim; d++) { 9272 for (f = 0; f < dim; f++) { 9273 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9274 } 9275 } 9276 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9277 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9278 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9279 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9280 PetscLogFlops(18.0 + 12.0); 9281 } 9282 if (invJ) { 9283 const PetscReal invDet = 1.0/(*detJ); 9284 9285 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9286 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9287 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9288 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9289 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9290 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9291 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9292 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9293 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9294 PetscLogFlops(37.0); 9295 } 9296 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9297 PetscFunctionReturn(0); 9298 } 9299 9300 #undef __FUNCT__ 9301 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9302 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9303 { 9304 PetscSection coordSection; 9305 Vec coordinates; 9306 const PetscScalar *coords; 9307 const PetscInt dim = 3; 9308 PetscInt d; 9309 PetscErrorCode ierr; 9310 9311 PetscFunctionBegin; 9312 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9313 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9314 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9315 if (v0) { 9316 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9317 } 9318 if (J) { 9319 for (d = 0; d < dim; d++) { 9320 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9321 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9322 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9323 } 9324 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9325 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9326 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9327 PetscLogFlops(18.0 + 12.0); 9328 } 9329 if (invJ) { 9330 const PetscReal invDet = -1.0/(*detJ); 9331 9332 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9333 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9334 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9335 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9336 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9337 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9338 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9339 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9340 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9341 PetscLogFlops(37.0); 9342 } 9343 *detJ *= 8.0; 9344 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9345 PetscFunctionReturn(0); 9346 } 9347 9348 #undef __FUNCT__ 9349 #define __FUNCT__ "DMPlexComputeCellGeometry" 9350 /*@C 9351 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9352 9353 Collective on DM 9354 9355 Input Arguments: 9356 + dm - the DM 9357 - cell - the cell 9358 9359 Output Arguments: 9360 + v0 - the translation part of this affine transform 9361 . J - the Jacobian of the transform to the reference element 9362 . invJ - the inverse of the Jacobian 9363 - detJ - the Jacobian determinant 9364 9365 Level: advanced 9366 9367 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9368 @*/ 9369 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9370 { 9371 PetscInt dim, coneSize; 9372 PetscErrorCode ierr; 9373 9374 PetscFunctionBegin; 9375 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9376 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9377 switch (dim) { 9378 case 2: 9379 switch (coneSize) { 9380 case 3: 9381 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9382 break; 9383 case 4: 9384 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9385 break; 9386 default: 9387 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9388 } 9389 break; 9390 case 3: 9391 switch (coneSize) { 9392 case 4: 9393 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9394 break; 9395 case 8: 9396 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9397 break; 9398 default: 9399 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9400 } 9401 break; 9402 default: 9403 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9404 } 9405 PetscFunctionReturn(0); 9406 } 9407 9408 #undef __FUNCT__ 9409 #define __FUNCT__ "DMPlexGetFaceOrientation" 9410 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9411 { 9412 MPI_Comm comm = ((PetscObject) dm)->comm; 9413 PetscBool posOrient = PETSC_FALSE; 9414 const PetscInt debug = 0; 9415 PetscInt cellDim, faceSize, f; 9416 PetscErrorCode ierr; 9417 9418 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9419 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9420 9421 if (cellDim == numCorners-1) { 9422 /* Simplices */ 9423 faceSize = numCorners-1; 9424 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9425 } else if (cellDim == 1 && numCorners == 3) { 9426 /* Quadratic line */ 9427 faceSize = 1; 9428 posOrient = PETSC_TRUE; 9429 } else if (cellDim == 2 && numCorners == 4) { 9430 /* Quads */ 9431 faceSize = 2; 9432 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9433 posOrient = PETSC_TRUE; 9434 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9435 posOrient = PETSC_TRUE; 9436 } else { 9437 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9438 posOrient = PETSC_FALSE; 9439 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9440 } 9441 } else if (cellDim == 2 && numCorners == 6) { 9442 /* Quadratic triangle (I hate this) */ 9443 /* Edges are determined by the first 2 vertices (corners of edges) */ 9444 const PetscInt faceSizeTri = 3; 9445 PetscInt sortedIndices[3], i, iFace; 9446 PetscBool found = PETSC_FALSE; 9447 PetscInt faceVerticesTriSorted[9] = { 9448 0, 3, 4, /* bottom */ 9449 1, 4, 5, /* right */ 9450 2, 3, 5, /* left */ 9451 }; 9452 PetscInt faceVerticesTri[9] = { 9453 0, 3, 4, /* bottom */ 9454 1, 4, 5, /* right */ 9455 2, 5, 3, /* left */ 9456 }; 9457 9458 faceSize = faceSizeTri; 9459 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9460 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9461 for (iFace = 0; iFace < 3; ++iFace) { 9462 const PetscInt ii = iFace*faceSizeTri; 9463 PetscInt fVertex, cVertex; 9464 9465 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9466 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9467 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9468 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9469 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9470 faceVertices[fVertex] = origVertices[cVertex]; 9471 break; 9472 } 9473 } 9474 } 9475 found = PETSC_TRUE; 9476 break; 9477 } 9478 } 9479 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9480 if (posOriented) *posOriented = PETSC_TRUE; 9481 PetscFunctionReturn(0); 9482 } else if (cellDim == 2 && numCorners == 9) { 9483 /* Quadratic quad (I hate this) */ 9484 /* Edges are determined by the first 2 vertices (corners of edges) */ 9485 const PetscInt faceSizeQuad = 3; 9486 PetscInt sortedIndices[3], i, iFace; 9487 PetscBool found = PETSC_FALSE; 9488 PetscInt faceVerticesQuadSorted[12] = { 9489 0, 1, 4, /* bottom */ 9490 1, 2, 5, /* right */ 9491 2, 3, 6, /* top */ 9492 0, 3, 7, /* left */ 9493 }; 9494 PetscInt faceVerticesQuad[12] = { 9495 0, 1, 4, /* bottom */ 9496 1, 2, 5, /* right */ 9497 2, 3, 6, /* top */ 9498 3, 0, 7, /* left */ 9499 }; 9500 9501 faceSize = faceSizeQuad; 9502 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9503 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9504 for (iFace = 0; iFace < 4; ++iFace) { 9505 const PetscInt ii = iFace*faceSizeQuad; 9506 PetscInt fVertex, cVertex; 9507 9508 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9509 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9510 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9511 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9512 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9513 faceVertices[fVertex] = origVertices[cVertex]; 9514 break; 9515 } 9516 } 9517 } 9518 found = PETSC_TRUE; 9519 break; 9520 } 9521 } 9522 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9523 if (posOriented) *posOriented = PETSC_TRUE; 9524 PetscFunctionReturn(0); 9525 } else if (cellDim == 3 && numCorners == 8) { 9526 /* Hexes 9527 A hex is two oriented quads with the normal of the first 9528 pointing up at the second. 9529 9530 7---6 9531 /| /| 9532 4---5 | 9533 | 3-|-2 9534 |/ |/ 9535 0---1 9536 9537 Faces are determined by the first 4 vertices (corners of faces) */ 9538 const PetscInt faceSizeHex = 4; 9539 PetscInt sortedIndices[4], i, iFace; 9540 PetscBool found = PETSC_FALSE; 9541 PetscInt faceVerticesHexSorted[24] = { 9542 0, 1, 2, 3, /* bottom */ 9543 4, 5, 6, 7, /* top */ 9544 0, 1, 4, 5, /* front */ 9545 1, 2, 5, 6, /* right */ 9546 2, 3, 6, 7, /* back */ 9547 0, 3, 4, 7, /* left */ 9548 }; 9549 PetscInt faceVerticesHex[24] = { 9550 3, 2, 1, 0, /* bottom */ 9551 4, 5, 6, 7, /* top */ 9552 0, 1, 5, 4, /* front */ 9553 1, 2, 6, 5, /* right */ 9554 2, 3, 7, 6, /* back */ 9555 3, 0, 4, 7, /* left */ 9556 }; 9557 9558 faceSize = faceSizeHex; 9559 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9560 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9561 for (iFace = 0; iFace < 6; ++iFace) { 9562 const PetscInt ii = iFace*faceSizeHex; 9563 PetscInt fVertex, cVertex; 9564 9565 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9566 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9567 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9568 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9569 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9570 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9571 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9572 faceVertices[fVertex] = origVertices[cVertex]; 9573 break; 9574 } 9575 } 9576 } 9577 found = PETSC_TRUE; 9578 break; 9579 } 9580 } 9581 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9582 if (posOriented) *posOriented = PETSC_TRUE; 9583 PetscFunctionReturn(0); 9584 } else if (cellDim == 3 && numCorners == 10) { 9585 /* Quadratic tet */ 9586 /* Faces are determined by the first 3 vertices (corners of faces) */ 9587 const PetscInt faceSizeTet = 6; 9588 PetscInt sortedIndices[6], i, iFace; 9589 PetscBool found = PETSC_FALSE; 9590 PetscInt faceVerticesTetSorted[24] = { 9591 0, 1, 2, 6, 7, 8, /* bottom */ 9592 0, 3, 4, 6, 7, 9, /* front */ 9593 1, 4, 5, 7, 8, 9, /* right */ 9594 2, 3, 5, 6, 8, 9, /* left */ 9595 }; 9596 PetscInt faceVerticesTet[24] = { 9597 0, 1, 2, 6, 7, 8, /* bottom */ 9598 0, 4, 3, 6, 7, 9, /* front */ 9599 1, 5, 4, 7, 8, 9, /* right */ 9600 2, 3, 5, 8, 6, 9, /* left */ 9601 }; 9602 9603 faceSize = faceSizeTet; 9604 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9605 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9606 for (iFace=0; iFace < 4; ++iFace) { 9607 const PetscInt ii = iFace*faceSizeTet; 9608 PetscInt fVertex, cVertex; 9609 9610 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9611 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9612 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9613 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9614 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9615 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9616 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9617 faceVertices[fVertex] = origVertices[cVertex]; 9618 break; 9619 } 9620 } 9621 } 9622 found = PETSC_TRUE; 9623 break; 9624 } 9625 } 9626 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9627 if (posOriented) *posOriented = PETSC_TRUE; 9628 PetscFunctionReturn(0); 9629 } else if (cellDim == 3 && numCorners == 27) { 9630 /* Quadratic hexes (I hate this) 9631 A hex is two oriented quads with the normal of the first 9632 pointing up at the second. 9633 9634 7---6 9635 /| /| 9636 4---5 | 9637 | 3-|-2 9638 |/ |/ 9639 0---1 9640 9641 Faces are determined by the first 4 vertices (corners of faces) */ 9642 const PetscInt faceSizeQuadHex = 9; 9643 PetscInt sortedIndices[9], i, iFace; 9644 PetscBool found = PETSC_FALSE; 9645 PetscInt faceVerticesQuadHexSorted[54] = { 9646 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9647 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9648 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9649 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9650 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9651 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9652 }; 9653 PetscInt faceVerticesQuadHex[54] = { 9654 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9655 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9656 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9657 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9658 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9659 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9660 }; 9661 9662 faceSize = faceSizeQuadHex; 9663 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9664 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9665 for (iFace = 0; iFace < 6; ++iFace) { 9666 const PetscInt ii = iFace*faceSizeQuadHex; 9667 PetscInt fVertex, cVertex; 9668 9669 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9670 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9671 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9672 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9673 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9674 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9675 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9676 faceVertices[fVertex] = origVertices[cVertex]; 9677 break; 9678 } 9679 } 9680 } 9681 found = PETSC_TRUE; 9682 break; 9683 } 9684 } 9685 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9686 if (posOriented) *posOriented = PETSC_TRUE; 9687 PetscFunctionReturn(0); 9688 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9689 if (!posOrient) { 9690 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9691 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize-1 - f]; 9692 } else { 9693 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9694 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f]; 9695 } 9696 if (posOriented) *posOriented = posOrient; 9697 PetscFunctionReturn(0); 9698 } 9699 9700 #undef __FUNCT__ 9701 #define __FUNCT__ "DMPlexGetOrientedFace" 9702 /* 9703 Given a cell and a face, as a set of vertices, 9704 return the oriented face, as a set of vertices, in faceVertices 9705 The orientation is such that the face normal points out of the cell 9706 */ 9707 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9708 { 9709 const PetscInt *cone = PETSC_NULL; 9710 PetscInt coneSize, v, f, v2; 9711 PetscInt oppositeVertex = -1; 9712 PetscErrorCode ierr; 9713 9714 PetscFunctionBegin; 9715 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9716 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9717 for (v = 0, v2 = 0; v < coneSize; ++v) { 9718 PetscBool found = PETSC_FALSE; 9719 9720 for (f = 0; f < faceSize; ++f) { 9721 if (face[f] == cone[v]) { 9722 found = PETSC_TRUE; break; 9723 } 9724 } 9725 if (found) { 9726 indices[v2] = v; 9727 origVertices[v2] = cone[v]; 9728 ++v2; 9729 } else { 9730 oppositeVertex = v; 9731 } 9732 } 9733 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9734 PetscFunctionReturn(0); 9735 } 9736 9737 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9738 { 9739 switch (i) { 9740 case 0: 9741 switch (j) { 9742 case 0: return 0; 9743 case 1: 9744 switch (k) { 9745 case 0: return 0; 9746 case 1: return 0; 9747 case 2: return 1; 9748 } 9749 case 2: 9750 switch (k) { 9751 case 0: return 0; 9752 case 1: return -1; 9753 case 2: return 0; 9754 } 9755 } 9756 case 1: 9757 switch (j) { 9758 case 0: 9759 switch (k) { 9760 case 0: return 0; 9761 case 1: return 0; 9762 case 2: return -1; 9763 } 9764 case 1: return 0; 9765 case 2: 9766 switch (k) { 9767 case 0: return 1; 9768 case 1: return 0; 9769 case 2: return 0; 9770 } 9771 } 9772 case 2: 9773 switch (j) { 9774 case 0: 9775 switch (k) { 9776 case 0: return 0; 9777 case 1: return 1; 9778 case 2: return 0; 9779 } 9780 case 1: 9781 switch (k) { 9782 case 0: return -1; 9783 case 1: return 0; 9784 case 2: return 0; 9785 } 9786 case 2: return 0; 9787 } 9788 } 9789 return 0; 9790 } 9791 9792 #undef __FUNCT__ 9793 #define __FUNCT__ "DMPlexCreateRigidBody" 9794 /*@C 9795 DMPlexCreateRigidBody - create rigid body modes from coordinates 9796 9797 Collective on DM 9798 9799 Input Arguments: 9800 + dm - the DM 9801 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9802 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9803 9804 Output Argument: 9805 . sp - the null space 9806 9807 Note: This is necessary to take account of Dirichlet conditions on the displacements 9808 9809 Level: advanced 9810 9811 .seealso: MatNullSpaceCreate() 9812 @*/ 9813 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9814 { 9815 MPI_Comm comm = ((PetscObject) dm)->comm; 9816 Vec coordinates, localMode, mode[6]; 9817 PetscSection coordSection; 9818 PetscScalar *coords; 9819 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9820 PetscErrorCode ierr; 9821 9822 PetscFunctionBegin; 9823 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9824 if (dim == 1) { 9825 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9826 PetscFunctionReturn(0); 9827 } 9828 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9829 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9830 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9831 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9832 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9833 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9834 m = (dim*(dim+1))/2; 9835 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9836 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9837 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9838 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9839 /* Assume P1 */ 9840 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9841 for (d = 0; d < dim; ++d) { 9842 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9843 9844 values[d] = 1.0; 9845 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9846 for (v = vStart; v < vEnd; ++v) { 9847 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9848 } 9849 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9850 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9851 } 9852 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9853 for (d = dim; d < dim*(dim+1)/2; ++d) { 9854 PetscInt i, j, k = dim > 2 ? d - dim : d; 9855 9856 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9857 for (v = vStart; v < vEnd; ++v) { 9858 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9859 PetscInt off; 9860 9861 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9862 for (i = 0; i < dim; ++i) { 9863 for (j = 0; j < dim; ++j) { 9864 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9865 } 9866 } 9867 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9868 } 9869 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9870 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9871 } 9872 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9873 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9874 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9875 /* Orthonormalize system */ 9876 for (i = dim; i < m; ++i) { 9877 PetscScalar dots[6]; 9878 9879 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9880 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9881 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9882 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9883 } 9884 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9885 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9886 PetscFunctionReturn(0); 9887 } 9888 9889 #undef __FUNCT__ 9890 #define __FUNCT__ "DMPlexGetHybridBounds" 9891 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9892 { 9893 DM_Plex *mesh = (DM_Plex*) dm->data; 9894 PetscInt dim; 9895 PetscErrorCode ierr; 9896 9897 PetscFunctionBegin; 9898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9899 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9900 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9901 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9902 if (eMax) *eMax = mesh->hybridPointMax[1]; 9903 if (vMax) *vMax = mesh->hybridPointMax[0]; 9904 PetscFunctionReturn(0); 9905 } 9906 9907 #undef __FUNCT__ 9908 #define __FUNCT__ "DMPlexSetHybridBounds" 9909 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9910 { 9911 DM_Plex *mesh = (DM_Plex*) dm->data; 9912 PetscInt dim; 9913 PetscErrorCode ierr; 9914 9915 PetscFunctionBegin; 9916 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9917 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9918 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9919 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9920 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9921 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9922 PetscFunctionReturn(0); 9923 } 9924 9925 #undef __FUNCT__ 9926 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9927 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9928 { 9929 DM_Plex *mesh = (DM_Plex*) dm->data; 9930 9931 PetscFunctionBegin; 9932 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9933 PetscValidPointer(cellHeight, 2); 9934 *cellHeight = mesh->vtkCellHeight; 9935 PetscFunctionReturn(0); 9936 } 9937 9938 #undef __FUNCT__ 9939 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9940 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9941 { 9942 DM_Plex *mesh = (DM_Plex*) dm->data; 9943 9944 PetscFunctionBegin; 9945 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9946 mesh->vtkCellHeight = cellHeight; 9947 PetscFunctionReturn(0); 9948 } 9949 9950 #undef __FUNCT__ 9951 #define __FUNCT__ "DMPlexInsertFace_Private" 9952 /* 9953 DMPlexInsertFace_Private - Puts a face into the mesh 9954 9955 Not collective 9956 9957 Input Parameters: 9958 + dm - The DMPlex 9959 . numFaceVertex - The number of vertices in the face 9960 . faceVertices - The vertices in the face for dm 9961 . subfaceVertices - The vertices in the face for subdm 9962 . numCorners - The number of vertices in the cell 9963 . cell - A cell in dm containing the face 9964 . subcell - A cell in subdm containing the face 9965 . firstFace - First face in the mesh 9966 - newFacePoint - Next face in the mesh 9967 9968 Output Parameters: 9969 . newFacePoint - Contains next face point number on input, updated on output 9970 9971 Level: developer 9972 */ 9973 PetscErrorCode DMPlexInsertFace_Private(DM dm, DM subdm, PetscInt numFaceVertices, const PetscInt faceVertices[], const PetscInt subfaceVertices[], PetscInt numCorners, PetscInt cell, PetscInt subcell, PetscInt firstFace, PetscInt *newFacePoint) 9974 { 9975 MPI_Comm comm = ((PetscObject) dm)->comm; 9976 DM_Plex *submesh = (DM_Plex*) subdm->data; 9977 const PetscInt *faces; 9978 PetscInt numFaces, coneSize; 9979 PetscErrorCode ierr; 9980 9981 PetscFunctionBegin; 9982 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9983 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9984 #if 0 9985 /* Cannot use this because support() has not been constructed yet */ 9986 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9987 #else 9988 { 9989 PetscInt f; 9990 9991 numFaces = 0; 9992 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void**) &faces);CHKERRQ(ierr); 9993 for (f = firstFace; f < *newFacePoint; ++f) { 9994 PetscInt dof, off, d; 9995 9996 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9997 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9998 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9999 for (d = 0; d < dof; ++d) { 10000 const PetscInt p = submesh->cones[off+d]; 10001 PetscInt v; 10002 10003 for (v = 0; v < numFaceVertices; ++v) { 10004 if (subfaceVertices[v] == p) break; 10005 } 10006 if (v == numFaceVertices) break; 10007 } 10008 if (d == dof) { 10009 numFaces = 1; 10010 ((PetscInt*) faces)[0] = f; 10011 } 10012 } 10013 } 10014 #endif 10015 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 10016 else if (numFaces == 1) { 10017 /* Add the other cell neighbor for this face */ 10018 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 10019 } else { 10020 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 10021 PetscBool posOriented; 10022 10023 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10024 origVertices = &orientedVertices[numFaceVertices]; 10025 indices = &orientedVertices[numFaceVertices*2]; 10026 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 10027 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 10028 /* TODO: I know that routine should return a permutation, not the indices */ 10029 for (v = 0; v < numFaceVertices; ++v) { 10030 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 10031 for (ov = 0; ov < numFaceVertices; ++ov) { 10032 if (orientedVertices[ov] == vertex) { 10033 orientedSubVertices[ov] = subvertex; 10034 break; 10035 } 10036 } 10037 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 10038 } 10039 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 10040 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 10041 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10042 ++(*newFacePoint); 10043 } 10044 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 10045 PetscFunctionReturn(0); 10046 } 10047 10048 #undef __FUNCT__ 10049 #define __FUNCT__ "DMPlexCreateSubmesh_Uninterpolated" 10050 static PetscErrorCode DMPlexCreateSubmesh_Uninterpolated(DM dm, const char label[], const char surfaceLabel[], DM subdm) 10051 { 10052 MPI_Comm comm = ((PetscObject) dm)->comm; 10053 PetscBool boundaryFaces = PETSC_FALSE; 10054 PetscSection coordSection, subCoordSection; 10055 Vec coordinates, subCoordinates; 10056 PetscScalar *coords, *subCoords; 10057 IS labelIS, subpointMap; 10058 const PetscInt *subVertices; 10059 PetscInt *subVerticesActive, *tmpPoints; 10060 PetscInt *subCells = PETSC_NULL; 10061 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 10062 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 10063 PetscInt dim; /* Right now, do not specify dimension */ 10064 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 10065 PetscErrorCode ierr; 10066 10067 PetscFunctionBegin; 10068 if (surfaceLabel) SETERRQ(comm, PETSC_ERR_SUP, "Yell at me to do this"); 10069 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10070 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10071 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10072 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 10073 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10074 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 10075 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 10076 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10077 subface = &face[maxConeSize]; 10078 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 10079 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 10080 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 10081 maxSubCells = numSubVertices; 10082 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 10083 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 10084 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 10085 for (v = 0; v < numSubVertices; ++v) { 10086 const PetscInt vertex = subVertices[v]; 10087 PetscInt *star = PETSC_NULL; 10088 PetscInt starSize, numCells = 0; 10089 10090 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10091 for (p = 0; p < starSize*2; p += 2) { 10092 const PetscInt point = star[p]; 10093 if ((point >= cStart) && (point < cEnd)) star[numCells++] = point; 10094 } 10095 numOldSubCells = numSubCells; 10096 for (c = 0; c < numCells; ++c) { 10097 const PetscInt cell = star[c]; 10098 PetscInt *closure = PETSC_NULL; 10099 PetscInt closureSize, numCorners = 0, faceSize = 0; 10100 PetscInt cellLoc; 10101 10102 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 10103 if (cellLoc >= 0) continue; 10104 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10105 for (p = 0; p < closureSize*2; p += 2) { 10106 const PetscInt point = closure[p]; 10107 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 10108 } 10109 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 10110 for (corner = 0; corner < numCorners; ++corner) { 10111 const PetscInt cellVertex = closure[corner]; 10112 PetscInt subVertex; 10113 10114 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 10115 if (subVertex >= 0) { /* contains submesh vertex */ 10116 for (i = 0; i < faceSize; ++i) { 10117 if (cellVertex == face[i]) break; 10118 } 10119 if (i == faceSize) { 10120 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 10121 face[faceSize] = cellVertex; 10122 subface[faceSize] = subVertex; 10123 ++faceSize; 10124 } 10125 } 10126 } 10127 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10128 if (faceSize >= nFV) { 10129 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10130 if (numSubCells >= maxSubCells) { 10131 PetscInt *tmpCells; 10132 maxSubCells *= 2; 10133 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 10134 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 10135 ierr = PetscFree(subCells);CHKERRQ(ierr); 10136 10137 subCells = tmpCells; 10138 } 10139 /* TOOD: Maybe overestimate then squeeze out empty faces */ 10140 if (faceSize > nFV) { 10141 /* TODO: This is tricky. Maybe just add all faces */ 10142 numSubFaces++; 10143 } else { 10144 numSubFaces++; 10145 } 10146 for (f = 0; f < faceSize; ++f) subVerticesActive[subface[f]] = 1; 10147 subCells[numSubCells++] = cell; 10148 } 10149 } 10150 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10151 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 10152 } 10153 /* Pick out active subvertices */ 10154 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 10155 if (subVerticesActive[v]) { 10156 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 10157 } 10158 } 10159 ierr = DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 10160 /* Set cone sizes */ 10161 firstSubVertex = numSubCells; 10162 firstSubFace = numSubCells+numSubVerticesActive; 10163 newFacePoint = firstSubFace; 10164 for (c = 0; c < numSubCells; ++c) { 10165 ierr = DMPlexSetConeSize(subdm, c, 1);CHKERRQ(ierr); 10166 } 10167 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 10168 ierr = DMPlexSetConeSize(subdm, f, nFV);CHKERRQ(ierr); 10169 } 10170 ierr = DMSetUp(subdm);CHKERRQ(ierr); 10171 /* Create face cones */ 10172 for (c = 0; c < numSubCells; ++c) { 10173 const PetscInt cell = subCells[c]; 10174 PetscInt *closure = PETSC_NULL; 10175 PetscInt closureSize, numCorners = 0, faceSize = 0; 10176 10177 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10178 for (p = 0; p < closureSize*2; p += 2) { 10179 const PetscInt point = closure[p]; 10180 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 10181 } 10182 for (corner = 0; corner < numCorners; ++corner) { 10183 const PetscInt cellVertex = closure[corner]; 10184 PetscInt subVertex; 10185 10186 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 10187 if (subVertex >= 0) { /* contains submesh vertex */ 10188 for (i = 0; i < faceSize; ++i) { 10189 if (cellVertex == face[i]) break; 10190 } 10191 if (i == faceSize) { 10192 face[faceSize] = cellVertex; 10193 subface[faceSize] = numSubCells+subVertex; 10194 ++faceSize; 10195 } 10196 } 10197 } 10198 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10199 if (faceSize >= nFV) { 10200 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10201 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 10202 /* We have to take all the faces, and discard those in the interior */ 10203 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 10204 #if 0 10205 /* This object just calls insert on each face that comes from subsets() */ 10206 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 10207 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 10208 PointArray faceVec(face->begin(), face->end()); 10209 10210 subsets(faceVec, nFV, inserter); 10211 #endif 10212 ierr = DMPlexInsertFace_Private(dm, subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 10213 } 10214 } 10215 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 10216 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 10217 /* Build coordinates */ 10218 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10219 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10220 ierr = DMPlexGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 10221 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 10222 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 10223 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 10224 } 10225 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10226 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10227 ierr = VecCreate(comm, &subCoordinates);CHKERRQ(ierr); 10228 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10229 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10231 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10232 for (v = 0; v < numSubVerticesActive; ++v) { 10233 const PetscInt vertex = subVerticesActive[v]; 10234 const PetscInt subVertex = firstSubVertex+v; 10235 PetscInt dof, off, sdof, soff; 10236 10237 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10238 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10239 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10240 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10241 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10242 for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d]; 10243 } 10244 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10245 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10246 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 10247 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10248 10249 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 10250 /* Create map from submesh points to original mesh points */ 10251 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 10252 for (c = 0; c < numSubCells; ++c) tmpPoints[c] = subCells[c]; 10253 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) tmpPoints[v] = subVerticesActive[v-numSubCells]; 10254 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &subpointMap);CHKERRQ(ierr); 10255 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 10256 ierr = ISDestroy(&subpointMap);CHKERRQ(ierr); 10257 10258 ierr = PetscFree(subCells);CHKERRQ(ierr); 10259 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10260 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10261 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10262 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10263 PetscFunctionReturn(0); 10264 } 10265 10266 #undef __FUNCT__ 10267 #define __FUNCT__ "DMPlexCreateSubmesh_Interpolated" 10268 static PetscErrorCode DMPlexCreateSubmesh_Interpolated(DM dm, const char vertexLabel[], const char surfaceLabel[], DM subdm) 10269 { 10270 MPI_Comm comm = ((PetscObject) dm)->comm; 10271 const char *name = surfaceLabel ? surfaceLabel : "submesh_label"; 10272 DMLabel slabel; 10273 IS subvertexIS, subedgeIS, subfaceIS, subcellIS, subpointMap; 10274 const PetscInt *subVertices, *subEdges, *subFaces, *subCells; 10275 PetscInt *coneNew; 10276 PetscInt dim, numSubVerticesInitial, numSubVertices, firstSubVertex, v, numSubEdges = 0, firstSubEdge, e, numSubFaces = 0, firstSubFace, f, numSubCells; 10277 PetscInt vStart, vEnd, fStart, fEnd; 10278 PetscErrorCode ierr; 10279 10280 PetscFunctionBegin; 10281 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10282 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10283 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 10284 ierr = DMPlexCreateLabel(subdm, name);CHKERRQ(ierr); 10285 ierr = DMPlexGetLabel(subdm, name, &slabel);CHKERRQ(ierr); 10286 ierr = DMPlexGetStratumIS(dm, vertexLabel, 1, &subvertexIS);CHKERRQ(ierr); 10287 ierr = ISGetSize(subvertexIS, &numSubVerticesInitial);CHKERRQ(ierr); 10288 ierr = ISGetIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10289 for (v = 0; v < numSubVerticesInitial; ++v) { 10290 const PetscInt vertex = subVertices[v]; 10291 PetscInt *star = PETSC_NULL; 10292 PetscInt starSize, s, numFaces = 0, f; 10293 10294 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10295 for (s = 0; s < starSize*2; s += 2) { 10296 const PetscInt point = star[s]; 10297 if ((point >= fStart) && (point < fEnd)) { 10298 star[numFaces++] = point; 10299 } 10300 } 10301 for (f = 0; f < numFaces; ++f) { 10302 const PetscInt face = star[f]; 10303 PetscInt *closure = PETSC_NULL; 10304 PetscInt closureSize, c, numCorners = 0; 10305 PetscInt faceLoc, corner; 10306 10307 ierr = DMLabelGetValue(slabel, face, &faceLoc);CHKERRQ(ierr); 10308 if (faceLoc == dim-1) continue; 10309 if (faceLoc >= 0) SETERRQ2(comm, PETSC_ERR_PLIB, "Face %d has dimension %d in the surface label", face, faceLoc); 10310 ierr = DMPlexGetTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10311 for (c = 0; c < closureSize*2; c += 2) { 10312 const PetscInt point = closure[c]; 10313 if ((point >= vStart) && (point < vEnd)) { 10314 closure[numCorners++] = point; 10315 } 10316 } 10317 for (corner = 0; corner < numCorners; ++corner) { 10318 const PetscInt cellVertex = closure[corner]; 10319 PetscInt vertexLoc; 10320 10321 ierr = DMLabelGetValue(slabel, cellVertex, &vertexLoc);CHKERRQ(ierr); 10322 if (vertexLoc < 0) break; 10323 } 10324 ierr = DMPlexRestoreTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10325 if (corner == numCorners) { 10326 const PetscInt *support; 10327 PetscInt supportSize; 10328 10329 for (corner = 0; corner < numCorners; ++corner) {ierr = DMLabelSetValue(slabel, closure[corner], 0);CHKERRQ(ierr);} 10330 ierr = DMLabelSetValue(slabel, face, dim-1);CHKERRQ(ierr); 10331 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10332 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10333 for(s = 0; s < supportSize; ++s) { 10334 ierr = DMLabelSetValue(slabel, support[s], dim);CHKERRQ(ierr); 10335 } 10336 if (dim > 2) { 10337 const PetscInt *cone; 10338 PetscInt coneSize; 10339 10340 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10341 ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 10342 for(c = 0; c < coneSize; ++c) { 10343 ierr = DMLabelSetValue(slabel, cone[c], dim-2);CHKERRQ(ierr); 10344 } 10345 } 10346 } 10347 } 10348 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10349 } 10350 ierr = ISRestoreIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10351 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 10352 ierr = DMLabelGetStratumSize(slabel, dim, &numSubCells);CHKERRQ(ierr); 10353 ierr = DMLabelGetStratumSize(slabel, 0, &numSubVertices);CHKERRQ(ierr); 10354 if (dim > 1) {ierr = DMLabelGetStratumSize(slabel, dim-1, &numSubFaces);CHKERRQ(ierr);} 10355 if (dim > 2) {ierr = DMLabelGetStratumSize(slabel, 1, &numSubEdges);CHKERRQ(ierr);} 10356 ierr = DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubEdges+numSubVertices);CHKERRQ(ierr); 10357 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 10358 /* Set cone sizes */ 10359 firstSubVertex = numSubCells; 10360 firstSubFace = firstSubVertex + numSubVertices; 10361 firstSubEdge = firstSubFace + numSubFaces; 10362 ierr = DMLabelGetStratumIS(slabel, dim, &subcellIS);CHKERRQ(ierr); 10363 ierr = ISGetIndices(subcellIS, &subCells);CHKERRQ(ierr); 10364 ierr = DMLabelGetStratumIS(slabel, 0, &subvertexIS);CHKERRQ(ierr); 10365 ierr = ISGetIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10366 if (dim > 1) { 10367 ierr = DMLabelGetStratumIS(slabel, dim-1, &subfaceIS);CHKERRQ(ierr); 10368 ierr = ISGetIndices(subfaceIS, &subFaces);CHKERRQ(ierr); 10369 } 10370 if (dim > 2) { 10371 ierr = DMLabelGetStratumIS(slabel, 1, &subedgeIS);CHKERRQ(ierr); 10372 ierr = ISGetIndices(subedgeIS, &subEdges);CHKERRQ(ierr); 10373 } 10374 for (e = firstSubEdge; e < firstSubEdge+numSubEdges; ++e) { 10375 ierr = DMPlexSetConeSize(subdm, e, 2);CHKERRQ(ierr); 10376 } 10377 for (f = 0; f < numSubFaces; ++f) { 10378 const PetscInt face = subFaces[f]; 10379 const PetscInt subface = firstSubFace + f; 10380 const PetscInt *support; 10381 PetscInt coneSize, supportSize, subcell, s; 10382 10383 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10384 ierr = DMPlexSetConeSize(subdm, subface, coneSize);CHKERRQ(ierr); 10385 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10386 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10387 for(s = 0; s < supportSize; ++s) { 10388 ierr = PetscFindInt(support[s], numSubCells, subCells, &subcell);CHKERRQ(ierr); 10389 if (subcell < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Subcell %d not found in surface label", support[s]); 10390 /* ierr = DMPlexAddConeSize(subdm, subcell, 1);CHKERRQ(ierr); */ 10391 } 10392 } 10393 ierr = DMSetUp(subdm);CHKERRQ(ierr); 10394 /* Set cones */ 10395 for (e = 0; e < numSubEdges; ++e) { 10396 const PetscInt edge = subEdges[e]; 10397 const PetscInt subedge = firstSubEdge + e; 10398 const PetscInt *cone; 10399 PetscInt coneSize, c, coneNew[2], subv; 10400 10401 ierr = DMPlexGetConeSize(subdm, e, &coneSize);CHKERRQ(ierr); 10402 if (coneSize != 2) SETERRQ3(comm, PETSC_ERR_ARG_OUTOFRANGE, "Edge %d matching subedge %d had cone size %d != 2", edge, subedge, coneSize); 10403 ierr = DMPlexGetCone(subdm, e, &cone);CHKERRQ(ierr); 10404 for(c = 0; c < coneSize; ++c) { 10405 ierr = PetscFindInt(cone[c], numSubVertices, subVertices, &subv);CHKERRQ(ierr); 10406 if (subv < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Vertex %d has no matching subvertex", cone[v]); 10407 coneNew[c] = firstSubVertex + subv; 10408 } 10409 ierr = DMPlexSetCone(subdm, e, coneNew);CHKERRQ(ierr); 10410 } 10411 for (f = 0; f < numSubFaces; ++f) { 10412 const PetscInt face = subFaces[f]; 10413 const PetscInt subface = firstSubFace + f; 10414 const PetscInt *cone, *support; 10415 PetscInt coneSize, supportSize, subvertex, subcell, c, s; 10416 10417 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10418 ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 10419 for(c = 0; c < coneSize; ++c) { 10420 ierr = PetscFindInt(cone[c], numSubVertices, subVertices, &subvertex);CHKERRQ(ierr); 10421 if (subvertex < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Vertex %d has no matching subvertex", cone[v]); 10422 coneNew[c] = firstSubVertex + subvertex; 10423 } 10424 ierr = DMPlexSetCone(subdm, subface, coneNew);CHKERRQ(ierr); 10425 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10426 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10427 for(s = 0; s < supportSize; ++s) { 10428 ierr = PetscFindInt(support[s], numSubCells, subCells, &subcell);CHKERRQ(ierr); 10429 if (subcell < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Subcell %d not found in surface label", support[s]); 10430 /* ierr = DMPlexAddCone(subdm, subcell, 1);CHKERRQ(ierr); */ 10431 } 10432 } 10433 ierr = ISRestoreIndices(subcellIS, &subCells);CHKERRQ(ierr); 10434 ierr = ISDestroy(&subcellIS);CHKERRQ(ierr); 10435 ierr = ISRestoreIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10436 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 10437 if (dim > 1) { 10438 ierr = ISRestoreIndices(subfaceIS, &subFaces);CHKERRQ(ierr); 10439 ierr = ISDestroy(&subfaceIS);CHKERRQ(ierr); 10440 } 10441 if (dim > 2) { 10442 ierr = ISRestoreIndices(subedgeIS, &subEdges);CHKERRQ(ierr); 10443 ierr = ISDestroy(&subedgeIS);CHKERRQ(ierr); 10444 } 10445 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 10446 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 10447 /* Build coordinates */ 10448 { 10449 PetscSection coordSection, subCoordSection; 10450 Vec coordinates, subCoordinates; 10451 PetscScalar *coords, *subCoords; 10452 PetscInt coordSize; 10453 10454 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10455 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10456 ierr = DMPlexGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 10457 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVertices);CHKERRQ(ierr); 10458 for (v = 0; v < numSubVertices; ++v) { 10459 const PetscInt vertex = subVertices[v]; 10460 const PetscInt subVertex = firstSubVertex+v; 10461 PetscInt dof; 10462 10463 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10464 ierr = PetscSectionSetDof(subCoordSection, subVertex, dof);CHKERRQ(ierr); 10465 } 10466 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10467 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10468 ierr = VecCreate(comm, &subCoordinates);CHKERRQ(ierr); 10469 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10470 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10471 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10472 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10473 for (v = 0; v < numSubVertices; ++v) { 10474 const PetscInt vertex = subVertices[v]; 10475 const PetscInt subVertex = firstSubVertex+v; 10476 PetscInt dof, off, sdof, soff, d; 10477 10478 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10479 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10480 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10481 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10482 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10483 for (d = 0; d < dof; ++d) { 10484 subCoords[soff+d] = coords[off+d]; 10485 } 10486 } 10487 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10488 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10489 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 10490 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10491 } 10492 /* TODO: Create map from submesh points to original mesh points */ 10493 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 10494 PetscFunctionReturn(0); 10495 } 10496 10497 #undef __FUNCT__ 10498 #define __FUNCT__ "DMPlexCreateSubmesh" 10499 /* 10500 DMPlexCreateSubmesh - Extract a hypersurface from the mesh using vertices defined by a label 10501 10502 Input Parameters: 10503 + dm - The original mesh 10504 . vertexLabel - The DMLabel marking vertices contained in the surface 10505 - surfaceLabel - If not PETSC_NULL, create a new label with all the surface points labeled by dimension 10506 10507 Output Parameter: 10508 . subdm - The surface mesh 10509 10510 Level: developer 10511 10512 .seealso: DMPlexGetLabel(), DMLabelSetValue() 10513 */ 10514 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char vertexLabel[], const char surfaceLabel[], DM *subdm) 10515 { 10516 PetscInt dim, depth; 10517 PetscErrorCode ierr; 10518 10519 PetscFunctionBegin; 10520 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10521 PetscValidCharPointer(vertexLabel, 2); 10522 PetscValidPointer(subdm, 4); 10523 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10524 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 10525 ierr = DMCreate(((PetscObject) dm)->comm, subdm);CHKERRQ(ierr); 10526 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 10527 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 10528 if (depth == dim) { 10529 ierr = DMPlexCreateSubmesh_Interpolated(dm, vertexLabel, surfaceLabel, *subdm);CHKERRQ(ierr); 10530 } else { 10531 ierr = DMPlexCreateSubmesh_Uninterpolated(dm, vertexLabel, surfaceLabel, *subdm);CHKERRQ(ierr); 10532 } 10533 PetscFunctionReturn(0); 10534 } 10535 10536 #undef __FUNCT__ 10537 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10538 /* We can easily have a form that takes an IS instead */ 10539 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10540 { 10541 PetscSection section, globalSection; 10542 PetscInt *numbers, p; 10543 PetscErrorCode ierr; 10544 10545 PetscFunctionBegin; 10546 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10547 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10548 for (p = pStart; p < pEnd; ++p) { 10549 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10550 } 10551 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10552 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10553 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10554 for (p = pStart; p < pEnd; ++p) { 10555 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10556 } 10557 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10558 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10559 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10560 PetscFunctionReturn(0); 10561 } 10562 10563 #undef __FUNCT__ 10564 #define __FUNCT__ "DMPlexGetCellNumbering" 10565 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10566 { 10567 DM_Plex *mesh = (DM_Plex*) dm->data; 10568 PetscInt cellHeight, cStart, cEnd, cMax; 10569 PetscErrorCode ierr; 10570 10571 PetscFunctionBegin; 10572 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10573 if (!mesh->globalCellNumbers) { 10574 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10575 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10576 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10577 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 10578 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10579 } 10580 *globalCellNumbers = mesh->globalCellNumbers; 10581 PetscFunctionReturn(0); 10582 } 10583 10584 #undef __FUNCT__ 10585 #define __FUNCT__ "DMPlexGetVertexNumbering" 10586 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10587 { 10588 DM_Plex *mesh = (DM_Plex*) dm->data; 10589 PetscInt vStart, vEnd, vMax; 10590 PetscErrorCode ierr; 10591 10592 PetscFunctionBegin; 10593 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10594 if (!mesh->globalVertexNumbers) { 10595 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10596 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10597 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 10598 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10599 } 10600 *globalVertexNumbers = mesh->globalVertexNumbers; 10601 PetscFunctionReturn(0); 10602 } 10603 10604 #undef __FUNCT__ 10605 #define __FUNCT__ "DMPlexGetSubpointMap" 10606 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 10607 { 10608 DM_Plex *mesh = (DM_Plex*) dm->data; 10609 10610 PetscFunctionBegin; 10611 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10612 PetscValidPointer(subpointMap, 2); 10613 *subpointMap = mesh->subpointMap; 10614 PetscFunctionReturn(0); 10615 } 10616 10617 #undef __FUNCT__ 10618 #define __FUNCT__ "DMPlexSetSubpointMap" 10619 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10620 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 10621 { 10622 DM_Plex *mesh = (DM_Plex *) dm->data; 10623 PetscErrorCode ierr; 10624 10625 PetscFunctionBegin; 10626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10627 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 10628 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 10629 mesh->subpointMap = subpointMap; 10630 ierr = PetscObjectReference((PetscObject) mesh->subpointMap);CHKERRQ(ierr); 10631 PetscFunctionReturn(0); 10632 } 10633 10634 #undef __FUNCT__ 10635 #define __FUNCT__ "DMPlexGetScale" 10636 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10637 { 10638 DM_Plex *mesh = (DM_Plex*) dm->data; 10639 10640 PetscFunctionBegin; 10641 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10642 PetscValidPointer(scale, 3); 10643 *scale = mesh->scale[unit]; 10644 PetscFunctionReturn(0); 10645 } 10646 10647 #undef __FUNCT__ 10648 #define __FUNCT__ "DMPlexSetScale" 10649 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10650 { 10651 DM_Plex *mesh = (DM_Plex*) dm->data; 10652 10653 PetscFunctionBegin; 10654 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10655 mesh->scale[unit] = scale; 10656 PetscFunctionReturn(0); 10657 } 10658 10659 10660 /******************************************************************************* 10661 This should be in a separate Discretization object, but I am not sure how to lay 10662 it out yet, so I am stuffing things here while I experiment. 10663 *******************************************************************************/ 10664 #undef __FUNCT__ 10665 #define __FUNCT__ "DMPlexSetFEMIntegration" 10666 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10667 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10668 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10669 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10670 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10671 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10672 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10673 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10674 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10675 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10676 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10677 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10678 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10679 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10680 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10681 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10682 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 10683 { 10684 DM_Plex *mesh = (DM_Plex*) dm->data; 10685 10686 PetscFunctionBegin; 10687 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10688 mesh->integrateResidualFEM = integrateResidualFEM; 10689 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10690 mesh->integrateJacobianFEM = integrateJacobianFEM; 10691 PetscFunctionReturn(0); 10692 } 10693 10694 #undef __FUNCT__ 10695 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10696 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10697 { 10698 Vec coordinates; 10699 PetscSection section, cSection; 10700 PetscInt dim, vStart, vEnd, v, c, d; 10701 PetscScalar *values, *cArray; 10702 PetscReal *coords; 10703 PetscErrorCode ierr; 10704 10705 PetscFunctionBegin; 10706 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10707 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10708 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10709 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10710 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10711 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10712 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10713 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10714 for (v = vStart; v < vEnd; ++v) { 10715 PetscInt dof, off; 10716 10717 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10718 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10719 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10720 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 10721 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10722 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10723 } 10724 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10725 /* Temporary, must be replaced by a projection on the finite element basis */ 10726 { 10727 PetscInt eStart = 0, eEnd = 0, e, depth; 10728 10729 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10730 --depth; 10731 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10732 for (e = eStart; e < eEnd; ++e) { 10733 const PetscInt *cone = PETSC_NULL; 10734 PetscInt coneSize, d; 10735 PetscScalar *coordsA, *coordsB; 10736 10737 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10738 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10739 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10740 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10741 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10742 for (d = 0; d < dim; ++d) { 10743 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10744 } 10745 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10746 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10747 } 10748 } 10749 10750 ierr = PetscFree(coords);CHKERRQ(ierr); 10751 ierr = PetscFree(values);CHKERRQ(ierr); 10752 #if 0 10753 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10754 PetscReal detJ; 10755 10756 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10757 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10758 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10759 10760 for (PetscInt c = cStart; c < cEnd; ++c) { 10761 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10762 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10763 const int oSize = pV.getSize(); 10764 int v = 0; 10765 10766 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10767 for (PetscInt cl = 0; cl < oSize; ++cl) { 10768 const PetscInt fDim; 10769 10770 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10771 if (pointDim) { 10772 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10773 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10774 } 10775 } 10776 } 10777 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10778 pV.clear(); 10779 } 10780 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10781 ierr = PetscFree(values);CHKERRQ(ierr); 10782 #endif 10783 PetscFunctionReturn(0); 10784 } 10785 10786 #undef __FUNCT__ 10787 #define __FUNCT__ "DMPlexProjectFunction" 10788 /*@C 10789 DMPlexProjectFunction - This projects the given function into the function space provided. 10790 10791 Input Parameters: 10792 + dm - The DM 10793 . numComp - The number of components (functions) 10794 . funcs - The coordinate functions to evaluate 10795 - mode - The insertion mode for values 10796 10797 Output Parameter: 10798 . X - vector 10799 10800 Level: developer 10801 10802 Note: 10803 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10804 We will eventually fix it. 10805 10806 ,seealso: DMPlexComputeL2Diff() 10807 */ 10808 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10809 { 10810 Vec localX; 10811 PetscErrorCode ierr; 10812 10813 PetscFunctionBegin; 10814 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10815 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10816 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10817 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10818 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10819 PetscFunctionReturn(0); 10820 } 10821 10822 #undef __FUNCT__ 10823 #define __FUNCT__ "DMPlexComputeL2Diff" 10824 /*@C 10825 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10826 10827 Input Parameters: 10828 + dm - The DM 10829 . quad - The PetscQuadrature object for each field 10830 . funcs - The functions to evaluate for each field component 10831 - X - The coefficient vector u_h 10832 10833 Output Parameter: 10834 . diff - The diff ||u - u_h||_2 10835 10836 Level: developer 10837 10838 .seealso: DMPlexProjectFunction() 10839 */ 10840 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10841 { 10842 const PetscInt debug = 0; 10843 PetscSection section; 10844 Vec localX; 10845 PetscReal *coords, *v0, *J, *invJ, detJ; 10846 PetscReal localDiff = 0.0; 10847 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10848 PetscErrorCode ierr; 10849 10850 PetscFunctionBegin; 10851 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10852 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10853 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10854 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10855 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10856 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10857 for (field = 0; field < numFields; ++field) { 10858 numComponents += quad[field].numComponents; 10859 } 10860 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10861 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10862 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10863 for (c = cStart; c < cEnd; ++c) { 10864 const PetscScalar *x; 10865 PetscReal elemDiff = 0.0; 10866 10867 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10868 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10869 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10870 10871 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10872 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10873 const PetscReal *quadPoints = quad[field].quadPoints; 10874 const PetscReal *quadWeights = quad[field].quadWeights; 10875 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10876 const PetscInt numBasisComps = quad[field].numComponents; 10877 const PetscReal *basis = quad[field].basis; 10878 PetscInt q, d, e, fc, f; 10879 10880 if (debug) { 10881 char title[1024]; 10882 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10883 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10884 } 10885 for (q = 0; q < numQuadPoints; ++q) { 10886 for (d = 0; d < dim; d++) { 10887 coords[d] = v0[d]; 10888 for (e = 0; e < dim; e++) { 10889 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10890 } 10891 } 10892 for (fc = 0; fc < numBasisComps; ++fc) { 10893 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10894 PetscReal interpolant = 0.0; 10895 for (f = 0; f < numBasisFuncs; ++f) { 10896 const PetscInt fidx = f*numBasisComps+fc; 10897 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10898 } 10899 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10900 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10901 } 10902 } 10903 comp += numBasisComps; 10904 fieldOffset += numBasisFuncs*numBasisComps; 10905 } 10906 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10907 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10908 localDiff += elemDiff; 10909 } 10910 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10911 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10912 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10913 *diff = PetscSqrtReal(*diff); 10914 PetscFunctionReturn(0); 10915 } 10916 10917 #undef __FUNCT__ 10918 #define __FUNCT__ "DMPlexComputeResidualFEM" 10919 /*@ 10920 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10921 10922 Input Parameters: 10923 + dm - The mesh 10924 . X - Local input vector 10925 - user - The user context 10926 10927 Output Parameter: 10928 . F - Local output vector 10929 10930 Note: 10931 The second member of the user context must be an FEMContext. 10932 10933 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10934 like a GPU, or vectorize on a multicore machine. 10935 10936 .seealso: DMPlexComputeJacobianActionFEM() 10937 */ 10938 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10939 { 10940 DM_Plex *mesh = (DM_Plex*) dm->data; 10941 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10942 PetscQuadrature *quad = fem->quad; 10943 PetscSection section; 10944 PetscReal *v0, *J, *invJ, *detJ; 10945 PetscScalar *elemVec, *u; 10946 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10947 PetscInt cellDof = 0, numComponents = 0; 10948 PetscErrorCode ierr; 10949 10950 PetscFunctionBegin; 10951 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10952 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10953 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10954 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10955 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10956 numCells = cEnd - cStart; 10957 for (field = 0; field < numFields; ++field) { 10958 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10959 numComponents += quad[field].numComponents; 10960 } 10961 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10962 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10963 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); 10964 for (c = cStart; c < cEnd; ++c) { 10965 const PetscScalar *x; 10966 PetscInt i; 10967 10968 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10969 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10970 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10971 10972 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10973 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10974 } 10975 for (field = 0; field < numFields; ++field) { 10976 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10977 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10978 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10979 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10980 /* Conforming batches */ 10981 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10982 PetscInt numBlocks = 1; 10983 PetscInt batchSize = numBlocks * blockSize; 10984 PetscInt numBatches = numBatchesTmp; 10985 PetscInt numChunks = numCells / (numBatches*batchSize); 10986 /* Remainder */ 10987 PetscInt numRemainder = numCells % (numBatches * batchSize); 10988 PetscInt offset = numCells - numRemainder; 10989 10990 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10991 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10992 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10993 } 10994 for (c = cStart; c < cEnd; ++c) { 10995 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10996 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10997 } 10998 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10999 if (mesh->printFEM) { 11000 PetscMPIInt rank, numProcs; 11001 PetscInt p; 11002 11003 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 11004 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 11005 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 11006 for (p = 0; p < numProcs; ++p) { 11007 if (p == rank) { 11008 Vec f; 11009 11010 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 11011 ierr = VecCopy(F, f);CHKERRQ(ierr); 11012 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 11013 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 11014 ierr = VecDestroy(&f);CHKERRQ(ierr); 11015 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 11016 } 11017 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 11018 } 11019 } 11020 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11021 PetscFunctionReturn(0); 11022 } 11023 11024 #undef __FUNCT__ 11025 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 11026 /*@C 11027 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 11028 11029 Input Parameters: 11030 + dm - The mesh 11031 . J - The Jacobian shell matrix 11032 . X - Local input vector 11033 - user - The user context 11034 11035 Output Parameter: 11036 . F - Local output vector 11037 11038 Note: 11039 The second member of the user context must be an FEMContext. 11040 11041 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 11042 like a GPU, or vectorize on a multicore machine. 11043 11044 .seealso: DMPlexComputeResidualFEM() 11045 */ 11046 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 11047 { 11048 DM_Plex *mesh = (DM_Plex*) dm->data; 11049 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 11050 PetscQuadrature *quad = fem->quad; 11051 PetscSection section; 11052 JacActionCtx *jctx; 11053 PetscReal *v0, *J, *invJ, *detJ; 11054 PetscScalar *elemVec, *u, *a; 11055 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 11056 PetscInt cellDof = 0; 11057 PetscErrorCode ierr; 11058 11059 PetscFunctionBegin; 11060 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11061 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 11062 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 11063 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 11064 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 11065 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 11066 numCells = cEnd - cStart; 11067 for (field = 0; field < numFields; ++field) { 11068 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 11069 } 11070 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 11071 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); 11072 for (c = cStart; c < cEnd; ++c) { 11073 const PetscScalar *x; 11074 PetscInt i; 11075 11076 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 11077 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 11078 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 11079 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 11080 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 11081 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 11082 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 11083 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 11084 } 11085 for (field = 0; field < numFields; ++field) { 11086 const PetscInt numQuadPoints = quad[field].numQuadPoints; 11087 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 11088 /* Conforming batches */ 11089 PetscInt blockSize = numBasisFuncs*numQuadPoints; 11090 PetscInt numBlocks = 1; 11091 PetscInt batchSize = numBlocks * blockSize; 11092 PetscInt numBatches = numBatchesTmp; 11093 PetscInt numChunks = numCells / (numBatches*batchSize); 11094 /* Remainder */ 11095 PetscInt numRemainder = numCells % (numBatches * batchSize); 11096 PetscInt offset = numCells - numRemainder; 11097 11098 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); 11099 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], 11100 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 11101 } 11102 for (c = cStart; c < cEnd; ++c) { 11103 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 11104 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 11105 } 11106 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 11107 if (mesh->printFEM) { 11108 PetscMPIInt rank, numProcs; 11109 PetscInt p; 11110 11111 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 11112 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 11113 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 11114 for (p = 0; p < numProcs; ++p) { 11115 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 11116 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 11117 } 11118 } 11119 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11120 PetscFunctionReturn(0); 11121 } 11122 11123 #undef __FUNCT__ 11124 #define __FUNCT__ "DMPlexComputeJacobianFEM" 11125 /*@ 11126 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 11127 11128 Input Parameters: 11129 + dm - The mesh 11130 . X - Local input vector 11131 - user - The user context 11132 11133 Output Parameter: 11134 . Jac - Jacobian matrix 11135 11136 Note: 11137 The second member of the user context must be an FEMContext. 11138 11139 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 11140 like a GPU, or vectorize on a multicore machine. 11141 11142 .seealso: FormFunctionLocal() 11143 */ 11144 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 11145 { 11146 DM_Plex *mesh = (DM_Plex*) dm->data; 11147 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 11148 PetscQuadrature *quad = fem->quad; 11149 PetscSection section; 11150 PetscReal *v0, *J, *invJ, *detJ; 11151 PetscScalar *elemMat, *u; 11152 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 11153 PetscInt cellDof = 0, numComponents = 0; 11154 PetscBool isShell; 11155 PetscErrorCode ierr; 11156 11157 PetscFunctionBegin; 11158 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11159 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 11160 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 11161 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 11162 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 11163 numCells = cEnd - cStart; 11164 for (field = 0; field < numFields; ++field) { 11165 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 11166 numComponents += quad[field].numComponents; 11167 } 11168 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 11169 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 11170 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); 11171 for (c = cStart; c < cEnd; ++c) { 11172 const PetscScalar *x; 11173 PetscInt i; 11174 11175 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 11176 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 11177 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 11178 11179 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 11180 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 11181 } 11182 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 11183 for (fieldI = 0; fieldI < numFields; ++fieldI) { 11184 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 11185 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 11186 PetscInt fieldJ; 11187 11188 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 11189 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 11190 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 11191 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 11192 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 11193 /* Conforming batches */ 11194 PetscInt blockSize = numBasisFuncs*numQuadPoints; 11195 PetscInt numBlocks = 1; 11196 PetscInt batchSize = numBlocks * blockSize; 11197 PetscInt numBatches = numBatchesTmp; 11198 PetscInt numChunks = numCells / (numBatches*batchSize); 11199 /* Remainder */ 11200 PetscInt numRemainder = numCells % (numBatches * batchSize); 11201 PetscInt offset = numCells - numRemainder; 11202 11203 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 11204 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 11205 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 11206 } 11207 } 11208 for (c = cStart; c < cEnd; ++c) { 11209 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 11210 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 11211 } 11212 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 11213 11214 /* Assemble matrix, using the 2-step process: 11215 MatAssemblyBegin(), MatAssemblyEnd(). */ 11216 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11217 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11218 11219 if (mesh->printFEM) { 11220 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 11221 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 11222 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 11223 } 11224 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11225 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 11226 if (isShell) { 11227 JacActionCtx *jctx; 11228 11229 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 11230 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 11231 } 11232 *str = SAME_NONZERO_PATTERN; 11233 PetscFunctionReturn(0); 11234 } 11235 11236 11237 #undef __FUNCT__ 11238 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 11239 /*@C 11240 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 11241 the local section and an SF describing the section point overlap. 11242 11243 Input Parameters: 11244 + s - The PetscSection for the local field layout 11245 . sf - The SF describing parallel layout of the section points 11246 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 11247 . label - The label specifying the points 11248 - labelValue - The label stratum specifying the points 11249 11250 Output Parameter: 11251 . gsection - The PetscSection for the global field layout 11252 11253 Note: This gives negative sizes and offsets to points not owned by this process 11254 11255 Level: developer 11256 11257 .seealso: PetscSectionCreate() 11258 @*/ 11259 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 11260 { 11261 PetscInt *neg; 11262 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 11263 PetscErrorCode ierr; 11264 11265 PetscFunctionBegin; 11266 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 11267 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 11268 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 11269 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 11270 /* Mark ghost points with negative dof */ 11271 for (p = pStart; p < pEnd; ++p) { 11272 PetscInt value; 11273 11274 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 11275 if (value != labelValue) continue; 11276 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 11277 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 11278 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 11279 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 11280 neg[p-pStart] = -(dof+1); 11281 } 11282 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 11283 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 11284 if (nroots >= 0) { 11285 if (nroots > pEnd - pStart) { 11286 PetscInt *tmpDof; 11287 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11288 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 11289 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11290 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11291 for (p = pStart; p < pEnd; ++p) { 11292 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 11293 } 11294 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 11295 } else { 11296 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11297 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11298 } 11299 } 11300 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 11301 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11302 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 11303 11304 (*gsection)->atlasOff[p] = off; 11305 11306 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 11307 } 11308 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 11309 globalOff -= off; 11310 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11311 (*gsection)->atlasOff[p] += globalOff; 11312 11313 neg[p] = -((*gsection)->atlasOff[p]+1); 11314 } 11315 /* Put in negative offsets for ghost points */ 11316 if (nroots >= 0) { 11317 if (nroots > pEnd - pStart) { 11318 PetscInt *tmpOff; 11319 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11320 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 11321 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11322 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11323 for (p = pStart; p < pEnd; ++p) { 11324 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 11325 } 11326 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 11327 } else { 11328 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11329 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11330 } 11331 } 11332 ierr = PetscFree(neg);CHKERRQ(ierr); 11333 PetscFunctionReturn(0); 11334 } 11335