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 PetscInt *tmpClosure,*tmpAdj,*visits; 898 PetscInt c,cStart,cEnd,pStart,pEnd; 899 PetscErrorCode ierr; 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 PetscFunctionReturn(0); 7459 } 7460 7461 #undef __FUNCT__ 7462 #define __FUNCT__ "DMPlexSetRefinementUniform" 7463 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7464 { 7465 DM_Plex *mesh = (DM_Plex*) dm->data; 7466 7467 PetscFunctionBegin; 7468 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7469 mesh->refinementUniform = refinementUniform; 7470 PetscFunctionReturn(0); 7471 } 7472 7473 #undef __FUNCT__ 7474 #define __FUNCT__ "DMPlexGetRefinementUniform" 7475 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7476 { 7477 DM_Plex *mesh = (DM_Plex*) dm->data; 7478 7479 PetscFunctionBegin; 7480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7481 PetscValidPointer(refinementUniform, 2); 7482 *refinementUniform = mesh->refinementUniform; 7483 PetscFunctionReturn(0); 7484 } 7485 7486 #undef __FUNCT__ 7487 #define __FUNCT__ "DMPlexSetRefinementLimit" 7488 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7489 { 7490 DM_Plex *mesh = (DM_Plex*) dm->data; 7491 7492 PetscFunctionBegin; 7493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7494 mesh->refinementLimit = refinementLimit; 7495 PetscFunctionReturn(0); 7496 } 7497 7498 #undef __FUNCT__ 7499 #define __FUNCT__ "DMPlexGetRefinementLimit" 7500 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7501 { 7502 DM_Plex *mesh = (DM_Plex*) dm->data; 7503 7504 PetscFunctionBegin; 7505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7506 PetscValidPointer(refinementLimit, 2); 7507 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7508 *refinementLimit = mesh->refinementLimit; 7509 PetscFunctionReturn(0); 7510 } 7511 7512 #undef __FUNCT__ 7513 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7514 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7515 { 7516 PetscInt dim, cStart, coneSize, cMax; 7517 PetscErrorCode ierr; 7518 7519 PetscFunctionBegin; 7520 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7521 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7522 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7523 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7524 switch (dim) { 7525 case 2: 7526 switch (coneSize) { 7527 case 3: 7528 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7529 else *cellRefiner = 1; /* Triangular */ 7530 break; 7531 case 4: 7532 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7533 else *cellRefiner = 2; /* Quadrilateral */ 7534 break; 7535 default: 7536 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7537 } 7538 break; 7539 default: 7540 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7541 } 7542 PetscFunctionReturn(0); 7543 } 7544 7545 #undef __FUNCT__ 7546 #define __FUNCT__ "DMRefine_Plex" 7547 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7548 { 7549 PetscReal refinementLimit; 7550 PetscInt dim, cStart, cEnd; 7551 char genname[1024], *name = PETSC_NULL; 7552 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7553 PetscErrorCode ierr; 7554 7555 PetscFunctionBegin; 7556 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7557 if (isUniform) { 7558 CellRefiner cellRefiner; 7559 7560 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7561 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7562 PetscFunctionReturn(0); 7563 } 7564 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7565 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7566 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7567 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7568 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7569 if (flg) name = genname; 7570 if (name) { 7571 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7572 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7573 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7574 } 7575 switch (dim) { 7576 case 2: 7577 if (!name || isTriangle) { 7578 #if defined(PETSC_HAVE_TRIANGLE) 7579 double *maxVolumes; 7580 PetscInt c; 7581 7582 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7583 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7584 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7585 #else 7586 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7587 #endif 7588 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7589 break; 7590 case 3: 7591 if (!name || isCTetgen) { 7592 #if defined(PETSC_HAVE_CTETGEN) 7593 PetscReal *maxVolumes; 7594 PetscInt c; 7595 7596 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7597 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7598 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7599 #else 7600 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7601 #endif 7602 } else if (isTetgen) { 7603 #if defined(PETSC_HAVE_TETGEN) 7604 double *maxVolumes; 7605 PetscInt c; 7606 7607 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7608 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7609 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7610 #else 7611 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7612 #endif 7613 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7614 break; 7615 default: 7616 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7617 } 7618 PetscFunctionReturn(0); 7619 } 7620 7621 #undef __FUNCT__ 7622 #define __FUNCT__ "DMPlexGetDepth" 7623 /*@ 7624 DMPlexGetDepth - get the number of strata 7625 7626 Not Collective 7627 7628 Input Parameters: 7629 . dm - The DMPlex object 7630 7631 Output Parameters: 7632 . depth - number of strata 7633 7634 Level: developer 7635 7636 Notes: 7637 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7638 7639 .keywords: mesh, points 7640 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7641 @*/ 7642 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7643 { 7644 PetscInt d; 7645 PetscErrorCode ierr; 7646 7647 PetscFunctionBegin; 7648 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7649 PetscValidPointer(depth, 2); 7650 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7651 *depth = d-1; 7652 PetscFunctionReturn(0); 7653 } 7654 7655 #undef __FUNCT__ 7656 #define __FUNCT__ "DMPlexGetDepthStratum" 7657 /*@ 7658 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7659 7660 Not Collective 7661 7662 Input Parameters: 7663 + dm - The DMPlex object 7664 - stratumValue - The requested depth 7665 7666 Output Parameters: 7667 + start - The first point at this depth 7668 - end - One beyond the last point at this depth 7669 7670 Level: developer 7671 7672 .keywords: mesh, points 7673 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7674 @*/ 7675 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7676 { 7677 DM_Plex *mesh = (DM_Plex*) dm->data; 7678 DMLabel next = mesh->labels; 7679 PetscBool flg = PETSC_FALSE; 7680 PetscInt depth; 7681 PetscErrorCode ierr; 7682 7683 PetscFunctionBegin; 7684 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7685 if (stratumValue < 0) { 7686 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7687 PetscFunctionReturn(0); 7688 } else { 7689 PetscInt pStart, pEnd; 7690 7691 if (start) *start = 0; 7692 if (end) *end = 0; 7693 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7694 if (pStart == pEnd) PetscFunctionReturn(0); 7695 } 7696 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7697 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7698 /* We should have a generic GetLabel() and a Label class */ 7699 while (next) { 7700 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7701 if (flg) break; 7702 next = next->next; 7703 } 7704 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7705 depth = stratumValue; 7706 if ((depth < 0) || (depth >= next->numStrata)) { 7707 if (start) *start = 0; 7708 if (end) *end = 0; 7709 } else { 7710 if (start) *start = next->points[next->stratumOffsets[depth]]; 7711 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7712 } 7713 PetscFunctionReturn(0); 7714 } 7715 7716 #undef __FUNCT__ 7717 #define __FUNCT__ "DMPlexGetHeightStratum" 7718 /*@ 7719 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7720 7721 Not Collective 7722 7723 Input Parameters: 7724 + dm - The DMPlex object 7725 - stratumValue - The requested height 7726 7727 Output Parameters: 7728 + start - The first point at this height 7729 - end - One beyond the last point at this height 7730 7731 Level: developer 7732 7733 .keywords: mesh, points 7734 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7735 @*/ 7736 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7737 { 7738 DM_Plex *mesh = (DM_Plex*) dm->data; 7739 DMLabel next = mesh->labels; 7740 PetscBool flg = PETSC_FALSE; 7741 PetscInt depth; 7742 PetscErrorCode ierr; 7743 7744 PetscFunctionBegin; 7745 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7746 if (stratumValue < 0) { 7747 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7748 } else { 7749 PetscInt pStart, pEnd; 7750 7751 if (start) *start = 0; 7752 if (end) *end = 0; 7753 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7754 if (pStart == pEnd) PetscFunctionReturn(0); 7755 } 7756 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7757 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7758 /* We should have a generic GetLabel() and a Label class */ 7759 while (next) { 7760 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7761 if (flg) break; 7762 next = next->next; 7763 } 7764 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7765 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7766 if ((depth < 0) || (depth >= next->numStrata)) { 7767 if (start) *start = 0; 7768 if (end) *end = 0; 7769 } else { 7770 if (start) *start = next->points[next->stratumOffsets[depth]]; 7771 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7772 } 7773 PetscFunctionReturn(0); 7774 } 7775 7776 #undef __FUNCT__ 7777 #define __FUNCT__ "DMPlexCreateSectionInitial" 7778 /* Set the number of dof on each point and separate by fields */ 7779 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7780 { 7781 PetscInt *numDofTot; 7782 PetscInt pStart = 0, pEnd = 0; 7783 PetscInt p, d, f; 7784 PetscErrorCode ierr; 7785 7786 PetscFunctionBegin; 7787 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7788 for (d = 0; d <= dim; ++d) { 7789 numDofTot[d] = 0; 7790 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7791 } 7792 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7793 if (numFields > 0) { 7794 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7795 if (numComp) { 7796 for (f = 0; f < numFields; ++f) { 7797 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7798 } 7799 } 7800 } 7801 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7802 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7803 for (d = 0; d <= dim; ++d) { 7804 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7805 for (p = pStart; p < pEnd; ++p) { 7806 for (f = 0; f < numFields; ++f) { 7807 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7808 } 7809 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7810 } 7811 } 7812 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7813 PetscFunctionReturn(0); 7814 } 7815 7816 #undef __FUNCT__ 7817 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7818 /* Set the number of dof on each point and separate by fields 7819 If constDof is PETSC_DETERMINE, constrain every dof on the point 7820 */ 7821 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7822 { 7823 PetscInt numFields; 7824 PetscInt bc; 7825 PetscErrorCode ierr; 7826 7827 PetscFunctionBegin; 7828 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7829 for (bc = 0; bc < numBC; ++bc) { 7830 PetscInt field = 0; 7831 const PetscInt *idx; 7832 PetscInt n, i; 7833 7834 if (numFields) field = bcField[bc]; 7835 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7836 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7837 for (i = 0; i < n; ++i) { 7838 const PetscInt p = idx[i]; 7839 PetscInt numConst = constDof; 7840 7841 /* Constrain every dof on the point */ 7842 if (numConst < 0) { 7843 if (numFields) { 7844 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7845 } else { 7846 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7847 } 7848 } 7849 if (numFields) { 7850 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7851 } 7852 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7853 } 7854 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7855 } 7856 PetscFunctionReturn(0); 7857 } 7858 7859 #undef __FUNCT__ 7860 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7861 /* Set the constrained indices on each point and separate by fields */ 7862 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7863 { 7864 PetscInt *maxConstraints; 7865 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7866 PetscErrorCode ierr; 7867 7868 PetscFunctionBegin; 7869 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7870 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7871 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7872 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7873 for (p = pStart; p < pEnd; ++p) { 7874 PetscInt cdof; 7875 7876 if (numFields) { 7877 for (f = 0; f < numFields; ++f) { 7878 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7879 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7880 } 7881 } else { 7882 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7883 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7884 } 7885 } 7886 for (f = 0; f < numFields; ++f) { 7887 maxConstraints[numFields] += maxConstraints[f]; 7888 } 7889 if (maxConstraints[numFields]) { 7890 PetscInt *indices; 7891 7892 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7893 for (p = pStart; p < pEnd; ++p) { 7894 PetscInt cdof, d; 7895 7896 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7897 if (cdof) { 7898 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7899 if (numFields) { 7900 PetscInt numConst = 0, foff = 0; 7901 7902 for (f = 0; f < numFields; ++f) { 7903 PetscInt cfdof, fdof; 7904 7905 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7906 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7907 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7908 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7909 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7910 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7911 numConst += cfdof; 7912 foff += fdof; 7913 } 7914 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7915 } else { 7916 for (d = 0; d < cdof; ++d) indices[d] = d; 7917 } 7918 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7919 } 7920 } 7921 ierr = PetscFree(indices);CHKERRQ(ierr); 7922 } 7923 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7924 PetscFunctionReturn(0); 7925 } 7926 7927 #undef __FUNCT__ 7928 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7929 /* Set the constrained field indices on each point */ 7930 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7931 { 7932 const PetscInt *points, *indices; 7933 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7934 PetscErrorCode ierr; 7935 7936 PetscFunctionBegin; 7937 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7938 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7939 7940 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7941 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7942 if (!constraintIndices) { 7943 PetscInt *idx, i; 7944 7945 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7946 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7947 for (i = 0; i < maxDof; ++i) idx[i] = i; 7948 for (p = 0; p < numPoints; ++p) { 7949 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7950 } 7951 ierr = PetscFree(idx);CHKERRQ(ierr); 7952 } else { 7953 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7954 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7955 for (p = 0; p < numPoints; ++p) { 7956 PetscInt fcdof; 7957 7958 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7959 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); 7960 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7961 } 7962 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7963 } 7964 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7965 PetscFunctionReturn(0); 7966 } 7967 7968 #undef __FUNCT__ 7969 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7970 /* Set the constrained indices on each point and separate by fields */ 7971 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7972 { 7973 PetscInt *indices; 7974 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7975 PetscErrorCode ierr; 7976 7977 PetscFunctionBegin; 7978 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7979 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7980 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7981 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7982 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7983 for (p = pStart; p < pEnd; ++p) { 7984 PetscInt cdof, d; 7985 7986 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7987 if (cdof) { 7988 PetscInt numConst = 0, foff = 0; 7989 7990 for (f = 0; f < numFields; ++f) { 7991 const PetscInt *fcind; 7992 PetscInt fdof, fcdof; 7993 7994 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7995 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7996 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7997 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7998 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7999 foff += fdof; 8000 numConst += fcdof; 8001 } 8002 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8003 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8004 } 8005 } 8006 ierr = PetscFree(indices);CHKERRQ(ierr); 8007 PetscFunctionReturn(0); 8008 } 8009 8010 #undef __FUNCT__ 8011 #define __FUNCT__ "DMPlexCreateSection" 8012 /*@C 8013 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8014 8015 Not Collective 8016 8017 Input Parameters: 8018 + dm - The DMPlex object 8019 . dim - The spatial dimension of the problem 8020 . numFields - The number of fields in the problem 8021 . numComp - An array of size numFields that holds the number of components for each field 8022 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8023 . numBC - The number of boundary conditions 8024 . bcField - An array of size numBC giving the field number for each boundry condition 8025 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8026 8027 Output Parameter: 8028 . section - The PetscSection object 8029 8030 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 8031 nubmer of dof for field 0 on each edge. 8032 8033 Level: developer 8034 8035 .keywords: mesh, elements 8036 .seealso: DMPlexCreate(), PetscSectionCreate() 8037 @*/ 8038 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8039 { 8040 PetscErrorCode ierr; 8041 8042 PetscFunctionBegin; 8043 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8044 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8045 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8046 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8047 { 8048 PetscBool view = PETSC_FALSE; 8049 8050 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8051 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8052 } 8053 PetscFunctionReturn(0); 8054 } 8055 8056 #undef __FUNCT__ 8057 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8058 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8059 { 8060 PetscSection section; 8061 PetscErrorCode ierr; 8062 8063 PetscFunctionBegin; 8064 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8065 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8066 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8067 PetscFunctionReturn(0); 8068 } 8069 8070 #undef __FUNCT__ 8071 #define __FUNCT__ "DMPlexGetCoordinateSection" 8072 /*@ 8073 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8074 8075 Not Collective 8076 8077 Input Parameter: 8078 . dm - The DMPlex object 8079 8080 Output Parameter: 8081 . section - The PetscSection object 8082 8083 Level: intermediate 8084 8085 .keywords: mesh, coordinates 8086 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8087 @*/ 8088 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8089 { 8090 DM cdm; 8091 PetscErrorCode ierr; 8092 8093 PetscFunctionBegin; 8094 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8095 PetscValidPointer(section, 2); 8096 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8097 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8098 PetscFunctionReturn(0); 8099 } 8100 8101 #undef __FUNCT__ 8102 #define __FUNCT__ "DMPlexSetCoordinateSection" 8103 /*@ 8104 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8105 8106 Not Collective 8107 8108 Input Parameters: 8109 + dm - The DMPlex object 8110 - section - The PetscSection object 8111 8112 Level: intermediate 8113 8114 .keywords: mesh, coordinates 8115 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8116 @*/ 8117 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8118 { 8119 DM cdm; 8120 PetscErrorCode ierr; 8121 8122 PetscFunctionBegin; 8123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8125 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8126 PetscFunctionReturn(0); 8127 } 8128 8129 #undef __FUNCT__ 8130 #define __FUNCT__ "DMPlexGetConeSection" 8131 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8132 { 8133 DM_Plex *mesh = (DM_Plex*) dm->data; 8134 8135 PetscFunctionBegin; 8136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8137 if (section) *section = mesh->coneSection; 8138 PetscFunctionReturn(0); 8139 } 8140 8141 #undef __FUNCT__ 8142 #define __FUNCT__ "DMPlexGetCones" 8143 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8144 { 8145 DM_Plex *mesh = (DM_Plex*) dm->data; 8146 8147 PetscFunctionBegin; 8148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8149 if (cones) *cones = mesh->cones; 8150 PetscFunctionReturn(0); 8151 } 8152 8153 #undef __FUNCT__ 8154 #define __FUNCT__ "DMPlexGetConeOrientations" 8155 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8156 { 8157 DM_Plex *mesh = (DM_Plex*) dm->data; 8158 8159 PetscFunctionBegin; 8160 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8161 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8162 PetscFunctionReturn(0); 8163 } 8164 8165 #undef __FUNCT__ 8166 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8167 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8168 { 8169 const PetscInt embedDim = 2; 8170 PetscReal x = PetscRealPart(point[0]); 8171 PetscReal y = PetscRealPart(point[1]); 8172 PetscReal v0[2], J[4], invJ[4], detJ; 8173 PetscReal xi, eta; 8174 PetscErrorCode ierr; 8175 8176 PetscFunctionBegin; 8177 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8178 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8179 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8180 8181 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 8182 else *cell = -1; 8183 PetscFunctionReturn(0); 8184 } 8185 8186 #undef __FUNCT__ 8187 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8188 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8189 { 8190 PetscSection coordSection; 8191 Vec coordsLocal; 8192 const PetscScalar *coords; 8193 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8194 PetscReal x = PetscRealPart(point[0]); 8195 PetscReal y = PetscRealPart(point[1]); 8196 PetscInt crossings = 0, f; 8197 PetscErrorCode ierr; 8198 8199 PetscFunctionBegin; 8200 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8201 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8202 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8203 for (f = 0; f < 4; ++f) { 8204 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8205 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8206 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8207 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8208 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8209 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8210 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8211 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8212 if ((cond1 || cond2) && above) ++crossings; 8213 } 8214 if (crossings % 2) *cell = c; 8215 else *cell = -1; 8216 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8217 PetscFunctionReturn(0); 8218 } 8219 8220 #undef __FUNCT__ 8221 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8222 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8223 { 8224 const PetscInt embedDim = 3; 8225 PetscReal v0[3], J[9], invJ[9], detJ; 8226 PetscReal x = PetscRealPart(point[0]); 8227 PetscReal y = PetscRealPart(point[1]); 8228 PetscReal z = PetscRealPart(point[2]); 8229 PetscReal xi, eta, zeta; 8230 PetscErrorCode ierr; 8231 8232 PetscFunctionBegin; 8233 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8234 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8235 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8236 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8237 8238 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 8239 else *cell = -1; 8240 PetscFunctionReturn(0); 8241 } 8242 8243 #undef __FUNCT__ 8244 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8245 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8246 { 8247 PetscSection coordSection; 8248 Vec coordsLocal; 8249 const PetscScalar *coords; 8250 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8251 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8252 PetscBool found = PETSC_TRUE; 8253 PetscInt f; 8254 PetscErrorCode ierr; 8255 8256 PetscFunctionBegin; 8257 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8258 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8259 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8260 for (f = 0; f < 6; ++f) { 8261 /* Check the point is under plane */ 8262 /* Get face normal */ 8263 PetscReal v_i[3]; 8264 PetscReal v_j[3]; 8265 PetscReal normal[3]; 8266 PetscReal pp[3]; 8267 PetscReal dot; 8268 8269 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8270 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8271 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8272 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8273 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8274 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8275 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8276 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8277 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8278 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8279 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8280 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8281 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8282 8283 /* Check that projected point is in face (2D location problem) */ 8284 if (dot < 0.0) { 8285 found = PETSC_FALSE; 8286 break; 8287 } 8288 } 8289 if (found) *cell = c; 8290 else *cell = -1; 8291 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8292 PetscFunctionReturn(0); 8293 } 8294 8295 #undef __FUNCT__ 8296 #define __FUNCT__ "DMLocatePoints_Plex" 8297 /* 8298 Need to implement using the guess 8299 */ 8300 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8301 { 8302 PetscInt cell = -1 /*, guess = -1*/; 8303 PetscInt bs, numPoints, p; 8304 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8305 PetscInt *cells; 8306 PetscScalar *a; 8307 PetscErrorCode ierr; 8308 8309 PetscFunctionBegin; 8310 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8311 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8312 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8313 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8314 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8315 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8316 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8317 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); 8318 numPoints /= bs; 8319 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8320 for (p = 0; p < numPoints; ++p) { 8321 const PetscScalar *point = &a[p*bs]; 8322 8323 switch (dim) { 8324 case 2: 8325 for (c = cStart; c < cEnd; ++c) { 8326 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8327 switch (coneSize) { 8328 case 3: 8329 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8330 break; 8331 case 4: 8332 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8333 break; 8334 default: 8335 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8336 } 8337 if (cell >= 0) break; 8338 } 8339 break; 8340 case 3: 8341 for (c = cStart; c < cEnd; ++c) { 8342 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8343 switch (coneSize) { 8344 case 4: 8345 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8346 break; 8347 case 8: 8348 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8349 break; 8350 default: 8351 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8352 } 8353 if (cell >= 0) break; 8354 } 8355 break; 8356 default: 8357 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8358 } 8359 cells[p] = cell; 8360 } 8361 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8362 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8363 PetscFunctionReturn(0); 8364 } 8365 8366 /******************************** FEM Support **********************************/ 8367 8368 #undef __FUNCT__ 8369 #define __FUNCT__ "DMPlexVecGetClosure" 8370 /*@C 8371 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8372 8373 Not collective 8374 8375 Input Parameters: 8376 + dm - The DM 8377 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8378 . v - The local vector 8379 - point - The sieve point in the DM 8380 8381 Output Parameters: 8382 + csize - The number of values in the closure, or PETSC_NULL 8383 - values - The array of values, which is a borrowed array and should not be freed 8384 8385 Level: intermediate 8386 8387 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8388 @*/ 8389 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8390 { 8391 PetscScalar *array, *vArray; 8392 PetscInt *points = PETSC_NULL; 8393 PetscInt offsets[32]; 8394 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8395 PetscErrorCode ierr; 8396 8397 PetscFunctionBegin; 8398 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8399 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8400 if (!section) { 8401 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8402 } 8403 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8404 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8405 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8406 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8407 /* Compress out points not in the section */ 8408 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8409 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8410 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8411 points[q*2] = points[p]; 8412 points[q*2+1] = points[p+1]; 8413 ++q; 8414 } 8415 } 8416 numPoints = q; 8417 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8418 PetscInt dof, fdof; 8419 8420 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8421 for (f = 0; f < numFields; ++f) { 8422 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8423 offsets[f+1] += fdof; 8424 } 8425 size += dof; 8426 } 8427 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8428 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8429 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8430 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8431 for (p = 0; p < numPoints*2; p += 2) { 8432 PetscInt o = points[p+1]; 8433 PetscInt dof, off, d; 8434 PetscScalar *varr; 8435 8436 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8437 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8438 varr = &vArray[off]; 8439 if (numFields) { 8440 PetscInt fdof, foff, fcomp, f, c; 8441 8442 for (f = 0, foff = 0; f < numFields; ++f) { 8443 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8444 if (o >= 0) { 8445 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8446 array[offsets[f]] = varr[foff+d]; 8447 } 8448 } else { 8449 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8450 for (d = fdof/fcomp-1; d >= 0; --d) { 8451 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8452 array[offsets[f]] = varr[foff+d*fcomp+c]; 8453 } 8454 } 8455 } 8456 foff += fdof; 8457 } 8458 } else { 8459 if (o >= 0) { 8460 for (d = 0; d < dof; ++d, ++offsets[0]) { 8461 array[offsets[0]] = varr[d]; 8462 } 8463 } else { 8464 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8465 array[offsets[0]] = varr[d]; 8466 } 8467 } 8468 } 8469 } 8470 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8471 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8472 if (csize) *csize = size; 8473 *values = array; 8474 PetscFunctionReturn(0); 8475 } 8476 8477 #undef __FUNCT__ 8478 #define __FUNCT__ "DMPlexVecRestoreClosure" 8479 /*@C 8480 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8481 8482 Not collective 8483 8484 Input Parameters: 8485 + dm - The DM 8486 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8487 . v - The local vector 8488 . point - The sieve point in the DM 8489 . csize - The number of values in the closure, or PETSC_NULL 8490 - values - The array of values, which is a borrowed array and should not be freed 8491 8492 Level: intermediate 8493 8494 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8495 @*/ 8496 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8497 { 8498 PetscInt size = 0; 8499 PetscErrorCode ierr; 8500 8501 PetscFunctionBegin; 8502 /* Should work without recalculating size */ 8503 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8504 PetscFunctionReturn(0); 8505 } 8506 8507 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8508 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8509 8510 #undef __FUNCT__ 8511 #define __FUNCT__ "updatePoint_private" 8512 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8513 { 8514 PetscInt cdof; /* The number of constraints on this point */ 8515 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8516 PetscScalar *a; 8517 PetscInt off, cind = 0, k; 8518 PetscErrorCode ierr; 8519 8520 PetscFunctionBegin; 8521 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8522 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8523 a = &array[off]; 8524 if (!cdof || setBC) { 8525 if (orientation >= 0) { 8526 for (k = 0; k < dof; ++k) { 8527 fuse(&a[k], values[k]); 8528 } 8529 } else { 8530 for (k = 0; k < dof; ++k) { 8531 fuse(&a[k], values[dof-k-1]); 8532 } 8533 } 8534 } else { 8535 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8536 if (orientation >= 0) { 8537 for (k = 0; k < dof; ++k) { 8538 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8539 fuse(&a[k], values[k]); 8540 } 8541 } else { 8542 for (k = 0; k < dof; ++k) { 8543 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8544 fuse(&a[k], values[dof-k-1]); 8545 } 8546 } 8547 } 8548 PetscFunctionReturn(0); 8549 } 8550 8551 #undef __FUNCT__ 8552 #define __FUNCT__ "updatePointFields_private" 8553 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8554 { 8555 PetscScalar *a; 8556 PetscInt numFields, off, foff, f; 8557 PetscErrorCode ierr; 8558 8559 PetscFunctionBegin; 8560 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8561 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8562 a = &array[off]; 8563 for (f = 0, foff = 0; f < numFields; ++f) { 8564 PetscInt fdof, fcomp, fcdof; 8565 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8566 PetscInt cind = 0, k, c; 8567 8568 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8569 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8570 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8571 if (!fcdof || setBC) { 8572 if (orientation >= 0) { 8573 for (k = 0; k < fdof; ++k) { 8574 fuse(&a[foff+k], values[foffs[f]+k]); 8575 } 8576 } else { 8577 for (k = fdof/fcomp-1; k >= 0; --k) { 8578 for (c = 0; c < fcomp; ++c) { 8579 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8580 } 8581 } 8582 } 8583 } else { 8584 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8585 if (orientation >= 0) { 8586 for (k = 0; k < fdof; ++k) { 8587 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8588 fuse(&a[foff+k], values[foffs[f]+k]); 8589 } 8590 } else { 8591 for (k = fdof/fcomp-1; k >= 0; --k) { 8592 for (c = 0; c < fcomp; ++c) { 8593 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8594 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8595 } 8596 } 8597 } 8598 } 8599 foff += fdof; 8600 foffs[f] += fdof; 8601 } 8602 PetscFunctionReturn(0); 8603 } 8604 8605 #undef __FUNCT__ 8606 #define __FUNCT__ "DMPlexVecSetClosure" 8607 /*@C 8608 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8609 8610 Not collective 8611 8612 Input Parameters: 8613 + dm - The DM 8614 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8615 . v - The local vector 8616 . point - The sieve point in the DM 8617 . values - The array of values, which is a borrowed array and should not be freed 8618 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8619 8620 Level: intermediate 8621 8622 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8623 @*/ 8624 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8625 { 8626 PetscScalar *array; 8627 PetscInt *points = PETSC_NULL; 8628 PetscInt offsets[32]; 8629 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8630 PetscErrorCode ierr; 8631 8632 PetscFunctionBegin; 8633 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8634 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8635 if (!section) { 8636 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8637 } 8638 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8639 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8640 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8641 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8642 /* Compress out points not in the section */ 8643 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8644 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8645 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8646 points[q*2] = points[p]; 8647 points[q*2+1] = points[p+1]; 8648 ++q; 8649 } 8650 } 8651 numPoints = q; 8652 for (p = 0; p < numPoints*2; p += 2) { 8653 PetscInt fdof; 8654 8655 for (f = 0; f < numFields; ++f) { 8656 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8657 offsets[f+1] += fdof; 8658 } 8659 } 8660 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8661 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8662 if (numFields) { 8663 switch (mode) { 8664 case INSERT_VALUES: 8665 for (p = 0; p < numPoints*2; p += 2) { 8666 PetscInt o = points[p+1]; 8667 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8668 } break; 8669 case INSERT_ALL_VALUES: 8670 for (p = 0; p < numPoints*2; p += 2) { 8671 PetscInt o = points[p+1]; 8672 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8673 } break; 8674 case ADD_VALUES: 8675 for (p = 0; p < numPoints*2; p += 2) { 8676 PetscInt o = points[p+1]; 8677 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8678 } break; 8679 case ADD_ALL_VALUES: 8680 for (p = 0; p < numPoints*2; p += 2) { 8681 PetscInt o = points[p+1]; 8682 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8683 } break; 8684 default: 8685 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8686 } 8687 } else { 8688 switch (mode) { 8689 case INSERT_VALUES: 8690 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8691 PetscInt o = points[p+1]; 8692 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8693 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8694 } break; 8695 case INSERT_ALL_VALUES: 8696 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8697 PetscInt o = points[p+1]; 8698 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8699 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8700 } break; 8701 case ADD_VALUES: 8702 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8703 PetscInt o = points[p+1]; 8704 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8705 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8706 } break; 8707 case ADD_ALL_VALUES: 8708 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8709 PetscInt o = points[p+1]; 8710 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8711 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8712 } break; 8713 default: 8714 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8715 } 8716 } 8717 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8718 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8719 PetscFunctionReturn(0); 8720 } 8721 8722 #undef __FUNCT__ 8723 #define __FUNCT__ "DMPlexPrintMatSetValues" 8724 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8725 { 8726 PetscMPIInt rank; 8727 PetscInt i, j; 8728 PetscErrorCode ierr; 8729 8730 PetscFunctionBegin; 8731 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8732 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8733 for (i = 0; i < numIndices; i++) { 8734 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8735 } 8736 for (i = 0; i < numIndices; i++) { 8737 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8738 for (j = 0; j < numIndices; j++) { 8739 #if defined(PETSC_USE_COMPLEX) 8740 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8741 #else 8742 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8743 #endif 8744 } 8745 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8746 } 8747 PetscFunctionReturn(0); 8748 } 8749 8750 #undef __FUNCT__ 8751 #define __FUNCT__ "indicesPoint_private" 8752 /* . off - The global offset of this point */ 8753 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8754 { 8755 PetscInt cdof; /* The number of constraints on this point */ 8756 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8757 PetscInt cind = 0, k; 8758 PetscErrorCode ierr; 8759 8760 PetscFunctionBegin; 8761 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8762 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8763 if (!cdof || setBC) { 8764 if (orientation >= 0) { 8765 for (k = 0; k < dof; ++k) indices[k] = off+k; 8766 } else { 8767 for (k = 0; k < dof; ++k) indices[dof-k-1] = off+k; 8768 } 8769 } else { 8770 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8771 if (orientation >= 0) { 8772 for (k = 0; k < dof; ++k) { 8773 if ((cind < cdof) && (k == cdofs[cind])) { 8774 /* Insert check for returning constrained indices */ 8775 indices[k] = -(off+k+1); 8776 ++cind; 8777 } else { 8778 indices[k] = off+k-cind; 8779 } 8780 } 8781 } else { 8782 for (k = 0; k < dof; ++k) { 8783 if ((cind < cdof) && (k == cdofs[cind])) { 8784 /* Insert check for returning constrained indices */ 8785 indices[dof-k-1] = -(off+k+1); 8786 ++cind; 8787 } else { 8788 indices[dof-k-1] = off+k-cind; 8789 } 8790 } 8791 } 8792 } 8793 PetscFunctionReturn(0); 8794 } 8795 8796 #undef __FUNCT__ 8797 #define __FUNCT__ "indicesPointFields_private" 8798 /* . off - The global offset of this point */ 8799 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8800 { 8801 PetscInt numFields, foff, f; 8802 PetscErrorCode ierr; 8803 8804 PetscFunctionBegin; 8805 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8806 for (f = 0, foff = 0; f < numFields; ++f) { 8807 PetscInt fdof, fcomp, cfdof; 8808 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8809 PetscInt cind = 0, k, c; 8810 8811 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8812 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8813 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8814 if (!cfdof || setBC) { 8815 if (orientation >= 0) { 8816 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8817 } else { 8818 for (k = fdof/fcomp-1; k >= 0; --k) { 8819 for (c = 0; c < fcomp; ++c) { 8820 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8821 } 8822 } 8823 } 8824 } else { 8825 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8826 if (orientation >= 0) { 8827 for (k = 0; k < fdof; ++k) { 8828 if ((cind < cfdof) && (k == fcdofs[cind])) { 8829 indices[foffs[f]+k] = -(off+foff+k+1); 8830 ++cind; 8831 } else { 8832 indices[foffs[f]+k] = off+foff+k-cind; 8833 } 8834 } 8835 } else { 8836 for (k = fdof/fcomp-1; k >= 0; --k) { 8837 for (c = 0; c < fcomp; ++c) { 8838 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8839 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8840 ++cind; 8841 } else { 8842 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8843 } 8844 } 8845 } 8846 } 8847 } 8848 foff += fdof - cfdof; 8849 foffs[f] += fdof; 8850 } 8851 PetscFunctionReturn(0); 8852 } 8853 8854 #undef __FUNCT__ 8855 #define __FUNCT__ "DMPlexMatSetClosure" 8856 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8857 { 8858 DM_Plex *mesh = (DM_Plex*) dm->data; 8859 PetscInt *points = PETSC_NULL; 8860 PetscInt *indices; 8861 PetscInt offsets[32]; 8862 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8863 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8864 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8865 PetscErrorCode ierr; 8866 8867 PetscFunctionBegin; 8868 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8869 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8870 if (useDefault) { 8871 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8872 } 8873 if (useGlobalDefault) { 8874 if (useDefault) { 8875 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8876 } else { 8877 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8878 } 8879 } 8880 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8881 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8882 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8883 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8884 /* Compress out points not in the section */ 8885 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8886 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8887 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8888 points[q*2] = points[p]; 8889 points[q*2+1] = points[p+1]; 8890 ++q; 8891 } 8892 } 8893 numPoints = q; 8894 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8895 PetscInt fdof; 8896 8897 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8898 for (f = 0; f < numFields; ++f) { 8899 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8900 offsets[f+1] += fdof; 8901 } 8902 numIndices += dof; 8903 } 8904 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8905 8906 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8907 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8908 if (numFields) { 8909 for (p = 0; p < numPoints*2; p += 2) { 8910 PetscInt o = points[p+1]; 8911 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8912 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8913 } 8914 } else { 8915 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8916 PetscInt o = points[p+1]; 8917 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8918 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8919 } 8920 } 8921 if (useGlobalDefault && !useDefault) { 8922 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8923 } 8924 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8925 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8926 if (ierr) { 8927 PetscMPIInt rank; 8928 PetscErrorCode ierr2; 8929 8930 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8931 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8932 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8933 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8934 CHKERRQ(ierr); 8935 } 8936 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8937 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8938 PetscFunctionReturn(0); 8939 } 8940 8941 #undef __FUNCT__ 8942 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8943 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8944 { 8945 PetscSection coordSection; 8946 Vec coordinates; 8947 const PetscScalar *coords; 8948 const PetscInt dim = 2; 8949 PetscInt d, f; 8950 PetscErrorCode ierr; 8951 8952 PetscFunctionBegin; 8953 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8954 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8955 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8956 if (v0) { 8957 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8958 } 8959 if (J) { 8960 for (d = 0; d < dim; d++) { 8961 for (f = 0; f < dim; f++) { 8962 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8963 } 8964 } 8965 *detJ = J[0]*J[3] - J[1]*J[2]; 8966 #if 0 8967 if (detJ < 0.0) { 8968 const PetscReal xLength = mesh->periodicity[0]; 8969 8970 if (xLength != 0.0) { 8971 PetscReal v0x = coords[0*dim+0]; 8972 8973 if (v0x == 0.0) v0x = v0[0] = xLength; 8974 for (f = 0; f < dim; f++) { 8975 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8976 8977 J[0*dim+f] = 0.5*(px - v0x); 8978 } 8979 } 8980 detJ = J[0]*J[3] - J[1]*J[2]; 8981 } 8982 #endif 8983 PetscLogFlops(8.0 + 3.0); 8984 } 8985 if (invJ) { 8986 const PetscReal invDet = 1.0/(*detJ); 8987 8988 invJ[0] = invDet*J[3]; 8989 invJ[1] = -invDet*J[1]; 8990 invJ[2] = -invDet*J[2]; 8991 invJ[3] = invDet*J[0]; 8992 PetscLogFlops(5.0); 8993 } 8994 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8995 PetscFunctionReturn(0); 8996 } 8997 8998 #undef __FUNCT__ 8999 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9000 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9001 { 9002 PetscSection coordSection; 9003 Vec coordinates; 9004 const PetscScalar *coords; 9005 const PetscInt dim = 2; 9006 PetscInt d, f; 9007 PetscErrorCode ierr; 9008 9009 PetscFunctionBegin; 9010 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9011 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9012 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9013 if (v0) { 9014 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9015 } 9016 if (J) { 9017 for (d = 0; d < dim; d++) { 9018 for (f = 0; f < dim; f++) { 9019 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9020 } 9021 } 9022 *detJ = J[0]*J[3] - J[1]*J[2]; 9023 PetscLogFlops(8.0 + 3.0); 9024 } 9025 if (invJ) { 9026 const PetscReal invDet = 1.0/(*detJ); 9027 9028 invJ[0] = invDet*J[3]; 9029 invJ[1] = -invDet*J[1]; 9030 invJ[2] = -invDet*J[2]; 9031 invJ[3] = invDet*J[0]; 9032 PetscLogFlops(5.0); 9033 } 9034 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9035 PetscFunctionReturn(0); 9036 } 9037 9038 #undef __FUNCT__ 9039 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9040 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9041 { 9042 PetscSection coordSection; 9043 Vec coordinates; 9044 const PetscScalar *coords; 9045 const PetscInt dim = 3; 9046 PetscInt d, f; 9047 PetscErrorCode ierr; 9048 9049 PetscFunctionBegin; 9050 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9051 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9052 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9053 if (v0) { 9054 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9055 } 9056 if (J) { 9057 for (d = 0; d < dim; d++) { 9058 for (f = 0; f < dim; f++) { 9059 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9060 } 9061 } 9062 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9063 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9064 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9065 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9066 PetscLogFlops(18.0 + 12.0); 9067 } 9068 if (invJ) { 9069 const PetscReal invDet = 1.0/(*detJ); 9070 9071 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9072 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9073 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9074 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9075 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9076 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9077 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9078 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9079 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9080 PetscLogFlops(37.0); 9081 } 9082 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9083 PetscFunctionReturn(0); 9084 } 9085 9086 #undef __FUNCT__ 9087 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9088 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9089 { 9090 PetscSection coordSection; 9091 Vec coordinates; 9092 const PetscScalar *coords; 9093 const PetscInt dim = 3; 9094 PetscInt d; 9095 PetscErrorCode ierr; 9096 9097 PetscFunctionBegin; 9098 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9099 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9100 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9101 if (v0) { 9102 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 9103 } 9104 if (J) { 9105 for (d = 0; d < dim; d++) { 9106 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9107 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9108 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9109 } 9110 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9111 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9112 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9113 PetscLogFlops(18.0 + 12.0); 9114 } 9115 if (invJ) { 9116 const PetscReal invDet = -1.0/(*detJ); 9117 9118 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9119 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9120 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9121 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9122 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9123 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9124 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9125 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9126 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9127 PetscLogFlops(37.0); 9128 } 9129 *detJ *= 8.0; 9130 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9131 PetscFunctionReturn(0); 9132 } 9133 9134 #undef __FUNCT__ 9135 #define __FUNCT__ "DMPlexComputeCellGeometry" 9136 /*@C 9137 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9138 9139 Collective on DM 9140 9141 Input Arguments: 9142 + dm - the DM 9143 - cell - the cell 9144 9145 Output Arguments: 9146 + v0 - the translation part of this affine transform 9147 . J - the Jacobian of the transform to the reference element 9148 . invJ - the inverse of the Jacobian 9149 - detJ - the Jacobian determinant 9150 9151 Level: advanced 9152 9153 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9154 @*/ 9155 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9156 { 9157 PetscInt dim, coneSize; 9158 PetscErrorCode ierr; 9159 9160 PetscFunctionBegin; 9161 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9162 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9163 switch (dim) { 9164 case 2: 9165 switch (coneSize) { 9166 case 3: 9167 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9168 break; 9169 case 4: 9170 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9171 break; 9172 default: 9173 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9174 } 9175 break; 9176 case 3: 9177 switch (coneSize) { 9178 case 4: 9179 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9180 break; 9181 case 8: 9182 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9183 break; 9184 default: 9185 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9186 } 9187 break; 9188 default: 9189 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9190 } 9191 PetscFunctionReturn(0); 9192 } 9193 9194 #undef __FUNCT__ 9195 #define __FUNCT__ "DMPlexGetFaceOrientation" 9196 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9197 { 9198 MPI_Comm comm = ((PetscObject) dm)->comm; 9199 PetscBool posOrient = PETSC_FALSE; 9200 const PetscInt debug = 0; 9201 PetscInt cellDim, faceSize, f; 9202 PetscErrorCode ierr; 9203 9204 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9205 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9206 9207 if (cellDim == numCorners-1) { 9208 /* Simplices */ 9209 faceSize = numCorners-1; 9210 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9211 } else if (cellDim == 1 && numCorners == 3) { 9212 /* Quadratic line */ 9213 faceSize = 1; 9214 posOrient = PETSC_TRUE; 9215 } else if (cellDim == 2 && numCorners == 4) { 9216 /* Quads */ 9217 faceSize = 2; 9218 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9219 posOrient = PETSC_TRUE; 9220 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9221 posOrient = PETSC_TRUE; 9222 } else { 9223 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9224 posOrient = PETSC_FALSE; 9225 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9226 } 9227 } else if (cellDim == 2 && numCorners == 6) { 9228 /* Quadratic triangle (I hate this) */ 9229 /* Edges are determined by the first 2 vertices (corners of edges) */ 9230 const PetscInt faceSizeTri = 3; 9231 PetscInt sortedIndices[3], i, iFace; 9232 PetscBool found = PETSC_FALSE; 9233 PetscInt faceVerticesTriSorted[9] = { 9234 0, 3, 4, /* bottom */ 9235 1, 4, 5, /* right */ 9236 2, 3, 5, /* left */ 9237 }; 9238 PetscInt faceVerticesTri[9] = { 9239 0, 3, 4, /* bottom */ 9240 1, 4, 5, /* right */ 9241 2, 5, 3, /* left */ 9242 }; 9243 9244 faceSize = faceSizeTri; 9245 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9246 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9247 for (iFace = 0; iFace < 3; ++iFace) { 9248 const PetscInt ii = iFace*faceSizeTri; 9249 PetscInt fVertex, cVertex; 9250 9251 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9252 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9253 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9254 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9255 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9256 faceVertices[fVertex] = origVertices[cVertex]; 9257 break; 9258 } 9259 } 9260 } 9261 found = PETSC_TRUE; 9262 break; 9263 } 9264 } 9265 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9266 if (posOriented) *posOriented = PETSC_TRUE; 9267 PetscFunctionReturn(0); 9268 } else if (cellDim == 2 && numCorners == 9) { 9269 /* Quadratic quad (I hate this) */ 9270 /* Edges are determined by the first 2 vertices (corners of edges) */ 9271 const PetscInt faceSizeQuad = 3; 9272 PetscInt sortedIndices[3], i, iFace; 9273 PetscBool found = PETSC_FALSE; 9274 PetscInt faceVerticesQuadSorted[12] = { 9275 0, 1, 4, /* bottom */ 9276 1, 2, 5, /* right */ 9277 2, 3, 6, /* top */ 9278 0, 3, 7, /* left */ 9279 }; 9280 PetscInt faceVerticesQuad[12] = { 9281 0, 1, 4, /* bottom */ 9282 1, 2, 5, /* right */ 9283 2, 3, 6, /* top */ 9284 3, 0, 7, /* left */ 9285 }; 9286 9287 faceSize = faceSizeQuad; 9288 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9289 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9290 for (iFace = 0; iFace < 4; ++iFace) { 9291 const PetscInt ii = iFace*faceSizeQuad; 9292 PetscInt fVertex, cVertex; 9293 9294 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9295 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9296 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9297 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9298 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9299 faceVertices[fVertex] = origVertices[cVertex]; 9300 break; 9301 } 9302 } 9303 } 9304 found = PETSC_TRUE; 9305 break; 9306 } 9307 } 9308 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9309 if (posOriented) *posOriented = PETSC_TRUE; 9310 PetscFunctionReturn(0); 9311 } else if (cellDim == 3 && numCorners == 8) { 9312 /* Hexes 9313 A hex is two oriented quads with the normal of the first 9314 pointing up at the second. 9315 9316 7---6 9317 /| /| 9318 4---5 | 9319 | 3-|-2 9320 |/ |/ 9321 0---1 9322 9323 Faces are determined by the first 4 vertices (corners of faces) */ 9324 const PetscInt faceSizeHex = 4; 9325 PetscInt sortedIndices[4], i, iFace; 9326 PetscBool found = PETSC_FALSE; 9327 PetscInt faceVerticesHexSorted[24] = { 9328 0, 1, 2, 3, /* bottom */ 9329 4, 5, 6, 7, /* top */ 9330 0, 1, 4, 5, /* front */ 9331 1, 2, 5, 6, /* right */ 9332 2, 3, 6, 7, /* back */ 9333 0, 3, 4, 7, /* left */ 9334 }; 9335 PetscInt faceVerticesHex[24] = { 9336 3, 2, 1, 0, /* bottom */ 9337 4, 5, 6, 7, /* top */ 9338 0, 1, 5, 4, /* front */ 9339 1, 2, 6, 5, /* right */ 9340 2, 3, 7, 6, /* back */ 9341 3, 0, 4, 7, /* left */ 9342 }; 9343 9344 faceSize = faceSizeHex; 9345 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9346 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9347 for (iFace = 0; iFace < 6; ++iFace) { 9348 const PetscInt ii = iFace*faceSizeHex; 9349 PetscInt fVertex, cVertex; 9350 9351 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9352 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9353 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9354 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9355 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9356 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9357 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9358 faceVertices[fVertex] = origVertices[cVertex]; 9359 break; 9360 } 9361 } 9362 } 9363 found = PETSC_TRUE; 9364 break; 9365 } 9366 } 9367 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9368 if (posOriented) *posOriented = PETSC_TRUE; 9369 PetscFunctionReturn(0); 9370 } else if (cellDim == 3 && numCorners == 10) { 9371 /* Quadratic tet */ 9372 /* Faces are determined by the first 3 vertices (corners of faces) */ 9373 const PetscInt faceSizeTet = 6; 9374 PetscInt sortedIndices[6], i, iFace; 9375 PetscBool found = PETSC_FALSE; 9376 PetscInt faceVerticesTetSorted[24] = { 9377 0, 1, 2, 6, 7, 8, /* bottom */ 9378 0, 3, 4, 6, 7, 9, /* front */ 9379 1, 4, 5, 7, 8, 9, /* right */ 9380 2, 3, 5, 6, 8, 9, /* left */ 9381 }; 9382 PetscInt faceVerticesTet[24] = { 9383 0, 1, 2, 6, 7, 8, /* bottom */ 9384 0, 4, 3, 6, 7, 9, /* front */ 9385 1, 5, 4, 7, 8, 9, /* right */ 9386 2, 3, 5, 8, 6, 9, /* left */ 9387 }; 9388 9389 faceSize = faceSizeTet; 9390 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9391 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9392 for (iFace=0; iFace < 4; ++iFace) { 9393 const PetscInt ii = iFace*faceSizeTet; 9394 PetscInt fVertex, cVertex; 9395 9396 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9397 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9398 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9399 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9400 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9401 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9402 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9403 faceVertices[fVertex] = origVertices[cVertex]; 9404 break; 9405 } 9406 } 9407 } 9408 found = PETSC_TRUE; 9409 break; 9410 } 9411 } 9412 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9413 if (posOriented) *posOriented = PETSC_TRUE; 9414 PetscFunctionReturn(0); 9415 } else if (cellDim == 3 && numCorners == 27) { 9416 /* Quadratic hexes (I hate this) 9417 A hex is two oriented quads with the normal of the first 9418 pointing up at the second. 9419 9420 7---6 9421 /| /| 9422 4---5 | 9423 | 3-|-2 9424 |/ |/ 9425 0---1 9426 9427 Faces are determined by the first 4 vertices (corners of faces) */ 9428 const PetscInt faceSizeQuadHex = 9; 9429 PetscInt sortedIndices[9], i, iFace; 9430 PetscBool found = PETSC_FALSE; 9431 PetscInt faceVerticesQuadHexSorted[54] = { 9432 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9433 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9434 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9435 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9436 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9437 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9438 }; 9439 PetscInt faceVerticesQuadHex[54] = { 9440 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9441 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9442 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9443 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9444 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9445 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9446 }; 9447 9448 faceSize = faceSizeQuadHex; 9449 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9450 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9451 for (iFace = 0; iFace < 6; ++iFace) { 9452 const PetscInt ii = iFace*faceSizeQuadHex; 9453 PetscInt fVertex, cVertex; 9454 9455 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9456 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9457 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9458 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9459 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9460 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9461 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9462 faceVertices[fVertex] = origVertices[cVertex]; 9463 break; 9464 } 9465 } 9466 } 9467 found = PETSC_TRUE; 9468 break; 9469 } 9470 } 9471 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9472 if (posOriented) *posOriented = PETSC_TRUE; 9473 PetscFunctionReturn(0); 9474 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9475 if (!posOrient) { 9476 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9477 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize-1 - f]; 9478 } else { 9479 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9480 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f]; 9481 } 9482 if (posOriented) *posOriented = posOrient; 9483 PetscFunctionReturn(0); 9484 } 9485 9486 #undef __FUNCT__ 9487 #define __FUNCT__ "DMPlexGetOrientedFace" 9488 /* 9489 Given a cell and a face, as a set of vertices, 9490 return the oriented face, as a set of vertices, in faceVertices 9491 The orientation is such that the face normal points out of the cell 9492 */ 9493 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9494 { 9495 const PetscInt *cone = PETSC_NULL; 9496 PetscInt coneSize, v, f, v2; 9497 PetscInt oppositeVertex = -1; 9498 PetscErrorCode ierr; 9499 9500 PetscFunctionBegin; 9501 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9502 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9503 for (v = 0, v2 = 0; v < coneSize; ++v) { 9504 PetscBool found = PETSC_FALSE; 9505 9506 for (f = 0; f < faceSize; ++f) { 9507 if (face[f] == cone[v]) { 9508 found = PETSC_TRUE; break; 9509 } 9510 } 9511 if (found) { 9512 indices[v2] = v; 9513 origVertices[v2] = cone[v]; 9514 ++v2; 9515 } else { 9516 oppositeVertex = v; 9517 } 9518 } 9519 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9520 PetscFunctionReturn(0); 9521 } 9522 9523 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9524 { 9525 switch (i) { 9526 case 0: 9527 switch (j) { 9528 case 0: return 0; 9529 case 1: 9530 switch (k) { 9531 case 0: return 0; 9532 case 1: return 0; 9533 case 2: return 1; 9534 } 9535 case 2: 9536 switch (k) { 9537 case 0: return 0; 9538 case 1: return -1; 9539 case 2: return 0; 9540 } 9541 } 9542 case 1: 9543 switch (j) { 9544 case 0: 9545 switch (k) { 9546 case 0: return 0; 9547 case 1: return 0; 9548 case 2: return -1; 9549 } 9550 case 1: return 0; 9551 case 2: 9552 switch (k) { 9553 case 0: return 1; 9554 case 1: return 0; 9555 case 2: return 0; 9556 } 9557 } 9558 case 2: 9559 switch (j) { 9560 case 0: 9561 switch (k) { 9562 case 0: return 0; 9563 case 1: return 1; 9564 case 2: return 0; 9565 } 9566 case 1: 9567 switch (k) { 9568 case 0: return -1; 9569 case 1: return 0; 9570 case 2: return 0; 9571 } 9572 case 2: return 0; 9573 } 9574 } 9575 return 0; 9576 } 9577 9578 #undef __FUNCT__ 9579 #define __FUNCT__ "DMPlexCreateRigidBody" 9580 /*@C 9581 DMPlexCreateRigidBody - create rigid body modes from coordinates 9582 9583 Collective on DM 9584 9585 Input Arguments: 9586 + dm - the DM 9587 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9588 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9589 9590 Output Argument: 9591 . sp - the null space 9592 9593 Note: This is necessary to take account of Dirichlet conditions on the displacements 9594 9595 Level: advanced 9596 9597 .seealso: MatNullSpaceCreate() 9598 @*/ 9599 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9600 { 9601 MPI_Comm comm = ((PetscObject) dm)->comm; 9602 Vec coordinates, localMode, mode[6]; 9603 PetscSection coordSection; 9604 PetscScalar *coords; 9605 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9606 PetscErrorCode ierr; 9607 9608 PetscFunctionBegin; 9609 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9610 if (dim == 1) { 9611 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9612 PetscFunctionReturn(0); 9613 } 9614 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9615 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9616 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9617 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9618 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9619 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9620 m = (dim*(dim+1))/2; 9621 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9622 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9623 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9624 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9625 /* Assume P1 */ 9626 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9627 for (d = 0; d < dim; ++d) { 9628 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9629 9630 values[d] = 1.0; 9631 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9632 for (v = vStart; v < vEnd; ++v) { 9633 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9634 } 9635 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9636 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9637 } 9638 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9639 for (d = dim; d < dim*(dim+1)/2; ++d) { 9640 PetscInt i, j, k = dim > 2 ? d - dim : d; 9641 9642 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9643 for (v = vStart; v < vEnd; ++v) { 9644 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9645 PetscInt off; 9646 9647 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9648 for (i = 0; i < dim; ++i) { 9649 for (j = 0; j < dim; ++j) { 9650 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9651 } 9652 } 9653 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9654 } 9655 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9656 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9657 } 9658 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9659 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9660 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9661 /* Orthonormalize system */ 9662 for (i = dim; i < m; ++i) { 9663 PetscScalar dots[6]; 9664 9665 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9666 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9667 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9668 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9669 } 9670 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9671 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9672 PetscFunctionReturn(0); 9673 } 9674 9675 #undef __FUNCT__ 9676 #define __FUNCT__ "DMPlexGetHybridBounds" 9677 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9678 { 9679 DM_Plex *mesh = (DM_Plex*) dm->data; 9680 PetscInt dim; 9681 PetscErrorCode ierr; 9682 9683 PetscFunctionBegin; 9684 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9685 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9686 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9687 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9688 if (eMax) *eMax = mesh->hybridPointMax[1]; 9689 if (vMax) *vMax = mesh->hybridPointMax[0]; 9690 PetscFunctionReturn(0); 9691 } 9692 9693 #undef __FUNCT__ 9694 #define __FUNCT__ "DMPlexSetHybridBounds" 9695 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9696 { 9697 DM_Plex *mesh = (DM_Plex*) dm->data; 9698 PetscInt dim; 9699 PetscErrorCode ierr; 9700 9701 PetscFunctionBegin; 9702 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9703 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9704 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9705 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9706 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9707 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9708 PetscFunctionReturn(0); 9709 } 9710 9711 #undef __FUNCT__ 9712 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9713 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9714 { 9715 DM_Plex *mesh = (DM_Plex*) dm->data; 9716 9717 PetscFunctionBegin; 9718 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9719 PetscValidPointer(cellHeight, 2); 9720 *cellHeight = mesh->vtkCellHeight; 9721 PetscFunctionReturn(0); 9722 } 9723 9724 #undef __FUNCT__ 9725 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9726 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9727 { 9728 DM_Plex *mesh = (DM_Plex*) dm->data; 9729 9730 PetscFunctionBegin; 9731 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9732 mesh->vtkCellHeight = cellHeight; 9733 PetscFunctionReturn(0); 9734 } 9735 9736 #undef __FUNCT__ 9737 #define __FUNCT__ "DMPlexInsertFace_Private" 9738 /* 9739 DMPlexInsertFace_Private - Puts a face into the mesh 9740 9741 Not collective 9742 9743 Input Parameters: 9744 + dm - The DMPlex 9745 . numFaceVertex - The number of vertices in the face 9746 . faceVertices - The vertices in the face for dm 9747 . subfaceVertices - The vertices in the face for subdm 9748 . numCorners - The number of vertices in the cell 9749 . cell - A cell in dm containing the face 9750 . subcell - A cell in subdm containing the face 9751 . firstFace - First face in the mesh 9752 - newFacePoint - Next face in the mesh 9753 9754 Output Parameters: 9755 . newFacePoint - Contains next face point number on input, updated on output 9756 9757 Level: developer 9758 */ 9759 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) 9760 { 9761 MPI_Comm comm = ((PetscObject) dm)->comm; 9762 DM_Plex *submesh = (DM_Plex*) subdm->data; 9763 const PetscInt *faces; 9764 PetscInt numFaces, coneSize; 9765 PetscErrorCode ierr; 9766 9767 PetscFunctionBegin; 9768 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9769 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9770 #if 0 9771 /* Cannot use this because support() has not been constructed yet */ 9772 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9773 #else 9774 { 9775 PetscInt f; 9776 9777 numFaces = 0; 9778 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void**) &faces);CHKERRQ(ierr); 9779 for (f = firstFace; f < *newFacePoint; ++f) { 9780 PetscInt dof, off, d; 9781 9782 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9783 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9784 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9785 for (d = 0; d < dof; ++d) { 9786 const PetscInt p = submesh->cones[off+d]; 9787 PetscInt v; 9788 9789 for (v = 0; v < numFaceVertices; ++v) { 9790 if (subfaceVertices[v] == p) break; 9791 } 9792 if (v == numFaceVertices) break; 9793 } 9794 if (d == dof) { 9795 numFaces = 1; 9796 ((PetscInt*) faces)[0] = f; 9797 } 9798 } 9799 } 9800 #endif 9801 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 9802 else if (numFaces == 1) { 9803 /* Add the other cell neighbor for this face */ 9804 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 9805 } else { 9806 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 9807 PetscBool posOriented; 9808 9809 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9810 origVertices = &orientedVertices[numFaceVertices]; 9811 indices = &orientedVertices[numFaceVertices*2]; 9812 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 9813 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 9814 /* TODO: I know that routine should return a permutation, not the indices */ 9815 for (v = 0; v < numFaceVertices; ++v) { 9816 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 9817 for (ov = 0; ov < numFaceVertices; ++ov) { 9818 if (orientedVertices[ov] == vertex) { 9819 orientedSubVertices[ov] = subvertex; 9820 break; 9821 } 9822 } 9823 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 9824 } 9825 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 9826 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 9827 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9828 ++(*newFacePoint); 9829 } 9830 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9831 PetscFunctionReturn(0); 9832 } 9833 9834 #undef __FUNCT__ 9835 #define __FUNCT__ "DMPlexCreateSubmesh_Uninterpolated" 9836 static PetscErrorCode DMPlexCreateSubmesh_Uninterpolated(DM dm, const char label[], const char surfaceLabel[], DM subdm) 9837 { 9838 MPI_Comm comm = ((PetscObject) dm)->comm; 9839 PetscBool boundaryFaces = PETSC_FALSE; 9840 PetscSection coordSection, subCoordSection; 9841 Vec coordinates, subCoordinates; 9842 PetscScalar *coords, *subCoords; 9843 IS labelIS, subpointMap; 9844 const PetscInt *subVertices; 9845 PetscInt *subVerticesActive, *tmpPoints; 9846 PetscInt *subCells = PETSC_NULL; 9847 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 9848 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 9849 PetscInt dim; /* Right now, do not specify dimension */ 9850 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 9851 PetscErrorCode ierr; 9852 9853 PetscFunctionBegin; 9854 if (surfaceLabel) SETERRQ(comm, PETSC_ERR_SUP, "Yell at me to do this"); 9855 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9856 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9857 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9858 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 9859 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9860 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9861 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9862 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9863 subface = &face[maxConeSize]; 9864 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 9865 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 9866 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 9867 maxSubCells = numSubVertices; 9868 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 9869 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 9870 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 9871 for (v = 0; v < numSubVertices; ++v) { 9872 const PetscInt vertex = subVertices[v]; 9873 PetscInt *star = PETSC_NULL; 9874 PetscInt starSize, numCells = 0; 9875 9876 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9877 for (p = 0; p < starSize*2; p += 2) { 9878 const PetscInt point = star[p]; 9879 if ((point >= cStart) && (point < cEnd)) star[numCells++] = point; 9880 } 9881 numOldSubCells = numSubCells; 9882 for (c = 0; c < numCells; ++c) { 9883 const PetscInt cell = star[c]; 9884 PetscInt *closure = PETSC_NULL; 9885 PetscInt closureSize, numCorners = 0, faceSize = 0; 9886 PetscInt cellLoc; 9887 9888 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 9889 if (cellLoc >= 0) continue; 9890 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9891 for (p = 0; p < closureSize*2; p += 2) { 9892 const PetscInt point = closure[p]; 9893 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 9894 } 9895 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9896 for (corner = 0; corner < numCorners; ++corner) { 9897 const PetscInt cellVertex = closure[corner]; 9898 PetscInt subVertex; 9899 9900 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9901 if (subVertex >= 0) { /* contains submesh vertex */ 9902 for (i = 0; i < faceSize; ++i) { 9903 if (cellVertex == face[i]) break; 9904 } 9905 if (i == faceSize) { 9906 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9907 face[faceSize] = cellVertex; 9908 subface[faceSize] = subVertex; 9909 ++faceSize; 9910 } 9911 } 9912 } 9913 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9914 if (faceSize >= nFV) { 9915 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9916 if (numSubCells >= maxSubCells) { 9917 PetscInt *tmpCells; 9918 maxSubCells *= 2; 9919 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9920 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9921 ierr = PetscFree(subCells);CHKERRQ(ierr); 9922 9923 subCells = tmpCells; 9924 } 9925 /* TOOD: Maybe overestimate then squeeze out empty faces */ 9926 if (faceSize > nFV) { 9927 /* TODO: This is tricky. Maybe just add all faces */ 9928 numSubFaces++; 9929 } else { 9930 numSubFaces++; 9931 } 9932 for (f = 0; f < faceSize; ++f) subVerticesActive[subface[f]] = 1; 9933 subCells[numSubCells++] = cell; 9934 } 9935 } 9936 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9937 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9938 } 9939 /* Pick out active subvertices */ 9940 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9941 if (subVerticesActive[v]) { 9942 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9943 } 9944 } 9945 ierr = DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9946 /* Set cone sizes */ 9947 firstSubVertex = numSubCells; 9948 firstSubFace = numSubCells+numSubVerticesActive; 9949 newFacePoint = firstSubFace; 9950 for (c = 0; c < numSubCells; ++c) { 9951 ierr = DMPlexSetConeSize(subdm, c, 1);CHKERRQ(ierr); 9952 } 9953 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9954 ierr = DMPlexSetConeSize(subdm, f, nFV);CHKERRQ(ierr); 9955 } 9956 ierr = DMSetUp(subdm);CHKERRQ(ierr); 9957 /* Create face cones */ 9958 for (c = 0; c < numSubCells; ++c) { 9959 const PetscInt cell = subCells[c]; 9960 PetscInt *closure = PETSC_NULL; 9961 PetscInt closureSize, numCorners = 0, faceSize = 0; 9962 9963 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9964 for (p = 0; p < closureSize*2; p += 2) { 9965 const PetscInt point = closure[p]; 9966 if ((point >= vStart) && (point < vEnd)) closure[numCorners++] = point; 9967 } 9968 for (corner = 0; corner < numCorners; ++corner) { 9969 const PetscInt cellVertex = closure[corner]; 9970 PetscInt subVertex; 9971 9972 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9973 if (subVertex >= 0) { /* contains submesh vertex */ 9974 for (i = 0; i < faceSize; ++i) { 9975 if (cellVertex == face[i]) break; 9976 } 9977 if (i == faceSize) { 9978 face[faceSize] = cellVertex; 9979 subface[faceSize] = numSubCells+subVertex; 9980 ++faceSize; 9981 } 9982 } 9983 } 9984 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9985 if (faceSize >= nFV) { 9986 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9987 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 9988 /* We have to take all the faces, and discard those in the interior */ 9989 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 9990 #if 0 9991 /* This object just calls insert on each face that comes from subsets() */ 9992 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 9993 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9994 PointArray faceVec(face->begin(), face->end()); 9995 9996 subsets(faceVec, nFV, inserter); 9997 #endif 9998 ierr = DMPlexInsertFace_Private(dm, subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 9999 } 10000 } 10001 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 10002 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 10003 /* Build coordinates */ 10004 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10005 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10006 ierr = DMPlexGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 10007 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 10008 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 10009 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 10010 } 10011 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10012 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10013 ierr = VecCreate(comm, &subCoordinates);CHKERRQ(ierr); 10014 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10015 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10016 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10017 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10018 for (v = 0; v < numSubVerticesActive; ++v) { 10019 const PetscInt vertex = subVerticesActive[v]; 10020 const PetscInt subVertex = firstSubVertex+v; 10021 PetscInt dof, off, sdof, soff; 10022 10023 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10024 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10025 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10026 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10027 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10028 for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d]; 10029 } 10030 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10031 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10032 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 10033 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10034 10035 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 10036 /* Create map from submesh points to original mesh points */ 10037 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 10038 for (c = 0; c < numSubCells; ++c) tmpPoints[c] = subCells[c]; 10039 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) tmpPoints[v] = subVerticesActive[v-numSubCells]; 10040 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &subpointMap);CHKERRQ(ierr); 10041 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 10042 ierr = ISDestroy(&subpointMap);CHKERRQ(ierr); 10043 10044 ierr = PetscFree(subCells);CHKERRQ(ierr); 10045 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10046 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10047 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10048 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10049 PetscFunctionReturn(0); 10050 } 10051 10052 #undef __FUNCT__ 10053 #define __FUNCT__ "DMPlexCreateSubmesh_Interpolated" 10054 static PetscErrorCode DMPlexCreateSubmesh_Interpolated(DM dm, const char vertexLabel[], const char surfaceLabel[], DM subdm) 10055 { 10056 MPI_Comm comm = ((PetscObject) dm)->comm; 10057 const char *name = surfaceLabel ? surfaceLabel : "submesh_label"; 10058 DMLabel slabel; 10059 IS subvertexIS, subedgeIS, subfaceIS, subcellIS, subpointMap; 10060 const PetscInt *subVertices, *subEdges, *subFaces, *subCells; 10061 PetscInt *coneNew; 10062 PetscInt dim, numSubVerticesInitial, numSubVertices, firstSubVertex, v, numSubEdges = 0, firstSubEdge, e, numSubFaces = 0, firstSubFace, f, numSubCells; 10063 PetscInt vStart, vEnd, fStart, fEnd; 10064 PetscErrorCode ierr; 10065 10066 PetscFunctionBegin; 10067 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10068 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10069 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 10070 ierr = DMPlexCreateLabel(subdm, name);CHKERRQ(ierr); 10071 ierr = DMPlexGetLabel(subdm, name, &slabel);CHKERRQ(ierr); 10072 ierr = DMPlexGetStratumIS(dm, vertexLabel, 1, &subvertexIS);CHKERRQ(ierr); 10073 ierr = ISGetSize(subvertexIS, &numSubVerticesInitial);CHKERRQ(ierr); 10074 ierr = ISGetIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10075 for (v = 0; v < numSubVerticesInitial; ++v) { 10076 const PetscInt vertex = subVertices[v]; 10077 PetscInt *star = PETSC_NULL; 10078 PetscInt starSize, s, numFaces = 0, f; 10079 10080 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10081 for (s = 0; s < starSize*2; s += 2) { 10082 const PetscInt point = star[s]; 10083 if ((point >= fStart) && (point < fEnd)) { 10084 star[numFaces++] = point; 10085 } 10086 } 10087 for (f = 0; f < numFaces; ++f) { 10088 const PetscInt face = star[f]; 10089 PetscInt *closure = PETSC_NULL; 10090 PetscInt closureSize, c, numCorners = 0; 10091 PetscInt faceLoc, corner; 10092 10093 ierr = DMLabelGetValue(slabel, face, &faceLoc);CHKERRQ(ierr); 10094 if (faceLoc == dim-1) continue; 10095 if (faceLoc >= 0) SETERRQ2(comm, PETSC_ERR_PLIB, "Face %d has dimension %d in the surface label", face, faceLoc); 10096 ierr = DMPlexGetTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10097 for (c = 0; c < closureSize*2; c += 2) { 10098 const PetscInt point = closure[c]; 10099 if ((point >= vStart) && (point < vEnd)) { 10100 closure[numCorners++] = point; 10101 } 10102 } 10103 for (corner = 0; corner < numCorners; ++corner) { 10104 const PetscInt cellVertex = closure[corner]; 10105 PetscInt vertexLoc; 10106 10107 ierr = DMLabelGetValue(slabel, cellVertex, &vertexLoc);CHKERRQ(ierr); 10108 if (vertexLoc < 0) break; 10109 } 10110 ierr = DMPlexRestoreTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10111 if (corner == numCorners) { 10112 const PetscInt *support; 10113 PetscInt supportSize; 10114 10115 for (corner = 0; corner < numCorners; ++corner) {ierr = DMLabelSetValue(slabel, closure[corner], 0);CHKERRQ(ierr);} 10116 ierr = DMLabelSetValue(slabel, face, dim-1);CHKERRQ(ierr); 10117 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10118 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10119 for(s = 0; s < supportSize; ++s) { 10120 ierr = DMLabelSetValue(slabel, support[s], dim);CHKERRQ(ierr); 10121 } 10122 if (dim > 2) { 10123 const PetscInt *cone; 10124 PetscInt coneSize; 10125 10126 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10127 ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 10128 for(c = 0; c < coneSize; ++c) { 10129 ierr = DMLabelSetValue(slabel, cone[c], dim-2);CHKERRQ(ierr); 10130 } 10131 } 10132 } 10133 } 10134 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10135 } 10136 ierr = ISRestoreIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10137 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 10138 ierr = DMLabelGetStratumSize(slabel, dim, &numSubCells);CHKERRQ(ierr); 10139 ierr = DMLabelGetStratumSize(slabel, 0, &numSubVertices);CHKERRQ(ierr); 10140 if (dim > 1) {ierr = DMLabelGetStratumSize(slabel, dim-1, &numSubFaces);CHKERRQ(ierr);} 10141 if (dim > 2) {ierr = DMLabelGetStratumSize(slabel, 1, &numSubEdges);CHKERRQ(ierr);} 10142 ierr = DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubEdges+numSubVertices);CHKERRQ(ierr); 10143 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 10144 /* Set cone sizes */ 10145 firstSubVertex = numSubCells; 10146 firstSubFace = firstSubVertex + numSubVertices; 10147 firstSubEdge = firstSubFace + numSubFaces; 10148 ierr = DMLabelGetStratumIS(slabel, dim, &subcellIS);CHKERRQ(ierr); 10149 ierr = ISGetIndices(subcellIS, &subCells);CHKERRQ(ierr); 10150 ierr = DMLabelGetStratumIS(slabel, 0, &subvertexIS);CHKERRQ(ierr); 10151 ierr = ISGetIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10152 if (dim > 1) { 10153 ierr = DMLabelGetStratumIS(slabel, dim-1, &subfaceIS);CHKERRQ(ierr); 10154 ierr = ISGetIndices(subfaceIS, &subFaces);CHKERRQ(ierr); 10155 } 10156 if (dim > 2) { 10157 ierr = DMLabelGetStratumIS(slabel, 1, &subedgeIS);CHKERRQ(ierr); 10158 ierr = ISGetIndices(subedgeIS, &subEdges);CHKERRQ(ierr); 10159 } 10160 for (e = firstSubEdge; e < firstSubEdge+numSubEdges; ++e) { 10161 ierr = DMPlexSetConeSize(subdm, e, 2);CHKERRQ(ierr); 10162 } 10163 for (f = 0; f < numSubFaces; ++f) { 10164 const PetscInt face = subFaces[f]; 10165 const PetscInt subface = firstSubFace + f; 10166 const PetscInt *support; 10167 PetscInt coneSize, supportSize, subcell, s; 10168 10169 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10170 ierr = DMPlexSetConeSize(subdm, subface, coneSize);CHKERRQ(ierr); 10171 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10172 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10173 for(s = 0; s < supportSize; ++s) { 10174 ierr = PetscFindInt(support[s], numSubCells, subCells, &subcell);CHKERRQ(ierr); 10175 if (subcell < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Subcell %d not found in surface label", support[s]); 10176 /* ierr = DMPlexAddConeSize(subdm, subcell, 1);CHKERRQ(ierr); */ 10177 } 10178 } 10179 ierr = DMSetUp(subdm);CHKERRQ(ierr); 10180 /* Set cones */ 10181 for (e = 0; e < numSubEdges; ++e) { 10182 const PetscInt edge = subEdges[e]; 10183 const PetscInt subedge = firstSubEdge + e; 10184 const PetscInt *cone; 10185 PetscInt coneSize, c, coneNew[2], subv; 10186 10187 ierr = DMPlexGetConeSize(subdm, e, &coneSize);CHKERRQ(ierr); 10188 if (coneSize != 2) SETERRQ3(comm, PETSC_ERR_ARG_OUTOFRANGE, "Edge %d matching subedge %d had cone size %d != 2", edge, subedge, coneSize); 10189 ierr = DMPlexGetCone(subdm, e, &cone);CHKERRQ(ierr); 10190 for(c = 0; c < coneSize; ++c) { 10191 ierr = PetscFindInt(cone[c], numSubVertices, subVertices, &subv);CHKERRQ(ierr); 10192 if (subv < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Vertex %d has no matching subvertex", cone[v]); 10193 coneNew[c] = firstSubVertex + subv; 10194 } 10195 ierr = DMPlexSetCone(subdm, e, coneNew);CHKERRQ(ierr); 10196 } 10197 for (f = 0; f < numSubFaces; ++f) { 10198 const PetscInt face = subFaces[f]; 10199 const PetscInt subface = firstSubFace + f; 10200 const PetscInt *cone, *support; 10201 PetscInt coneSize, supportSize, subvertex, subcell, c, s; 10202 10203 ierr = DMPlexGetConeSize(dm, face, &coneSize);CHKERRQ(ierr); 10204 ierr = DMPlexGetCone(dm, face, &cone);CHKERRQ(ierr); 10205 for(c = 0; c < coneSize; ++c) { 10206 ierr = PetscFindInt(cone[c], numSubVertices, subVertices, &subvertex);CHKERRQ(ierr); 10207 if (subvertex < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Vertex %d has no matching subvertex", cone[v]); 10208 coneNew[c] = firstSubVertex + subvertex; 10209 } 10210 ierr = DMPlexSetCone(subdm, subface, coneNew);CHKERRQ(ierr); 10211 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 10212 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 10213 for(s = 0; s < supportSize; ++s) { 10214 ierr = PetscFindInt(support[s], numSubCells, subCells, &subcell);CHKERRQ(ierr); 10215 if (subcell < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Subcell %d not found in surface label", support[s]); 10216 /* ierr = DMPlexAddCone(subdm, subcell, 1);CHKERRQ(ierr); */ 10217 } 10218 } 10219 ierr = ISRestoreIndices(subcellIS, &subCells);CHKERRQ(ierr); 10220 ierr = ISDestroy(&subcellIS);CHKERRQ(ierr); 10221 ierr = ISRestoreIndices(subvertexIS, &subVertices);CHKERRQ(ierr); 10222 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 10223 if (dim > 1) { 10224 ierr = ISRestoreIndices(subfaceIS, &subFaces);CHKERRQ(ierr); 10225 ierr = ISDestroy(&subfaceIS);CHKERRQ(ierr); 10226 } 10227 if (dim > 2) { 10228 ierr = ISRestoreIndices(subedgeIS, &subEdges);CHKERRQ(ierr); 10229 ierr = ISDestroy(&subedgeIS);CHKERRQ(ierr); 10230 } 10231 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 10232 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 10233 /* Build coordinates */ 10234 { 10235 PetscSection coordSection, subCoordSection; 10236 Vec coordinates, subCoordinates; 10237 PetscScalar *coords, *subCoords; 10238 PetscInt coordSize; 10239 10240 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10241 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10242 ierr = DMPlexGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 10243 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVertices);CHKERRQ(ierr); 10244 for (v = 0; v < numSubVertices; ++v) { 10245 const PetscInt vertex = subVertices[v]; 10246 const PetscInt subVertex = firstSubVertex+v; 10247 PetscInt dof; 10248 10249 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10250 ierr = PetscSectionSetDof(subCoordSection, subVertex, dof);CHKERRQ(ierr); 10251 } 10252 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10253 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10254 ierr = VecCreate(comm, &subCoordinates);CHKERRQ(ierr); 10255 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10256 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10257 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10258 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10259 for (v = 0; v < numSubVertices; ++v) { 10260 const PetscInt vertex = subVertices[v]; 10261 const PetscInt subVertex = firstSubVertex+v; 10262 PetscInt dof, off, sdof, soff, d; 10263 10264 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10265 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10266 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10267 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10268 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10269 for (d = 0; d < dof; ++d) { 10270 subCoords[soff+d] = coords[off+d]; 10271 } 10272 } 10273 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10274 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10275 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 10276 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10277 } 10278 /* TODO: Create map from submesh points to original mesh points */ 10279 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 10280 PetscFunctionReturn(0); 10281 } 10282 10283 #undef __FUNCT__ 10284 #define __FUNCT__ "DMPlexCreateSubmesh" 10285 /* 10286 DMPlexCreateSubmesh - Extract a hypersurface from the mesh using vertices defined by a label 10287 10288 Input Parameters: 10289 + dm - The original mesh 10290 . vertexLabel - The DMLabel marking vertices contained in the surface 10291 - surfaceLabel - If not PETSC_NULL, create a new label with all the surface points labeled by dimension 10292 10293 Output Parameter: 10294 . subdm - The surface mesh 10295 10296 Level: developer 10297 10298 .seealso: DMPlexGetLabel(), DMLabelSetValue() 10299 */ 10300 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char vertexLabel[], const char surfaceLabel[], DM *subdm) 10301 { 10302 PetscInt dim, depth; 10303 PetscErrorCode ierr; 10304 10305 PetscFunctionBegin; 10306 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10307 PetscValidCharPointer(vertexLabel, 2); 10308 PetscValidPointer(subdm, 4); 10309 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10310 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 10311 ierr = DMCreate(((PetscObject) dm)->comm, subdm);CHKERRQ(ierr); 10312 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 10313 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 10314 if (depth == dim) { 10315 ierr = DMPlexCreateSubmesh_Interpolated(dm, vertexLabel, surfaceLabel, *subdm);CHKERRQ(ierr); 10316 } else { 10317 ierr = DMPlexCreateSubmesh_Uninterpolated(dm, vertexLabel, surfaceLabel, *subdm);CHKERRQ(ierr); 10318 } 10319 PetscFunctionReturn(0); 10320 } 10321 10322 #undef __FUNCT__ 10323 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10324 /* We can easily have a form that takes an IS instead */ 10325 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10326 { 10327 PetscSection section, globalSection; 10328 PetscInt *numbers, p; 10329 PetscErrorCode ierr; 10330 10331 PetscFunctionBegin; 10332 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10333 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10334 for (p = pStart; p < pEnd; ++p) { 10335 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10336 } 10337 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10338 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10339 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10340 for (p = pStart; p < pEnd; ++p) { 10341 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10342 } 10343 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10344 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10345 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10346 PetscFunctionReturn(0); 10347 } 10348 10349 #undef __FUNCT__ 10350 #define __FUNCT__ "DMPlexGetCellNumbering" 10351 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10352 { 10353 DM_Plex *mesh = (DM_Plex*) dm->data; 10354 PetscInt cellHeight, cStart, cEnd, cMax; 10355 PetscErrorCode ierr; 10356 10357 PetscFunctionBegin; 10358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10359 if (!mesh->globalCellNumbers) { 10360 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10361 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10362 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10363 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 10364 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10365 } 10366 *globalCellNumbers = mesh->globalCellNumbers; 10367 PetscFunctionReturn(0); 10368 } 10369 10370 #undef __FUNCT__ 10371 #define __FUNCT__ "DMPlexGetVertexNumbering" 10372 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10373 { 10374 DM_Plex *mesh = (DM_Plex*) dm->data; 10375 PetscInt vStart, vEnd, vMax; 10376 PetscErrorCode ierr; 10377 10378 PetscFunctionBegin; 10379 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10380 if (!mesh->globalVertexNumbers) { 10381 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10382 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10383 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 10384 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10385 } 10386 *globalVertexNumbers = mesh->globalVertexNumbers; 10387 PetscFunctionReturn(0); 10388 } 10389 10390 #undef __FUNCT__ 10391 #define __FUNCT__ "DMPlexGetSubpointMap" 10392 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 10393 { 10394 DM_Plex *mesh = (DM_Plex*) dm->data; 10395 10396 PetscFunctionBegin; 10397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10398 PetscValidPointer(subpointMap, 2); 10399 *subpointMap = mesh->subpointMap; 10400 PetscFunctionReturn(0); 10401 } 10402 10403 #undef __FUNCT__ 10404 #define __FUNCT__ "DMPlexSetSubpointMap" 10405 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10406 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 10407 { 10408 DM_Plex *mesh = (DM_Plex *) dm->data; 10409 PetscErrorCode ierr; 10410 10411 PetscFunctionBegin; 10412 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10413 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 10414 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 10415 mesh->subpointMap = subpointMap; 10416 ierr = PetscObjectReference((PetscObject) mesh->subpointMap);CHKERRQ(ierr); 10417 PetscFunctionReturn(0); 10418 } 10419 10420 #undef __FUNCT__ 10421 #define __FUNCT__ "DMPlexGetScale" 10422 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10423 { 10424 DM_Plex *mesh = (DM_Plex*) dm->data; 10425 10426 PetscFunctionBegin; 10427 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10428 PetscValidPointer(scale, 3); 10429 *scale = mesh->scale[unit]; 10430 PetscFunctionReturn(0); 10431 } 10432 10433 #undef __FUNCT__ 10434 #define __FUNCT__ "DMPlexSetScale" 10435 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10436 { 10437 DM_Plex *mesh = (DM_Plex*) dm->data; 10438 10439 PetscFunctionBegin; 10440 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10441 mesh->scale[unit] = scale; 10442 PetscFunctionReturn(0); 10443 } 10444 10445 10446 /******************************************************************************* 10447 This should be in a separate Discretization object, but I am not sure how to lay 10448 it out yet, so I am stuffing things here while I experiment. 10449 *******************************************************************************/ 10450 #undef __FUNCT__ 10451 #define __FUNCT__ "DMPlexSetFEMIntegration" 10452 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10453 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10454 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10455 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10456 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10457 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10458 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10459 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10460 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10461 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10462 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10463 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10464 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10465 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10466 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10467 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10468 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 10469 { 10470 DM_Plex *mesh = (DM_Plex*) dm->data; 10471 10472 PetscFunctionBegin; 10473 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10474 mesh->integrateResidualFEM = integrateResidualFEM; 10475 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10476 mesh->integrateJacobianFEM = integrateJacobianFEM; 10477 PetscFunctionReturn(0); 10478 } 10479 10480 #undef __FUNCT__ 10481 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10482 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10483 { 10484 Vec coordinates; 10485 PetscSection section, cSection; 10486 PetscInt dim, vStart, vEnd, v, c, d; 10487 PetscScalar *values, *cArray; 10488 PetscReal *coords; 10489 PetscErrorCode ierr; 10490 10491 PetscFunctionBegin; 10492 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10493 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10494 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10495 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10496 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10497 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10498 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10499 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10500 for (v = vStart; v < vEnd; ++v) { 10501 PetscInt dof, off; 10502 10503 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10504 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10505 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10506 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 10507 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10508 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10509 } 10510 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10511 /* Temporary, must be replaced by a projection on the finite element basis */ 10512 { 10513 PetscInt eStart = 0, eEnd = 0, e, depth; 10514 10515 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10516 --depth; 10517 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10518 for (e = eStart; e < eEnd; ++e) { 10519 const PetscInt *cone = PETSC_NULL; 10520 PetscInt coneSize, d; 10521 PetscScalar *coordsA, *coordsB; 10522 10523 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10524 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10525 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10526 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10527 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10528 for (d = 0; d < dim; ++d) { 10529 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10530 } 10531 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 10532 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10533 } 10534 } 10535 10536 ierr = PetscFree(coords);CHKERRQ(ierr); 10537 ierr = PetscFree(values);CHKERRQ(ierr); 10538 #if 0 10539 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10540 PetscReal detJ; 10541 10542 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10543 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10544 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10545 10546 for (PetscInt c = cStart; c < cEnd; ++c) { 10547 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10548 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10549 const int oSize = pV.getSize(); 10550 int v = 0; 10551 10552 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10553 for (PetscInt cl = 0; cl < oSize; ++cl) { 10554 const PetscInt fDim; 10555 10556 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10557 if (pointDim) { 10558 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10559 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10560 } 10561 } 10562 } 10563 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10564 pV.clear(); 10565 } 10566 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10567 ierr = PetscFree(values);CHKERRQ(ierr); 10568 #endif 10569 PetscFunctionReturn(0); 10570 } 10571 10572 #undef __FUNCT__ 10573 #define __FUNCT__ "DMPlexProjectFunction" 10574 /*@C 10575 DMPlexProjectFunction - This projects the given function into the function space provided. 10576 10577 Input Parameters: 10578 + dm - The DM 10579 . numComp - The number of components (functions) 10580 . funcs - The coordinate functions to evaluate 10581 - mode - The insertion mode for values 10582 10583 Output Parameter: 10584 . X - vector 10585 10586 Level: developer 10587 10588 Note: 10589 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10590 We will eventually fix it. 10591 10592 ,seealso: DMPlexComputeL2Diff() 10593 */ 10594 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10595 { 10596 Vec localX; 10597 PetscErrorCode ierr; 10598 10599 PetscFunctionBegin; 10600 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10601 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10602 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10603 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10604 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10605 PetscFunctionReturn(0); 10606 } 10607 10608 #undef __FUNCT__ 10609 #define __FUNCT__ "DMPlexComputeL2Diff" 10610 /*@C 10611 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10612 10613 Input Parameters: 10614 + dm - The DM 10615 . quad - The PetscQuadrature object for each field 10616 . funcs - The functions to evaluate for each field component 10617 - X - The coefficient vector u_h 10618 10619 Output Parameter: 10620 . diff - The diff ||u - u_h||_2 10621 10622 Level: developer 10623 10624 .seealso: DMPlexProjectFunction() 10625 */ 10626 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10627 { 10628 const PetscInt debug = 0; 10629 PetscSection section; 10630 Vec localX; 10631 PetscReal *coords, *v0, *J, *invJ, detJ; 10632 PetscReal localDiff = 0.0; 10633 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10634 PetscErrorCode ierr; 10635 10636 PetscFunctionBegin; 10637 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10638 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10639 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10640 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10641 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10642 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10643 for (field = 0; field < numFields; ++field) { 10644 numComponents += quad[field].numComponents; 10645 } 10646 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10647 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10648 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10649 for (c = cStart; c < cEnd; ++c) { 10650 const PetscScalar *x; 10651 PetscReal elemDiff = 0.0; 10652 10653 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10654 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10655 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10656 10657 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10658 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10659 const PetscReal *quadPoints = quad[field].quadPoints; 10660 const PetscReal *quadWeights = quad[field].quadWeights; 10661 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10662 const PetscInt numBasisComps = quad[field].numComponents; 10663 const PetscReal *basis = quad[field].basis; 10664 PetscInt q, d, e, fc, f; 10665 10666 if (debug) { 10667 char title[1024]; 10668 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10669 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10670 } 10671 for (q = 0; q < numQuadPoints; ++q) { 10672 for (d = 0; d < dim; d++) { 10673 coords[d] = v0[d]; 10674 for (e = 0; e < dim; e++) { 10675 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10676 } 10677 } 10678 for (fc = 0; fc < numBasisComps; ++fc) { 10679 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10680 PetscReal interpolant = 0.0; 10681 for (f = 0; f < numBasisFuncs; ++f) { 10682 const PetscInt fidx = f*numBasisComps+fc; 10683 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10684 } 10685 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10686 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10687 } 10688 } 10689 comp += numBasisComps; 10690 fieldOffset += numBasisFuncs*numBasisComps; 10691 } 10692 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10693 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10694 localDiff += elemDiff; 10695 } 10696 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10697 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10698 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10699 *diff = PetscSqrtReal(*diff); 10700 PetscFunctionReturn(0); 10701 } 10702 10703 #undef __FUNCT__ 10704 #define __FUNCT__ "DMPlexComputeResidualFEM" 10705 /*@ 10706 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10707 10708 Input Parameters: 10709 + dm - The mesh 10710 . X - Local input vector 10711 - user - The user context 10712 10713 Output Parameter: 10714 . F - Local output vector 10715 10716 Note: 10717 The second member of the user context must be an FEMContext. 10718 10719 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10720 like a GPU, or vectorize on a multicore machine. 10721 10722 .seealso: DMPlexComputeJacobianActionFEM() 10723 */ 10724 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10725 { 10726 DM_Plex *mesh = (DM_Plex*) dm->data; 10727 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10728 PetscQuadrature *quad = fem->quad; 10729 PetscSection section; 10730 PetscReal *v0, *J, *invJ, *detJ; 10731 PetscScalar *elemVec, *u; 10732 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10733 PetscInt cellDof = 0, numComponents = 0; 10734 PetscErrorCode ierr; 10735 10736 PetscFunctionBegin; 10737 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10738 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10739 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10740 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10741 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10742 numCells = cEnd - cStart; 10743 for (field = 0; field < numFields; ++field) { 10744 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10745 numComponents += quad[field].numComponents; 10746 } 10747 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10748 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10749 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); 10750 for (c = cStart; c < cEnd; ++c) { 10751 const PetscScalar *x; 10752 PetscInt i; 10753 10754 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10755 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10756 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10757 10758 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10759 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10760 } 10761 for (field = 0; field < numFields; ++field) { 10762 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10763 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10764 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10765 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10766 /* Conforming batches */ 10767 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10768 PetscInt numBlocks = 1; 10769 PetscInt batchSize = numBlocks * blockSize; 10770 PetscInt numBatches = numBatchesTmp; 10771 PetscInt numChunks = numCells / (numBatches*batchSize); 10772 /* Remainder */ 10773 PetscInt numRemainder = numCells % (numBatches * batchSize); 10774 PetscInt offset = numCells - numRemainder; 10775 10776 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10777 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10778 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10779 } 10780 for (c = cStart; c < cEnd; ++c) { 10781 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10782 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10783 } 10784 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10785 if (mesh->printFEM) { 10786 PetscMPIInt rank, numProcs; 10787 PetscInt p; 10788 10789 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10790 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10791 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10792 for (p = 0; p < numProcs; ++p) { 10793 if (p == rank) { 10794 Vec f; 10795 10796 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10797 ierr = VecCopy(F, f);CHKERRQ(ierr); 10798 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10799 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10800 ierr = VecDestroy(&f);CHKERRQ(ierr); 10801 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10802 } 10803 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10804 } 10805 } 10806 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10807 PetscFunctionReturn(0); 10808 } 10809 10810 #undef __FUNCT__ 10811 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10812 /*@C 10813 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10814 10815 Input Parameters: 10816 + dm - The mesh 10817 . J - The Jacobian shell matrix 10818 . X - Local input vector 10819 - user - The user context 10820 10821 Output Parameter: 10822 . F - Local output vector 10823 10824 Note: 10825 The second member of the user context must be an FEMContext. 10826 10827 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10828 like a GPU, or vectorize on a multicore machine. 10829 10830 .seealso: DMPlexComputeResidualFEM() 10831 */ 10832 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10833 { 10834 DM_Plex *mesh = (DM_Plex*) dm->data; 10835 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10836 PetscQuadrature *quad = fem->quad; 10837 PetscSection section; 10838 JacActionCtx *jctx; 10839 PetscReal *v0, *J, *invJ, *detJ; 10840 PetscScalar *elemVec, *u, *a; 10841 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10842 PetscInt cellDof = 0; 10843 PetscErrorCode ierr; 10844 10845 PetscFunctionBegin; 10846 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10847 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10848 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10849 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10850 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10851 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10852 numCells = cEnd - cStart; 10853 for (field = 0; field < numFields; ++field) { 10854 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10855 } 10856 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10857 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); 10858 for (c = cStart; c < cEnd; ++c) { 10859 const PetscScalar *x; 10860 PetscInt i; 10861 10862 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10863 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10864 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10865 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10866 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10867 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10868 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 10869 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10870 } 10871 for (field = 0; field < numFields; ++field) { 10872 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10873 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10874 /* Conforming batches */ 10875 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10876 PetscInt numBlocks = 1; 10877 PetscInt batchSize = numBlocks * blockSize; 10878 PetscInt numBatches = numBatchesTmp; 10879 PetscInt numChunks = numCells / (numBatches*batchSize); 10880 /* Remainder */ 10881 PetscInt numRemainder = numCells % (numBatches * batchSize); 10882 PetscInt offset = numCells - numRemainder; 10883 10884 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); 10885 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], 10886 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10887 } 10888 for (c = cStart; c < cEnd; ++c) { 10889 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10890 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10891 } 10892 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10893 if (mesh->printFEM) { 10894 PetscMPIInt rank, numProcs; 10895 PetscInt p; 10896 10897 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10898 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10899 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10900 for (p = 0; p < numProcs; ++p) { 10901 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10902 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10903 } 10904 } 10905 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10906 PetscFunctionReturn(0); 10907 } 10908 10909 #undef __FUNCT__ 10910 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10911 /*@ 10912 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10913 10914 Input Parameters: 10915 + dm - The mesh 10916 . X - Local input vector 10917 - user - The user context 10918 10919 Output Parameter: 10920 . Jac - Jacobian matrix 10921 10922 Note: 10923 The second member of the user context must be an FEMContext. 10924 10925 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10926 like a GPU, or vectorize on a multicore machine. 10927 10928 .seealso: FormFunctionLocal() 10929 */ 10930 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10931 { 10932 DM_Plex *mesh = (DM_Plex*) dm->data; 10933 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 10934 PetscQuadrature *quad = fem->quad; 10935 PetscSection section; 10936 PetscReal *v0, *J, *invJ, *detJ; 10937 PetscScalar *elemMat, *u; 10938 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10939 PetscInt cellDof = 0, numComponents = 0; 10940 PetscBool isShell; 10941 PetscErrorCode ierr; 10942 10943 PetscFunctionBegin; 10944 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10945 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10946 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10947 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10948 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10949 numCells = cEnd - cStart; 10950 for (field = 0; field < numFields; ++field) { 10951 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10952 numComponents += quad[field].numComponents; 10953 } 10954 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10955 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10956 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); 10957 for (c = cStart; c < cEnd; ++c) { 10958 const PetscScalar *x; 10959 PetscInt i; 10960 10961 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10962 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10963 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10964 10965 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 10966 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10967 } 10968 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10969 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10970 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10971 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10972 PetscInt fieldJ; 10973 10974 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10975 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10976 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10977 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10978 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10979 /* Conforming batches */ 10980 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10981 PetscInt numBlocks = 1; 10982 PetscInt batchSize = numBlocks * blockSize; 10983 PetscInt numBatches = numBatchesTmp; 10984 PetscInt numChunks = numCells / (numBatches*batchSize); 10985 /* Remainder */ 10986 PetscInt numRemainder = numCells % (numBatches * batchSize); 10987 PetscInt offset = numCells - numRemainder; 10988 10989 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10990 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10991 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10992 } 10993 } 10994 for (c = cStart; c < cEnd; ++c) { 10995 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10996 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10997 } 10998 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10999 11000 /* Assemble matrix, using the 2-step process: 11001 MatAssemblyBegin(), MatAssemblyEnd(). */ 11002 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11003 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11004 11005 if (mesh->printFEM) { 11006 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 11007 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 11008 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 11009 } 11010 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11011 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 11012 if (isShell) { 11013 JacActionCtx *jctx; 11014 11015 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 11016 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 11017 } 11018 *str = SAME_NONZERO_PATTERN; 11019 PetscFunctionReturn(0); 11020 } 11021 11022 11023 #undef __FUNCT__ 11024 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 11025 /*@C 11026 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 11027 the local section and an SF describing the section point overlap. 11028 11029 Input Parameters: 11030 + s - The PetscSection for the local field layout 11031 . sf - The SF describing parallel layout of the section points 11032 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 11033 . label - The label specifying the points 11034 - labelValue - The label stratum specifying the points 11035 11036 Output Parameter: 11037 . gsection - The PetscSection for the global field layout 11038 11039 Note: This gives negative sizes and offsets to points not owned by this process 11040 11041 Level: developer 11042 11043 .seealso: PetscSectionCreate() 11044 @*/ 11045 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 11046 { 11047 PetscInt *neg; 11048 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 11049 PetscErrorCode ierr; 11050 11051 PetscFunctionBegin; 11052 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 11053 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 11054 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 11055 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 11056 /* Mark ghost points with negative dof */ 11057 for (p = pStart; p < pEnd; ++p) { 11058 PetscInt value; 11059 11060 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 11061 if (value != labelValue) continue; 11062 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 11063 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 11064 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 11065 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 11066 neg[p-pStart] = -(dof+1); 11067 } 11068 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 11069 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 11070 if (nroots >= 0) { 11071 if (nroots > pEnd - pStart) { 11072 PetscInt *tmpDof; 11073 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11074 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 11075 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11076 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11077 for (p = pStart; p < pEnd; ++p) { 11078 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 11079 } 11080 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 11081 } else { 11082 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11083 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11084 } 11085 } 11086 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 11087 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11088 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 11089 11090 (*gsection)->atlasOff[p] = off; 11091 11092 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 11093 } 11094 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 11095 globalOff -= off; 11096 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11097 (*gsection)->atlasOff[p] += globalOff; 11098 11099 neg[p] = -((*gsection)->atlasOff[p]+1); 11100 } 11101 /* Put in negative offsets for ghost points */ 11102 if (nroots >= 0) { 11103 if (nroots > pEnd - pStart) { 11104 PetscInt *tmpOff; 11105 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11106 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 11107 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11108 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11109 for (p = pStart; p < pEnd; ++p) { 11110 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 11111 } 11112 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 11113 } else { 11114 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11115 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11116 } 11117 } 11118 ierr = PetscFree(neg);CHKERRQ(ierr); 11119 PetscFunctionReturn(0); 11120 } 11121