1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex *) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 if (markers) { 167 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 168 } 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for (c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = PETSC_NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm = ((PetscObject) dm)->comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 284 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 285 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 286 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 287 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 288 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 289 if (depth == 1) { 290 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 291 pEnd = pEnd - pStart; 292 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 293 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 294 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 295 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 296 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 297 pEnd = pEnd - pStart; 298 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 299 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 300 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 301 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 302 } else { 303 for (d = 0; d <= dim; d++) { 304 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 305 pEnd = pEnd - pStart; 306 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 307 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 308 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 309 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 310 } 311 } 312 ierr = PetscFree(sizes);CHKERRQ(ierr); 313 } 314 PetscFunctionReturn(0); 315 } 316 317 #undef __FUNCT__ 318 #define __FUNCT__ "DMView_Plex" 319 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 320 { 321 PetscBool iascii, isbinary; 322 PetscErrorCode ierr; 323 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 326 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 327 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 329 if (iascii) { 330 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 331 #if 0 332 } else if (isbinary) { 333 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 334 #endif 335 } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name); 336 PetscFunctionReturn(0); 337 } 338 339 #undef __FUNCT__ 340 #define __FUNCT__ "DMDestroy_Plex" 341 PetscErrorCode DMDestroy_Plex(DM dm) 342 { 343 DM_Plex *mesh = (DM_Plex *) dm->data; 344 DMLabel next = mesh->labels; 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 if (--mesh->refct > 0) {PetscFunctionReturn(0);} 349 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 350 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 352 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 353 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 355 while (next) { 356 DMLabel tmp = next->next; 357 358 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 359 next = tmp; 360 } 361 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 362 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 364 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 365 ierr = PetscFree(mesh);CHKERRQ(ierr); 366 PetscFunctionReturn(0); 367 } 368 369 #undef __FUNCT__ 370 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 371 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 372 { 373 const PetscInt *support = PETSC_NULL; 374 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 if (useClosure) { 379 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 380 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 381 for (s = 0; s < supportSize; ++s) { 382 const PetscInt *cone = PETSC_NULL; 383 PetscInt coneSize, c, q; 384 385 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 386 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 387 for (c = 0; c < coneSize; ++c) { 388 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 389 if (cone[c] == adj[q]) break; 390 } 391 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 392 } 393 } 394 } else { 395 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 396 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 397 for (s = 0; s < supportSize; ++s) { 398 const PetscInt *cone = PETSC_NULL; 399 PetscInt coneSize, c, q; 400 401 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 402 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 403 for (c = 0; c < coneSize; ++c) { 404 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 405 if (cone[c] == adj[q]) break; 406 } 407 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 408 } 409 } 410 } 411 *adjSize = numAdj; 412 PetscFunctionReturn(0); 413 } 414 415 #undef __FUNCT__ 416 #define __FUNCT__ "DMPlexGetAdjacency_Private" 417 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 418 { 419 const PetscInt *star = tmpClosure; 420 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 421 PetscErrorCode ierr; 422 423 PetscFunctionBegin; 424 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 425 for (s = 2; s < starSize*2; s += 2) { 426 const PetscInt *closure = PETSC_NULL; 427 PetscInt closureSize, c, q; 428 429 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 430 for (c = 0; c < closureSize*2; c += 2) { 431 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 432 if (closure[c] == adj[q]) break; 433 } 434 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 435 } 436 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 437 } 438 *adjSize = numAdj; 439 PetscFunctionReturn(0); 440 } 441 442 #undef __FUNCT__ 443 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 444 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 445 { 446 DM_Plex *mesh = (DM_Plex *) dm->data; 447 448 PetscFunctionBegin; 449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 450 mesh->preallocCenterDim = preallocCenterDim; 451 PetscFunctionReturn(0); 452 } 453 454 #undef __FUNCT__ 455 #define __FUNCT__ "DMPlexPreallocateOperator" 456 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 457 { 458 DM_Plex *mesh = (DM_Plex *) dm->data; 459 MPI_Comm comm = ((PetscObject) dm)->comm; 460 PetscSF sf, sfDof, sfAdj; 461 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 462 PetscInt nleaves, l, p; 463 const PetscInt *leaves; 464 const PetscSFNode *remotes; 465 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 466 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 467 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 468 PetscLayout rLayout; 469 PetscInt locRows, rStart, rEnd, r; 470 PetscMPIInt size; 471 PetscBool useClosure, debug = PETSC_FALSE; 472 PetscErrorCode ierr; 473 474 PetscFunctionBegin; 475 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 476 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 477 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 478 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 479 /* Create dof SF based on point SF */ 480 if (debug) { 481 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 487 } 488 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 489 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 490 if (debug) { 491 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 492 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 493 } 494 /* Create section for dof adjacency (dof ==> # adj dof) */ 495 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 496 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 497 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 498 if (mesh->preallocCenterDim == dim) { 499 useClosure = PETSC_FALSE; 500 } else if (mesh->preallocCenterDim == 0) { 501 useClosure = PETSC_TRUE; 502 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 503 504 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 505 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 510 /* Fill in the ghost dofs on the interface */ 511 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 512 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 513 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 514 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 515 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 516 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 517 518 /* 519 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 520 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 521 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 522 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 523 Create sfAdj connecting rootSectionAdj and leafSectionAdj 524 3. Visit unowned points on interface, write adjacencies to adj 525 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 526 4. Visit owned points on interface, write adjacencies to rootAdj 527 Remove redundancy in rootAdj 528 ** The last two traversals use transitive closure 529 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 530 Allocate memory addressed by sectionAdj (cols) 531 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 532 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 533 */ 534 535 for (l = 0; l < nleaves; ++l) { 536 PetscInt dof, off, d, q; 537 PetscInt p = leaves[l], numAdj = maxAdjSize; 538 539 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 540 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 541 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 542 for (q = 0; q < numAdj; ++q) { 543 PetscInt ndof, ncdof; 544 545 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 546 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 547 for (d = off; d < off+dof; ++d) { 548 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 549 } 550 } 551 } 552 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 553 if (debug) { 554 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 555 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 556 } 557 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 558 if (size > 1) { 559 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 560 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 561 } 562 if (debug) { 563 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 564 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 565 } 566 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 567 for (p = pStart; p < pEnd; ++p) { 568 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 569 570 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 571 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 572 if (!dof) continue; 573 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 574 if (adof <= 0) continue; 575 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 576 for (q = 0; q < numAdj; ++q) { 577 PetscInt ndof, ncdof; 578 579 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 580 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 581 for (d = off; d < off+dof; ++d) { 582 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 583 } 584 } 585 } 586 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 587 if (debug) { 588 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 589 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 590 } 591 /* Create adj SF based on dof SF */ 592 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 593 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 594 if (debug) { 595 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 596 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 597 } 598 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 599 /* Create leaf adjacency */ 600 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 601 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 602 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 603 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 604 for (l = 0; l < nleaves; ++l) { 605 PetscInt dof, off, d, q; 606 PetscInt p = leaves[l], numAdj = maxAdjSize; 607 608 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 609 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 610 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 611 for (d = off; d < off+dof; ++d) { 612 PetscInt aoff, i = 0; 613 614 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 615 for (q = 0; q < numAdj; ++q) { 616 PetscInt ndof, ncdof, ngoff, nd; 617 618 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 619 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 621 for (nd = 0; nd < ndof-ncdof; ++nd) { 622 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 623 ++i; 624 } 625 } 626 } 627 } 628 /* Debugging */ 629 if (debug) { 630 IS tmp; 631 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 632 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 633 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 634 } 635 /* Gather adjacenct indices to root */ 636 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 637 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 638 for (r = 0; r < adjSize; ++r) { 639 rootAdj[r] = -1; 640 } 641 if (size > 1) { 642 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 643 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 644 } 645 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 646 ierr = PetscFree(adj);CHKERRQ(ierr); 647 /* Debugging */ 648 if (debug) { 649 IS tmp; 650 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 651 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 652 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 653 } 654 /* Add in local adjacency indices for owned dofs on interface (roots) */ 655 for (p = pStart; p < pEnd; ++p) { 656 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 657 658 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 659 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 660 if (!dof) continue; 661 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 662 if (adof <= 0) continue; 663 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 664 for (d = off; d < off+dof; ++d) { 665 PetscInt adof, aoff, i; 666 667 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 668 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 669 i = adof-1; 670 for (q = 0; q < numAdj; ++q) { 671 PetscInt ndof, ncdof, ngoff, nd; 672 673 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 674 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 675 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 676 for (nd = 0; nd < ndof-ncdof; ++nd) { 677 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 678 --i; 679 } 680 } 681 } 682 } 683 /* Debugging */ 684 if (debug) { 685 IS tmp; 686 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 687 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 688 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 689 } 690 /* Compress indices */ 691 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 692 for (p = pStart; p < pEnd; ++p) { 693 PetscInt dof, cdof, off, d; 694 PetscInt adof, aoff; 695 696 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 697 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 698 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 699 if (!dof) continue; 700 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 701 if (adof <= 0) continue; 702 for (d = off; d < off+dof-cdof; ++d) { 703 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 704 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 705 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 706 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 707 } 708 } 709 /* Debugging */ 710 if (debug) { 711 IS tmp; 712 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 713 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 714 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 715 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 716 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 717 } 718 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 719 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 720 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 721 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 722 for (p = pStart; p < pEnd; ++p) { 723 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 724 PetscBool found = PETSC_TRUE; 725 726 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 727 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 728 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 729 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 730 for (d = 0; d < dof-cdof; ++d) { 731 PetscInt ldof, rdof; 732 733 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 734 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 735 if (ldof > 0) { 736 /* We do not own this point */ 737 } else if (rdof > 0) { 738 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 739 } else { 740 found = PETSC_FALSE; 741 } 742 } 743 if (found) continue; 744 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 745 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 746 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 747 for (q = 0; q < numAdj; ++q) { 748 PetscInt ndof, ncdof, noff; 749 750 /* Adjacent points may not be in the section chart */ 751 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 752 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 753 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 754 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 755 for (d = goff; d < goff+dof-cdof; ++d) { 756 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 757 } 758 } 759 } 760 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 761 if (debug) { 762 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 763 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 764 } 765 /* Get adjacent indices */ 766 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 767 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 768 for (p = pStart; p < pEnd; ++p) { 769 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 770 PetscBool found = PETSC_TRUE; 771 772 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 773 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 774 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 775 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 776 for (d = 0; d < dof-cdof; ++d) { 777 PetscInt ldof, rdof; 778 779 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 780 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 781 if (ldof > 0) { 782 /* We do not own this point */ 783 } else if (rdof > 0) { 784 PetscInt aoff, roff; 785 786 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 787 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 788 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 789 } else { 790 found = PETSC_FALSE; 791 } 792 } 793 if (found) continue; 794 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 795 for (d = goff; d < goff+dof-cdof; ++d) { 796 PetscInt adof, aoff, i = 0; 797 798 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 799 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 800 for (q = 0; q < numAdj; ++q) { 801 PetscInt ndof, ncdof, ngoff, nd; 802 const PetscInt *ncind; 803 804 /* Adjacent points may not be in the section chart */ 805 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 806 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 807 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 808 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 809 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 810 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 811 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 812 } 813 } 814 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 815 } 816 } 817 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 818 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 819 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 820 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 821 /* Debugging */ 822 if (debug) { 823 IS tmp; 824 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 825 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 826 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 827 } 828 /* Create allocation vectors from adjacency graph */ 829 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 830 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 831 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 832 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 833 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 834 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 835 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 836 /* Only loop over blocks of rows */ 837 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 838 for (r = rStart/bs; r < rEnd/bs; ++r) { 839 const PetscInt row = r*bs; 840 PetscInt numCols, cStart, c; 841 842 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 843 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 844 for (c = cStart; c < cStart+numCols; ++c) { 845 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 846 ++dnz[r-rStart]; 847 if (cols[c] >= row) {++dnzu[r-rStart];} 848 } else { 849 ++onz[r-rStart]; 850 if (cols[c] >= row) {++onzu[r-rStart];} 851 } 852 } 853 } 854 if (bs > 1) { 855 for (r = 0; r < locRows/bs; ++r) { 856 dnz[r] /= bs; 857 onz[r] /= bs; 858 dnzu[r] /= bs; 859 onzu[r] /= bs; 860 } 861 } 862 /* Set matrix pattern */ 863 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 864 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 865 /* Fill matrix with zeros */ 866 if (fillMatrix) { 867 PetscScalar *values; 868 PetscInt maxRowLen = 0; 869 870 for (r = rStart; r < rEnd; ++r) { 871 PetscInt len; 872 873 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 874 maxRowLen = PetscMax(maxRowLen, len); 875 } 876 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 877 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 878 for (r = rStart; r < rEnd; ++r) { 879 PetscInt numCols, cStart; 880 881 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 882 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 883 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 884 } 885 ierr = PetscFree(values);CHKERRQ(ierr); 886 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 887 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 888 } 889 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 890 ierr = PetscFree(cols);CHKERRQ(ierr); 891 PetscFunctionReturn(0); 892 } 893 894 #if 0 895 #undef __FUNCT__ 896 #define __FUNCT__ "DMPlexPreallocateOperator_2" 897 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 898 { 899 PetscErrorCode ierr; 900 PetscInt c,cStart,cEnd,pStart,pEnd; 901 PetscInt *tmpClosure,*tmpAdj,*visits; 902 903 PetscFunctionBegin; 904 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 905 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 906 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 907 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 908 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 909 npoints = pEnd - pStart; 910 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 911 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 912 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 913 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 914 for (c=cStart; c<cEnd; c++) { 915 PetscInt *support = tmpClosure; 916 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 917 for (p=0; p<supportSize; p++) { 918 lvisits[support[p]]++; 919 } 920 } 921 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 922 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 923 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 924 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 925 926 ierr = PetscSFGetRanks();CHKERRQ(ierr); 927 928 929 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 930 for (c=cStart; c<cEnd; c++) { 931 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 932 /* 933 Depth-first walk of transitive closure. 934 At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 935 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 936 */ 937 } 938 939 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 940 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 941 PetscFunctionReturn(0); 942 } 943 #endif 944 945 #undef __FUNCT__ 946 #define __FUNCT__ "DMCreateMatrix_Plex" 947 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 948 { 949 PetscSection section, sectionGlobal; 950 PetscInt bs = -1; 951 PetscInt localSize; 952 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 953 PetscErrorCode ierr; 954 955 PetscFunctionBegin; 956 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 957 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 958 #endif 959 if (!mtype) mtype = MATAIJ; 960 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 961 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 962 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 963 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 964 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 965 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 966 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 967 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 974 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 975 /* Check for symmetric storage */ 976 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 977 if (isSymmetric) { 978 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 979 } 980 if (!isShell) { 981 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 982 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal; 983 984 if (bs < 0) { 985 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 986 PetscInt pStart, pEnd, p, dof; 987 988 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 989 for (p = pStart; p < pEnd; ++p) { 990 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 991 if (dof) { 992 bs = dof; 993 break; 994 } 995 } 996 } else { 997 bs = 1; 998 } 999 /* Must have same blocksize on all procs (some might have no points) */ 1000 bsLocal = bs; 1001 ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1002 } 1003 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1004 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1005 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1006 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1007 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1008 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1009 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1010 } 1011 PetscFunctionReturn(0); 1012 } 1013 1014 #undef __FUNCT__ 1015 #define __FUNCT__ "DMPlexGetDimension" 1016 /*@ 1017 DMPlexGetDimension - Return the topological mesh dimension 1018 1019 Not collective 1020 1021 Input Parameter: 1022 . mesh - The DMPlex 1023 1024 Output Parameter: 1025 . dim - The topological mesh dimension 1026 1027 Level: beginner 1028 1029 .seealso: DMPlexCreate() 1030 @*/ 1031 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1032 { 1033 DM_Plex *mesh = (DM_Plex *) dm->data; 1034 1035 PetscFunctionBegin; 1036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1037 PetscValidPointer(dim, 2); 1038 *dim = mesh->dim; 1039 PetscFunctionReturn(0); 1040 } 1041 1042 #undef __FUNCT__ 1043 #define __FUNCT__ "DMPlexSetDimension" 1044 /*@ 1045 DMPlexSetDimension - Set the topological mesh dimension 1046 1047 Collective on mesh 1048 1049 Input Parameters: 1050 + mesh - The DMPlex 1051 - dim - The topological mesh dimension 1052 1053 Level: beginner 1054 1055 .seealso: DMPlexCreate() 1056 @*/ 1057 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1058 { 1059 DM_Plex *mesh = (DM_Plex *) dm->data; 1060 1061 PetscFunctionBegin; 1062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1063 PetscValidLogicalCollectiveInt(dm, dim, 2); 1064 mesh->dim = dim; 1065 mesh->preallocCenterDim = dim; 1066 PetscFunctionReturn(0); 1067 } 1068 1069 #undef __FUNCT__ 1070 #define __FUNCT__ "DMPlexGetChart" 1071 /*@ 1072 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1073 1074 Not collective 1075 1076 Input Parameter: 1077 . mesh - The DMPlex 1078 1079 Output Parameters: 1080 + pStart - The first mesh point 1081 - pEnd - The upper bound for mesh points 1082 1083 Level: beginner 1084 1085 .seealso: DMPlexCreate(), DMPlexSetChart() 1086 @*/ 1087 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1088 { 1089 DM_Plex *mesh = (DM_Plex *) dm->data; 1090 PetscErrorCode ierr; 1091 1092 PetscFunctionBegin; 1093 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1094 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1095 PetscFunctionReturn(0); 1096 } 1097 1098 #undef __FUNCT__ 1099 #define __FUNCT__ "DMPlexSetChart" 1100 /*@ 1101 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1102 1103 Not collective 1104 1105 Input Parameters: 1106 + mesh - The DMPlex 1107 . pStart - The first mesh point 1108 - pEnd - The upper bound for mesh points 1109 1110 Output Parameters: 1111 1112 Level: beginner 1113 1114 .seealso: DMPlexCreate(), DMPlexGetChart() 1115 @*/ 1116 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1117 { 1118 DM_Plex *mesh = (DM_Plex *) dm->data; 1119 PetscErrorCode ierr; 1120 1121 PetscFunctionBegin; 1122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1123 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1124 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1125 PetscFunctionReturn(0); 1126 } 1127 1128 #undef __FUNCT__ 1129 #define __FUNCT__ "DMPlexGetConeSize" 1130 /*@ 1131 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1132 1133 Not collective 1134 1135 Input Parameters: 1136 + mesh - The DMPlex 1137 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1138 1139 Output Parameter: 1140 . size - The cone size for point p 1141 1142 Level: beginner 1143 1144 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1145 @*/ 1146 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1147 { 1148 DM_Plex *mesh = (DM_Plex *) dm->data; 1149 PetscErrorCode ierr; 1150 1151 PetscFunctionBegin; 1152 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1153 PetscValidPointer(size, 3); 1154 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1155 PetscFunctionReturn(0); 1156 } 1157 1158 #undef __FUNCT__ 1159 #define __FUNCT__ "DMPlexSetConeSize" 1160 /*@ 1161 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1162 1163 Not collective 1164 1165 Input Parameters: 1166 + mesh - The DMPlex 1167 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1168 - size - The cone size for point p 1169 1170 Output Parameter: 1171 1172 Note: 1173 This should be called after DMPlexSetChart(). 1174 1175 Level: beginner 1176 1177 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1178 @*/ 1179 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1180 { 1181 DM_Plex *mesh = (DM_Plex *) dm->data; 1182 PetscErrorCode ierr; 1183 1184 PetscFunctionBegin; 1185 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1186 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1187 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1188 PetscFunctionReturn(0); 1189 } 1190 1191 #undef __FUNCT__ 1192 #define __FUNCT__ "DMPlexGetCone" 1193 /*@C 1194 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1195 1196 Not collective 1197 1198 Input Parameters: 1199 + mesh - The DMPlex 1200 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1201 1202 Output Parameter: 1203 . cone - An array of points which are on the in-edges for point p 1204 1205 Level: beginner 1206 1207 Note: 1208 This routine is not available in Fortran. 1209 1210 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1211 @*/ 1212 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1213 { 1214 DM_Plex *mesh = (DM_Plex *) dm->data; 1215 PetscInt off; 1216 PetscErrorCode ierr; 1217 1218 PetscFunctionBegin; 1219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1220 PetscValidPointer(cone, 3); 1221 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1222 *cone = &mesh->cones[off]; 1223 PetscFunctionReturn(0); 1224 } 1225 1226 #undef __FUNCT__ 1227 #define __FUNCT__ "DMPlexSetCone" 1228 /*@ 1229 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1230 1231 Not collective 1232 1233 Input Parameters: 1234 + mesh - The DMPlex 1235 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1236 - cone - An array of points which are on the in-edges for point p 1237 1238 Output Parameter: 1239 1240 Note: 1241 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1242 1243 Level: beginner 1244 1245 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1246 @*/ 1247 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1248 { 1249 DM_Plex *mesh = (DM_Plex *) dm->data; 1250 PetscInt pStart, pEnd; 1251 PetscInt dof, off, c; 1252 PetscErrorCode ierr; 1253 1254 PetscFunctionBegin; 1255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1256 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1257 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1258 if (dof) PetscValidPointer(cone, 3); 1259 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1260 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1261 for (c = 0; c < dof; ++c) { 1262 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1263 mesh->cones[off+c] = cone[c]; 1264 } 1265 PetscFunctionReturn(0); 1266 } 1267 1268 #undef __FUNCT__ 1269 #define __FUNCT__ "DMPlexGetConeOrientation" 1270 /*@C 1271 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1272 1273 Not collective 1274 1275 Input Parameters: 1276 + mesh - The DMPlex 1277 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1278 1279 Output Parameter: 1280 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1281 integer giving the prescription for cone traversal. If it is negative, the cone is 1282 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1283 the index of the cone point on which to start. 1284 1285 Level: beginner 1286 1287 Note: 1288 This routine is not available in Fortran. 1289 1290 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1291 @*/ 1292 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1293 { 1294 DM_Plex *mesh = (DM_Plex *) dm->data; 1295 PetscInt off; 1296 PetscErrorCode ierr; 1297 1298 PetscFunctionBegin; 1299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1300 #if defined(PETSC_USE_DEBUG) 1301 { 1302 PetscInt dof; 1303 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1304 if (dof) PetscValidPointer(coneOrientation, 3); 1305 } 1306 #endif 1307 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1308 *coneOrientation = &mesh->coneOrientations[off]; 1309 PetscFunctionReturn(0); 1310 } 1311 1312 #undef __FUNCT__ 1313 #define __FUNCT__ "DMPlexSetConeOrientation" 1314 /*@ 1315 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1316 1317 Not collective 1318 1319 Input Parameters: 1320 + mesh - The DMPlex 1321 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1322 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1323 integer giving the prescription for cone traversal. If it is negative, the cone is 1324 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1325 the index of the cone point on which to start. 1326 1327 Output Parameter: 1328 1329 Note: 1330 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1331 1332 Level: beginner 1333 1334 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1335 @*/ 1336 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1337 { 1338 DM_Plex *mesh = (DM_Plex *) dm->data; 1339 PetscInt pStart, pEnd; 1340 PetscInt dof, off, c; 1341 PetscErrorCode ierr; 1342 1343 PetscFunctionBegin; 1344 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1345 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1346 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1347 if (dof) PetscValidPointer(coneOrientation, 3); 1348 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1349 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1350 for (c = 0; c < dof; ++c) { 1351 PetscInt cdof, o = coneOrientation[c]; 1352 1353 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1354 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1355 mesh->coneOrientations[off+c] = o; 1356 } 1357 PetscFunctionReturn(0); 1358 } 1359 1360 #undef __FUNCT__ 1361 #define __FUNCT__ "DMPlexInsertCone" 1362 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1363 { 1364 DM_Plex *mesh = (DM_Plex *) dm->data; 1365 PetscInt pStart, pEnd; 1366 PetscInt dof, off; 1367 PetscErrorCode ierr; 1368 1369 PetscFunctionBegin; 1370 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1371 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1372 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1373 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1374 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1375 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1376 if (conePos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1377 mesh->cones[off+conePos] = conePoint; 1378 PetscFunctionReturn(0); 1379 } 1380 1381 #undef __FUNCT__ 1382 #define __FUNCT__ "DMPlexGetSupportSize" 1383 /*@ 1384 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1385 1386 Not collective 1387 1388 Input Parameters: 1389 + mesh - The DMPlex 1390 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1391 1392 Output Parameter: 1393 . size - The support size for point p 1394 1395 Level: beginner 1396 1397 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1398 @*/ 1399 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1400 { 1401 DM_Plex *mesh = (DM_Plex *) dm->data; 1402 PetscErrorCode ierr; 1403 1404 PetscFunctionBegin; 1405 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1406 PetscValidPointer(size, 3); 1407 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1408 PetscFunctionReturn(0); 1409 } 1410 1411 #undef __FUNCT__ 1412 #define __FUNCT__ "DMPlexSetSupportSize" 1413 /*@ 1414 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1415 1416 Not collective 1417 1418 Input Parameters: 1419 + mesh - The DMPlex 1420 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1421 - size - The support size for point p 1422 1423 Output Parameter: 1424 1425 Note: 1426 This should be called after DMPlexSetChart(). 1427 1428 Level: beginner 1429 1430 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1431 @*/ 1432 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1433 { 1434 DM_Plex *mesh = (DM_Plex *) dm->data; 1435 PetscErrorCode ierr; 1436 1437 PetscFunctionBegin; 1438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1439 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1440 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1441 PetscFunctionReturn(0); 1442 } 1443 1444 #undef __FUNCT__ 1445 #define __FUNCT__ "DMPlexGetSupport" 1446 /*@C 1447 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1448 1449 Not collective 1450 1451 Input Parameters: 1452 + mesh - The DMPlex 1453 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1454 1455 Output Parameter: 1456 . support - An array of points which are on the out-edges for point p 1457 1458 Level: beginner 1459 1460 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1461 @*/ 1462 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1463 { 1464 DM_Plex *mesh = (DM_Plex *) dm->data; 1465 PetscInt off; 1466 PetscErrorCode ierr; 1467 1468 PetscFunctionBegin; 1469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1470 PetscValidPointer(support, 3); 1471 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1472 *support = &mesh->supports[off]; 1473 PetscFunctionReturn(0); 1474 } 1475 1476 #undef __FUNCT__ 1477 #define __FUNCT__ "DMPlexSetSupport" 1478 /*@ 1479 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1480 1481 Not collective 1482 1483 Input Parameters: 1484 + mesh - The DMPlex 1485 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1486 - support - An array of points which are on the in-edges for point p 1487 1488 Output Parameter: 1489 1490 Note: 1491 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1492 1493 Level: beginner 1494 1495 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1496 @*/ 1497 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1498 { 1499 DM_Plex *mesh = (DM_Plex *) dm->data; 1500 PetscInt pStart, pEnd; 1501 PetscInt dof, off, c; 1502 PetscErrorCode ierr; 1503 1504 PetscFunctionBegin; 1505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1506 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1507 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1508 if (dof) PetscValidPointer(support, 3); 1509 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1510 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1511 for (c = 0; c < dof; ++c) { 1512 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1513 mesh->supports[off+c] = support[c]; 1514 } 1515 PetscFunctionReturn(0); 1516 } 1517 1518 #undef __FUNCT__ 1519 #define __FUNCT__ "DMPlexInsertSupport" 1520 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1521 { 1522 DM_Plex *mesh = (DM_Plex *) dm->data; 1523 PetscInt pStart, pEnd; 1524 PetscInt dof, off; 1525 PetscErrorCode ierr; 1526 1527 PetscFunctionBegin; 1528 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1529 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1530 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1531 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1532 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1533 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1534 if (supportPos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1535 mesh->supports[off+supportPos] = supportPoint; 1536 PetscFunctionReturn(0); 1537 } 1538 1539 #undef __FUNCT__ 1540 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1541 /*@C 1542 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1543 1544 Not collective 1545 1546 Input Parameters: 1547 + mesh - The DMPlex 1548 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1549 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1550 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1551 1552 Output Parameters: 1553 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1554 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1555 1556 Note: 1557 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1558 1559 Level: beginner 1560 1561 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1562 @*/ 1563 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1564 { 1565 DM_Plex *mesh = (DM_Plex *) dm->data; 1566 PetscInt *closure, *fifo; 1567 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1568 PetscInt tmpSize, t; 1569 PetscInt depth = 0, maxSize; 1570 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1571 PetscErrorCode ierr; 1572 1573 PetscFunctionBegin; 1574 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1575 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1576 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1577 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1578 if (*points) { 1579 closure = *points; 1580 } else { 1581 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1582 } 1583 closure[0] = p; closure[1] = 0; 1584 /* This is only 1-level */ 1585 if (useCone) { 1586 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1587 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1588 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1589 } else { 1590 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1591 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1592 } 1593 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1594 const PetscInt cp = tmp[t]; 1595 const PetscInt co = tmpO ? tmpO[t] : 0; 1596 1597 closure[closureSize] = cp; 1598 closure[closureSize+1] = co; 1599 fifo[fifoSize] = cp; 1600 fifo[fifoSize+1] = co; 1601 } 1602 while (fifoSize - fifoStart) { 1603 const PetscInt q = fifo[fifoStart]; 1604 const PetscInt o = fifo[fifoStart+1]; 1605 const PetscInt rev = o >= 0 ? 0 : 1; 1606 const PetscInt off = rev ? -(o+1) : o; 1607 1608 if (useCone) { 1609 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1610 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1611 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1612 } else { 1613 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1614 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1615 tmpO = PETSC_NULL; 1616 } 1617 for (t = 0; t < tmpSize; ++t) { 1618 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1619 const PetscInt cp = tmp[i]; 1620 /* Must propogate orientation */ 1621 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1622 PetscInt c; 1623 1624 /* Check for duplicate */ 1625 for (c = 0; c < closureSize; c += 2) { 1626 if (closure[c] == cp) break; 1627 } 1628 if (c == closureSize) { 1629 closure[closureSize] = cp; 1630 closure[closureSize+1] = co; 1631 fifo[fifoSize] = cp; 1632 fifo[fifoSize+1] = co; 1633 closureSize += 2; 1634 fifoSize += 2; 1635 } 1636 } 1637 fifoStart += 2; 1638 } 1639 if (numPoints) *numPoints = closureSize/2; 1640 if (points) *points = closure; 1641 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1642 PetscFunctionReturn(0); 1643 } 1644 1645 #undef __FUNCT__ 1646 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1647 /*@C 1648 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1649 1650 Not collective 1651 1652 Input Parameters: 1653 + mesh - The DMPlex 1654 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1655 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1656 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1657 1658 Output Parameters: 1659 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1660 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1661 1662 Note: 1663 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1664 1665 Level: beginner 1666 1667 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1668 @*/ 1669 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1670 { 1671 PetscErrorCode ierr; 1672 1673 PetscFunctionBegin; 1674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1675 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1676 PetscFunctionReturn(0); 1677 } 1678 1679 #undef __FUNCT__ 1680 #define __FUNCT__ "DMPlexGetFaces" 1681 /* 1682 DMPlexGetFaces - 1683 1684 Note: This will only work for cell-vertex meshes. 1685 */ 1686 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1687 { 1688 DM_Plex *mesh = (DM_Plex *) dm->data; 1689 const PetscInt *cone = PETSC_NULL; 1690 PetscInt depth = 0, dim, coneSize; 1691 PetscErrorCode ierr; 1692 1693 PetscFunctionBegin; 1694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1695 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1696 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1697 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1698 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1699 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1700 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1701 switch (dim) { 1702 case 2: 1703 switch (coneSize) { 1704 case 3: 1705 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1706 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1707 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1708 *numFaces = 3; 1709 *faceSize = 2; 1710 *faces = mesh->facesTmp; 1711 break; 1712 case 4: 1713 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1714 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1715 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1716 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1717 *numFaces = 4; 1718 *faceSize = 2; 1719 *faces = mesh->facesTmp; 1720 break; 1721 default: 1722 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1723 } 1724 break; 1725 case 3: 1726 switch (coneSize) { 1727 case 3: 1728 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1729 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1730 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1731 *numFaces = 3; 1732 *faceSize = 2; 1733 *faces = mesh->facesTmp; 1734 break; 1735 case 4: 1736 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1737 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1738 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1739 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1740 *numFaces = 4; 1741 *faceSize = 3; 1742 *faces = mesh->facesTmp; 1743 break; 1744 default: 1745 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1746 } 1747 break; 1748 default: 1749 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1750 } 1751 PetscFunctionReturn(0); 1752 } 1753 1754 #undef __FUNCT__ 1755 #define __FUNCT__ "DMPlexGetMaxSizes" 1756 /*@ 1757 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1758 1759 Not collective 1760 1761 Input Parameter: 1762 . mesh - The DMPlex 1763 1764 Output Parameters: 1765 + maxConeSize - The maximum number of in-edges 1766 - maxSupportSize - The maximum number of out-edges 1767 1768 Level: beginner 1769 1770 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1771 @*/ 1772 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1773 { 1774 DM_Plex *mesh = (DM_Plex *) dm->data; 1775 1776 PetscFunctionBegin; 1777 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1778 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1779 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1780 PetscFunctionReturn(0); 1781 } 1782 1783 #undef __FUNCT__ 1784 #define __FUNCT__ "DMSetUp_Plex" 1785 PetscErrorCode DMSetUp_Plex(DM dm) 1786 { 1787 DM_Plex *mesh = (DM_Plex *) dm->data; 1788 PetscInt size; 1789 PetscErrorCode ierr; 1790 1791 PetscFunctionBegin; 1792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1793 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1794 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1795 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1796 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1797 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1798 if (mesh->maxSupportSize) { 1799 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1800 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1801 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1802 } 1803 PetscFunctionReturn(0); 1804 } 1805 1806 #undef __FUNCT__ 1807 #define __FUNCT__ "DMCreateSubDM_Plex" 1808 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1809 { 1810 PetscSection section, sectionGlobal; 1811 PetscInt *subIndices; 1812 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1813 PetscErrorCode ierr; 1814 1815 PetscFunctionBegin; 1816 if (!numFields) PetscFunctionReturn(0); 1817 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1818 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1819 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1820 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1821 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1822 if (numFields > nF) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1823 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1824 for (p = pStart; p < pEnd; ++p) { 1825 PetscInt gdof; 1826 1827 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1828 if (gdof > 0) { 1829 for (f = 0; f < numFields; ++f) { 1830 PetscInt fdof, fcdof; 1831 1832 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1833 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1834 subSize += fdof-fcdof; 1835 } 1836 } 1837 } 1838 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1839 for (p = pStart; p < pEnd; ++p) { 1840 PetscInt gdof, goff; 1841 1842 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1843 if (gdof > 0) { 1844 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1845 for (f = 0; f < numFields; ++f) { 1846 PetscInt fdof, fcdof, fc, f2, poff = 0; 1847 1848 /* Can get rid of this loop by storing field information in the global section */ 1849 for (f2 = 0; f2 < fields[f]; ++f2) { 1850 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1851 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1852 poff += fdof-fcdof; 1853 } 1854 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1855 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1856 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1857 subIndices[subOff] = goff+poff+fc; 1858 } 1859 } 1860 } 1861 } 1862 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1863 if (subdm) { 1864 PetscSection subsection; 1865 PetscBool haveNull = PETSC_FALSE; 1866 PetscInt f, nf = 0; 1867 1868 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1869 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1870 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1871 for (f = 0; f < numFields; ++f) { 1872 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1873 if ((*subdm)->nullspaceConstructors[f]) { 1874 haveNull = PETSC_TRUE; 1875 nf = f; 1876 } 1877 } 1878 if (haveNull) { 1879 MatNullSpace nullSpace; 1880 1881 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1882 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1883 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1884 } 1885 if (dm->fields) { 1886 if (nF != dm->numFields) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1887 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1888 for (f = 0; f < numFields; ++f) { 1889 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1890 } 1891 if (numFields == 1) { 1892 MatNullSpace space; 1893 Mat pmat; 1894 1895 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr); 1896 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1897 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr); 1898 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1899 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr); 1900 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1901 } 1902 } 1903 } 1904 PetscFunctionReturn(0); 1905 } 1906 1907 #undef __FUNCT__ 1908 #define __FUNCT__ "DMPlexSymmetrize" 1909 /*@ 1910 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1911 1912 Not collective 1913 1914 Input Parameter: 1915 . mesh - The DMPlex 1916 1917 Output Parameter: 1918 1919 Note: 1920 This should be called after all calls to DMPlexSetCone() 1921 1922 Level: beginner 1923 1924 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1925 @*/ 1926 PetscErrorCode DMPlexSymmetrize(DM dm) 1927 { 1928 DM_Plex *mesh = (DM_Plex *) dm->data; 1929 PetscInt *offsets; 1930 PetscInt supportSize; 1931 PetscInt pStart, pEnd, p; 1932 PetscErrorCode ierr; 1933 1934 PetscFunctionBegin; 1935 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1936 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1937 /* Calculate support sizes */ 1938 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1939 for (p = pStart; p < pEnd; ++p) { 1940 PetscInt dof, off, c; 1941 1942 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1943 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1944 for (c = off; c < off+dof; ++c) { 1945 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1946 } 1947 } 1948 for (p = pStart; p < pEnd; ++p) { 1949 PetscInt dof; 1950 1951 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1952 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1953 } 1954 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1955 /* Calculate supports */ 1956 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1957 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1958 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1959 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1960 for (p = pStart; p < pEnd; ++p) { 1961 PetscInt dof, off, c; 1962 1963 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1964 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1965 for (c = off; c < off+dof; ++c) { 1966 const PetscInt q = mesh->cones[c]; 1967 PetscInt offS; 1968 1969 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1970 mesh->supports[offS+offsets[q]] = p; 1971 ++offsets[q]; 1972 } 1973 } 1974 ierr = PetscFree(offsets);CHKERRQ(ierr); 1975 PetscFunctionReturn(0); 1976 } 1977 1978 #undef __FUNCT__ 1979 #define __FUNCT__ "DMPlexSetDepth_Private" 1980 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1981 { 1982 PetscInt d; 1983 PetscErrorCode ierr; 1984 1985 PetscFunctionBegin; 1986 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1987 if (d < 0) { 1988 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1989 const PetscInt *cone = PETSC_NULL; 1990 PetscInt dCone; 1991 1992 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1993 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1994 d = dCone+1; 1995 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1996 } 1997 *depth = d; 1998 PetscFunctionReturn(0); 1999 } 2000 2001 #undef __FUNCT__ 2002 #define __FUNCT__ "DMPlexStratify" 2003 /*@ 2004 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2005 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2006 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2007 the DAG. 2008 2009 Not collective 2010 2011 Input Parameter: 2012 . mesh - The DMPlex 2013 2014 Output Parameter: 2015 2016 Notes: 2017 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2018 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2019 2020 This should be called after all calls to DMPlexSymmetrize() 2021 2022 Level: beginner 2023 2024 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2025 @*/ 2026 PetscErrorCode DMPlexStratify(DM dm) 2027 { 2028 DM_Plex *mesh = (DM_Plex *) dm->data; 2029 PetscInt pStart, pEnd, p; 2030 PetscInt numRoots = 0, numLeaves = 0; 2031 PetscErrorCode ierr; 2032 2033 PetscFunctionBegin; 2034 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2035 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2036 /* Calculate depth */ 2037 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2038 /* Initialize roots and count leaves */ 2039 for (p = pStart; p < pEnd; ++p) { 2040 PetscInt coneSize, supportSize; 2041 2042 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2043 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2044 if (!coneSize && supportSize) { 2045 ++numRoots; 2046 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2047 } else if (!supportSize && coneSize) { 2048 ++numLeaves; 2049 } else if (!supportSize && !coneSize) { 2050 /* Isolated points */ 2051 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2052 } 2053 } 2054 if (numRoots + numLeaves == (pEnd - pStart)) { 2055 for (p = pStart; p < pEnd; ++p) { 2056 PetscInt coneSize, supportSize; 2057 2058 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2059 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2060 if (!supportSize && coneSize) { 2061 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2062 } 2063 } 2064 } else { 2065 /* This might be slow since lookup is not fast */ 2066 for (p = pStart; p < pEnd; ++p) { 2067 PetscInt depth; 2068 2069 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2070 } 2071 } 2072 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2073 PetscFunctionReturn(0); 2074 } 2075 2076 #undef __FUNCT__ 2077 #define __FUNCT__ "DMPlexGetJoin" 2078 /*@C 2079 DMPlexGetJoin - Get an array for the join of the set of points 2080 2081 Not Collective 2082 2083 Input Parameters: 2084 + dm - The DMPlex object 2085 . numPoints - The number of input points for the join 2086 - points - The input points 2087 2088 Output Parameters: 2089 + numCoveredPoints - The number of points in the join 2090 - coveredPoints - The points in the join 2091 2092 Level: intermediate 2093 2094 Note: Currently, this is restricted to a single level join 2095 2096 .keywords: mesh 2097 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2098 @*/ 2099 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2100 { 2101 DM_Plex *mesh = (DM_Plex *) dm->data; 2102 PetscInt *join[2]; 2103 PetscInt joinSize, i = 0; 2104 PetscInt dof, off, p, c, m; 2105 PetscErrorCode ierr; 2106 2107 PetscFunctionBegin; 2108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2109 PetscValidPointer(points, 2); 2110 PetscValidPointer(numCoveredPoints, 3); 2111 PetscValidPointer(coveredPoints, 4); 2112 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2113 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2114 /* Copy in support of first point */ 2115 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2116 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2117 for (joinSize = 0; joinSize < dof; ++joinSize) { 2118 join[i][joinSize] = mesh->supports[off+joinSize]; 2119 } 2120 /* Check each successive support */ 2121 for (p = 1; p < numPoints; ++p) { 2122 PetscInt newJoinSize = 0; 2123 2124 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2125 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2126 for (c = 0; c < dof; ++c) { 2127 const PetscInt point = mesh->supports[off+c]; 2128 2129 for (m = 0; m < joinSize; ++m) { 2130 if (point == join[i][m]) { 2131 join[1-i][newJoinSize++] = point; 2132 break; 2133 } 2134 } 2135 } 2136 joinSize = newJoinSize; 2137 i = 1-i; 2138 } 2139 *numCoveredPoints = joinSize; 2140 *coveredPoints = join[i]; 2141 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2142 PetscFunctionReturn(0); 2143 } 2144 2145 #undef __FUNCT__ 2146 #define __FUNCT__ "DMPlexRestoreJoin" 2147 /*@C 2148 DMPlexRestoreJoin - Restore an array for the join of the set of points 2149 2150 Not Collective 2151 2152 Input Parameters: 2153 + dm - The DMPlex object 2154 . numPoints - The number of input points for the join 2155 - points - The input points 2156 2157 Output Parameters: 2158 + numCoveredPoints - The number of points in the join 2159 - coveredPoints - The points in the join 2160 2161 Level: intermediate 2162 2163 .keywords: mesh 2164 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2165 @*/ 2166 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2167 { 2168 PetscErrorCode ierr; 2169 2170 PetscFunctionBegin; 2171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2172 PetscValidPointer(coveredPoints, 4); 2173 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2174 PetscFunctionReturn(0); 2175 } 2176 2177 #undef __FUNCT__ 2178 #define __FUNCT__ "DMPlexGetFullJoin" 2179 /*@C 2180 DMPlexGetFullJoin - Get an array for the join of the set of points 2181 2182 Not Collective 2183 2184 Input Parameters: 2185 + dm - The DMPlex object 2186 . numPoints - The number of input points for the join 2187 - points - The input points 2188 2189 Output Parameters: 2190 + numCoveredPoints - The number of points in the join 2191 - coveredPoints - The points in the join 2192 2193 Level: intermediate 2194 2195 .keywords: mesh 2196 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2197 @*/ 2198 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2199 { 2200 DM_Plex *mesh = (DM_Plex *) dm->data; 2201 PetscInt *offsets, **closures; 2202 PetscInt *join[2]; 2203 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2204 PetscInt p, d, c, m; 2205 PetscErrorCode ierr; 2206 2207 PetscFunctionBegin; 2208 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2209 PetscValidPointer(points, 2); 2210 PetscValidPointer(numCoveredPoints, 3); 2211 PetscValidPointer(coveredPoints, 4); 2212 2213 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2214 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2215 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2216 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2217 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2218 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2219 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2220 2221 for (p = 0; p < numPoints; ++p) { 2222 PetscInt closureSize; 2223 2224 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2225 offsets[p*(depth+2)+0] = 0; 2226 for (d = 0; d < depth+1; ++d) { 2227 PetscInt pStart, pEnd, i; 2228 2229 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2230 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2231 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2232 offsets[p*(depth+2)+d+1] = i; 2233 break; 2234 } 2235 } 2236 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2237 } 2238 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2239 } 2240 for (d = 0; d < depth+1; ++d) { 2241 PetscInt dof; 2242 2243 /* Copy in support of first point */ 2244 dof = offsets[d+1] - offsets[d]; 2245 for (joinSize = 0; joinSize < dof; ++joinSize) { 2246 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2247 } 2248 /* Check each successive cone */ 2249 for (p = 1; p < numPoints && joinSize; ++p) { 2250 PetscInt newJoinSize = 0; 2251 2252 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2253 for (c = 0; c < dof; ++c) { 2254 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2255 2256 for (m = 0; m < joinSize; ++m) { 2257 if (point == join[i][m]) { 2258 join[1-i][newJoinSize++] = point; 2259 break; 2260 } 2261 } 2262 } 2263 joinSize = newJoinSize; 2264 i = 1-i; 2265 } 2266 if (joinSize) break; 2267 } 2268 *numCoveredPoints = joinSize; 2269 *coveredPoints = join[i]; 2270 for (p = 0; p < numPoints; ++p) { 2271 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2272 } 2273 ierr = PetscFree(closures);CHKERRQ(ierr); 2274 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2275 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2276 PetscFunctionReturn(0); 2277 } 2278 2279 #undef __FUNCT__ 2280 #define __FUNCT__ "DMPlexGetMeet" 2281 /*@C 2282 DMPlexGetMeet - Get an array for the meet of the set of points 2283 2284 Not Collective 2285 2286 Input Parameters: 2287 + dm - The DMPlex object 2288 . numPoints - The number of input points for the meet 2289 - points - The input points 2290 2291 Output Parameters: 2292 + numCoveredPoints - The number of points in the meet 2293 - coveredPoints - The points in the meet 2294 2295 Level: intermediate 2296 2297 Note: Currently, this is restricted to a single level meet 2298 2299 .keywords: mesh 2300 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2301 @*/ 2302 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2303 { 2304 DM_Plex *mesh = (DM_Plex *) dm->data; 2305 PetscInt *meet[2]; 2306 PetscInt meetSize, i = 0; 2307 PetscInt dof, off, p, c, m; 2308 PetscErrorCode ierr; 2309 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2312 PetscValidPointer(points, 2); 2313 PetscValidPointer(numCoveringPoints, 3); 2314 PetscValidPointer(coveringPoints, 4); 2315 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2316 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2317 /* Copy in cone of first point */ 2318 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2319 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2320 for (meetSize = 0; meetSize < dof; ++meetSize) { 2321 meet[i][meetSize] = mesh->cones[off+meetSize]; 2322 } 2323 /* Check each successive cone */ 2324 for (p = 1; p < numPoints; ++p) { 2325 PetscInt newMeetSize = 0; 2326 2327 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2328 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2329 for (c = 0; c < dof; ++c) { 2330 const PetscInt point = mesh->cones[off+c]; 2331 2332 for (m = 0; m < meetSize; ++m) { 2333 if (point == meet[i][m]) { 2334 meet[1-i][newMeetSize++] = point; 2335 break; 2336 } 2337 } 2338 } 2339 meetSize = newMeetSize; 2340 i = 1-i; 2341 } 2342 *numCoveringPoints = meetSize; 2343 *coveringPoints = meet[i]; 2344 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2345 PetscFunctionReturn(0); 2346 } 2347 2348 #undef __FUNCT__ 2349 #define __FUNCT__ "DMPlexRestoreMeet" 2350 /*@C 2351 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2352 2353 Not Collective 2354 2355 Input Parameters: 2356 + dm - The DMPlex object 2357 . numPoints - The number of input points for the meet 2358 - points - The input points 2359 2360 Output Parameters: 2361 + numCoveredPoints - The number of points in the meet 2362 - coveredPoints - The points in the meet 2363 2364 Level: intermediate 2365 2366 .keywords: mesh 2367 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2368 @*/ 2369 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2370 { 2371 PetscErrorCode ierr; 2372 2373 PetscFunctionBegin; 2374 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2375 PetscValidPointer(coveredPoints, 4); 2376 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2377 PetscFunctionReturn(0); 2378 } 2379 2380 #undef __FUNCT__ 2381 #define __FUNCT__ "DMPlexGetFullMeet" 2382 /*@C 2383 DMPlexGetFullMeet - Get an array for the meet of the set of points 2384 2385 Not Collective 2386 2387 Input Parameters: 2388 + dm - The DMPlex object 2389 . numPoints - The number of input points for the meet 2390 - points - The input points 2391 2392 Output Parameters: 2393 + numCoveredPoints - The number of points in the meet 2394 - coveredPoints - The points in the meet 2395 2396 Level: intermediate 2397 2398 .keywords: mesh 2399 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2400 @*/ 2401 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2402 { 2403 DM_Plex *mesh = (DM_Plex *) dm->data; 2404 PetscInt *offsets, **closures; 2405 PetscInt *meet[2]; 2406 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2407 PetscInt p, h, c, m; 2408 PetscErrorCode ierr; 2409 2410 PetscFunctionBegin; 2411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2412 PetscValidPointer(points, 2); 2413 PetscValidPointer(numCoveredPoints, 3); 2414 PetscValidPointer(coveredPoints, 4); 2415 2416 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2417 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2418 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2419 maxSize = PetscPowInt(mesh->maxConeSize,height); 2420 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2421 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2422 2423 for (p = 0; p < numPoints; ++p) { 2424 PetscInt closureSize; 2425 2426 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2427 offsets[p*(height+2)+0] = 0; 2428 for (h = 0; h < height+1; ++h) { 2429 PetscInt pStart, pEnd, i; 2430 2431 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2432 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2433 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2434 offsets[p*(height+2)+h+1] = i; 2435 break; 2436 } 2437 } 2438 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2439 } 2440 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2441 } 2442 for (h = 0; h < height+1; ++h) { 2443 PetscInt dof; 2444 2445 /* Copy in cone of first point */ 2446 dof = offsets[h+1] - offsets[h]; 2447 for (meetSize = 0; meetSize < dof; ++meetSize) { 2448 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2449 } 2450 /* Check each successive cone */ 2451 for (p = 1; p < numPoints && meetSize; ++p) { 2452 PetscInt newMeetSize = 0; 2453 2454 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2455 for (c = 0; c < dof; ++c) { 2456 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2457 2458 for (m = 0; m < meetSize; ++m) { 2459 if (point == meet[i][m]) { 2460 meet[1-i][newMeetSize++] = point; 2461 break; 2462 } 2463 } 2464 } 2465 meetSize = newMeetSize; 2466 i = 1-i; 2467 } 2468 if (meetSize) break; 2469 } 2470 *numCoveredPoints = meetSize; 2471 *coveredPoints = meet[i]; 2472 for (p = 0; p < numPoints; ++p) { 2473 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2474 } 2475 ierr = PetscFree(closures);CHKERRQ(ierr); 2476 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2477 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2478 PetscFunctionReturn(0); 2479 } 2480 2481 #undef __FUNCT__ 2482 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2483 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2484 { 2485 MPI_Comm comm = ((PetscObject) dm)->comm; 2486 PetscInt cellDim; 2487 PetscErrorCode ierr; 2488 2489 PetscFunctionBegin; 2490 PetscValidPointer(numFaceVertices,3); 2491 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2492 switch (cellDim) { 2493 case 0: 2494 *numFaceVertices = 0; 2495 break; 2496 case 1: 2497 *numFaceVertices = 1; 2498 break; 2499 case 2: 2500 switch (numCorners) { 2501 case 3: /* triangle */ 2502 *numFaceVertices = 2; /* Edge has 2 vertices */ 2503 break; 2504 case 4: /* quadrilateral */ 2505 *numFaceVertices = 2; /* Edge has 2 vertices */ 2506 break; 2507 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2508 *numFaceVertices = 3; /* Edge has 3 vertices */ 2509 break; 2510 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2511 *numFaceVertices = 3; /* Edge has 3 vertices */ 2512 break; 2513 default: 2514 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2515 } 2516 break; 2517 case 3: 2518 switch (numCorners) { 2519 case 4: /* tetradehdron */ 2520 *numFaceVertices = 3; /* Face has 3 vertices */ 2521 break; 2522 case 6: /* tet cohesive cells */ 2523 *numFaceVertices = 4; /* Face has 4 vertices */ 2524 break; 2525 case 8: /* hexahedron */ 2526 *numFaceVertices = 4; /* Face has 4 vertices */ 2527 break; 2528 case 9: /* tet cohesive Lagrange cells */ 2529 *numFaceVertices = 6; /* Face has 6 vertices */ 2530 break; 2531 case 10: /* quadratic tetrahedron */ 2532 *numFaceVertices = 6; /* Face has 6 vertices */ 2533 break; 2534 case 12: /* hex cohesive Lagrange cells */ 2535 *numFaceVertices = 6; /* Face has 6 vertices */ 2536 break; 2537 case 18: /* quadratic tet cohesive Lagrange cells */ 2538 *numFaceVertices = 6; /* Face has 6 vertices */ 2539 break; 2540 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2541 *numFaceVertices = 9; /* Face has 9 vertices */ 2542 break; 2543 default: 2544 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2545 } 2546 break; 2547 default: 2548 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2549 } 2550 PetscFunctionReturn(0); 2551 } 2552 2553 #undef __FUNCT__ 2554 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2555 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2556 { 2557 const PetscInt maxFaceCases = 30; 2558 PetscInt numFaceCases = 0; 2559 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2560 PetscInt *off, *adj; 2561 PetscInt *neighborCells, *tmpClosure; 2562 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2563 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2564 PetscErrorCode ierr; 2565 2566 PetscFunctionBegin; 2567 /* For parallel partitioning, I think you have to communicate supports */ 2568 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2569 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2570 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2571 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2572 if (cEnd - cStart == 0) { 2573 if (numVertices) *numVertices = 0; 2574 if (offsets) *offsets = PETSC_NULL; 2575 if (adjacency) *adjacency = PETSC_NULL; 2576 PetscFunctionReturn(0); 2577 } 2578 numCells = cEnd - cStart; 2579 /* Setup face recognition */ 2580 { 2581 PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */ 2582 2583 for (c = cStart; c < cEnd; ++c) { 2584 PetscInt corners; 2585 2586 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2587 if (!cornersSeen[corners]) { 2588 PetscInt nFV; 2589 2590 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2591 cornersSeen[corners] = 1; 2592 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2593 numFaceVertices[numFaceCases++] = nFV; 2594 } 2595 } 2596 } 2597 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2598 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2599 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2600 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2601 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2602 /* Count neighboring cells */ 2603 for (cell = cStart; cell < cEnd; ++cell) { 2604 PetscInt numNeighbors = maxNeighbors, n; 2605 2606 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2607 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2608 for (n = 0; n < numNeighbors; ++n) { 2609 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2610 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2611 PetscInt meetSize = 0; 2612 const PetscInt *meet = PETSC_NULL; 2613 2614 if (cellPair[0] == cellPair[1]) continue; 2615 if (!found) { 2616 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2617 if (meetSize) { 2618 PetscInt f; 2619 2620 for (f = 0; f < numFaceCases; ++f) { 2621 if (numFaceVertices[f] == meetSize) { 2622 found = PETSC_TRUE; 2623 break; 2624 } 2625 } 2626 } 2627 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2628 } 2629 if (found) { 2630 ++off[cell-cStart+1]; 2631 } 2632 } 2633 } 2634 /* Prefix sum */ 2635 for (cell = 1; cell <= numCells; ++cell) { 2636 off[cell] += off[cell-1]; 2637 } 2638 if (adjacency) { 2639 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2640 /* Get neighboring cells */ 2641 for (cell = cStart; cell < cEnd; ++cell) { 2642 PetscInt numNeighbors = maxNeighbors, n; 2643 PetscInt cellOffset = 0; 2644 2645 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2646 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2647 for (n = 0; n < numNeighbors; ++n) { 2648 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2649 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2650 PetscInt meetSize = 0; 2651 const PetscInt *meet = PETSC_NULL; 2652 2653 if (cellPair[0] == cellPair[1]) continue; 2654 if (!found) { 2655 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2656 if (meetSize) { 2657 PetscInt f; 2658 2659 for (f = 0; f < numFaceCases; ++f) { 2660 if (numFaceVertices[f] == meetSize) { 2661 found = PETSC_TRUE; 2662 break; 2663 } 2664 } 2665 } 2666 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2667 } 2668 if (found) { 2669 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2670 ++cellOffset; 2671 } 2672 } 2673 } 2674 } 2675 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2676 if (numVertices) *numVertices = numCells; 2677 if (offsets) *offsets = off; 2678 if (adjacency) *adjacency = adj; 2679 PetscFunctionReturn(0); 2680 } 2681 2682 #if defined(PETSC_HAVE_CHACO) 2683 #if defined(PETSC_HAVE_UNISTD_H) 2684 #include <unistd.h> 2685 #endif 2686 /* Chaco does not have an include file */ 2687 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2688 float *ewgts, float *x, float *y, float *z, char *outassignname, 2689 char *outfilename, short *assignment, int architecture, int ndims_tot, 2690 int mesh_dims[3], double *goal, int global_method, int local_method, 2691 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2692 2693 extern int FREE_GRAPH; 2694 2695 #undef __FUNCT__ 2696 #define __FUNCT__ "DMPlexPartition_Chaco" 2697 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2698 { 2699 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2700 MPI_Comm comm = ((PetscObject) dm)->comm; 2701 int nvtxs = numVertices; /* number of vertices in full graph */ 2702 int *vwgts = NULL; /* weights for all vertices */ 2703 float *ewgts = NULL; /* weights for all edges */ 2704 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2705 char *outassignname = NULL; /* name of assignment output file */ 2706 char *outfilename = NULL; /* output file name */ 2707 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2708 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2709 int mesh_dims[3]; /* dimensions of mesh of processors */ 2710 double *goal = NULL; /* desired set sizes for each set */ 2711 int global_method = 1; /* global partitioning algorithm */ 2712 int local_method = 1; /* local partitioning algorithm */ 2713 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2714 int vmax = 200; /* how many vertices to coarsen down to? */ 2715 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2716 double eigtol = 0.001; /* tolerance on eigenvectors */ 2717 long seed = 123636512; /* for random graph mutations */ 2718 short int *assignment; /* Output partition */ 2719 int fd_stdout, fd_pipe[2]; 2720 PetscInt *points; 2721 PetscMPIInt commSize; 2722 int i, v, p; 2723 PetscErrorCode ierr; 2724 2725 PetscFunctionBegin; 2726 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2727 if (!numVertices) { 2728 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2729 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2730 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2731 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2732 PetscFunctionReturn(0); 2733 } 2734 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2735 for (i = 0; i < start[numVertices]; ++i) { 2736 ++adjacency[i]; 2737 } 2738 if (global_method == INERTIAL_METHOD) { 2739 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2740 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2741 } 2742 mesh_dims[0] = commSize; 2743 mesh_dims[1] = 1; 2744 mesh_dims[2] = 1; 2745 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2746 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2747 /* TODO: check error codes for UNIX calls */ 2748 #if defined(PETSC_HAVE_UNISTD_H) 2749 { 2750 int piperet; 2751 piperet = pipe(fd_pipe); 2752 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2753 fd_stdout = dup(1); 2754 close(1); 2755 dup2(fd_pipe[1], 1); 2756 } 2757 #endif 2758 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2759 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2760 vmax, ndims, eigtol, seed); 2761 #if defined(PETSC_HAVE_UNISTD_H) 2762 { 2763 char msgLog[10000]; 2764 int count; 2765 2766 fflush(stdout); 2767 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2768 if (count < 0) count = 0; 2769 msgLog[count] = 0; 2770 close(1); 2771 dup2(fd_stdout, 1); 2772 close(fd_stdout); 2773 close(fd_pipe[0]); 2774 close(fd_pipe[1]); 2775 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2776 } 2777 #endif 2778 /* Convert to PetscSection+IS */ 2779 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2780 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2781 for (v = 0; v < nvtxs; ++v) { 2782 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2783 } 2784 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2785 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2786 for (p = 0, i = 0; p < commSize; ++p) { 2787 for (v = 0; v < nvtxs; ++v) { 2788 if (assignment[v] == p) points[i++] = v; 2789 } 2790 } 2791 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2792 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2793 if (global_method == INERTIAL_METHOD) { 2794 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2795 } 2796 ierr = PetscFree(assignment);CHKERRQ(ierr); 2797 for (i = 0; i < start[numVertices]; ++i) { 2798 --adjacency[i]; 2799 } 2800 PetscFunctionReturn(0); 2801 } 2802 #endif 2803 2804 #if defined(PETSC_HAVE_PARMETIS) 2805 #undef __FUNCT__ 2806 #define __FUNCT__ "DMPlexPartition_ParMetis" 2807 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2808 { 2809 PetscFunctionBegin; 2810 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2811 PetscFunctionReturn(0); 2812 } 2813 #endif 2814 2815 #undef __FUNCT__ 2816 #define __FUNCT__ "DMPlexEnlargePartition" 2817 /* Expand the partition by BFS on the adjacency graph */ 2818 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2819 { 2820 PetscHashI h; 2821 const PetscInt *points; 2822 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2823 PetscInt pStart, pEnd, part, q; 2824 PetscErrorCode ierr; 2825 2826 PetscFunctionBegin; 2827 PetscHashICreate(h); 2828 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2829 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2830 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2831 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2832 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2833 for (part = pStart; part < pEnd; ++part) { 2834 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2835 2836 PetscHashIClear(h); 2837 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2838 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2839 /* Add all existing points to h */ 2840 for (p = 0; p < numPoints; ++p) { 2841 const PetscInt point = points[off+p]; 2842 PetscHashIAdd(h, point, 1); 2843 } 2844 PetscHashISize(h, nP); 2845 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2846 /* Add all points in next BFS level */ 2847 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2848 for (p = 0; p < numPoints; ++p) { 2849 const PetscInt point = points[off+p]; 2850 PetscInt s = start[point], e = start[point+1], a; 2851 2852 for (a = s; a < e; ++a) { 2853 PetscHashIAdd(h, adjacency[a], 1); 2854 } 2855 } 2856 PetscHashISize(h, numNewPoints); 2857 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2858 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2859 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2860 totPoints += numNewPoints; 2861 } 2862 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2863 PetscHashIDestroy(h); 2864 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2865 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2866 for (part = pStart, q = 0; part < pEnd; ++part) { 2867 PetscInt numPoints, p; 2868 2869 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2870 for (p = 0; p < numPoints; ++p, ++q) { 2871 newPoints[q] = tmpPoints[part][p]; 2872 } 2873 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2874 } 2875 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2876 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2877 PetscFunctionReturn(0); 2878 } 2879 2880 #undef __FUNCT__ 2881 #define __FUNCT__ "DMPlexCreatePartition" 2882 /* 2883 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2884 2885 Collective on DM 2886 2887 Input Parameters: 2888 + dm - The DM 2889 . height - The height for points in the partition 2890 - enlarge - Expand each partition with neighbors 2891 2892 Output Parameters: 2893 + partSection - The PetscSection giving the division of points by partition 2894 . partition - The list of points by partition 2895 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2896 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2897 2898 Level: developer 2899 2900 .seealso DMPlexDistribute() 2901 */ 2902 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2903 { 2904 PetscMPIInt size; 2905 PetscErrorCode ierr; 2906 2907 PetscFunctionBegin; 2908 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2909 *origPartSection = PETSC_NULL; 2910 *origPartition = PETSC_NULL; 2911 if (size == 1) { 2912 PetscInt *points; 2913 PetscInt cStart, cEnd, c; 2914 2915 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2916 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2917 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2918 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2919 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2920 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2921 for (c = cStart; c < cEnd; ++c) { 2922 points[c] = c; 2923 } 2924 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2925 PetscFunctionReturn(0); 2926 } 2927 if (height == 0) { 2928 PetscInt numVertices; 2929 PetscInt *start = PETSC_NULL; 2930 PetscInt *adjacency = PETSC_NULL; 2931 2932 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2933 if (1) { 2934 #if defined(PETSC_HAVE_CHACO) 2935 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2936 #endif 2937 } else { 2938 #if defined(PETSC_HAVE_PARMETIS) 2939 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2940 #endif 2941 } 2942 if (enlarge) { 2943 *origPartSection = *partSection; 2944 *origPartition = *partition; 2945 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2946 } 2947 ierr = PetscFree(start);CHKERRQ(ierr); 2948 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2949 # if 0 2950 } else if (height == 1) { 2951 /* Build the dual graph for faces and partition the hypergraph */ 2952 PetscInt numEdges; 2953 2954 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2955 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2956 destroyCSR(numEdges, start, adjacency); 2957 #endif 2958 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2959 PetscFunctionReturn(0); 2960 } 2961 2962 #undef __FUNCT__ 2963 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2964 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2965 { 2966 /* const PetscInt height = 0; */ 2967 const PetscInt *partArray; 2968 PetscInt *allPoints, *partPoints = PETSC_NULL; 2969 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2970 PetscErrorCode ierr; 2971 2972 PetscFunctionBegin; 2973 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2974 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2975 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2976 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2977 for (rank = rStart; rank < rEnd; ++rank) { 2978 PetscInt partSize = 0; 2979 PetscInt numPoints, offset, p; 2980 2981 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2982 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2983 for (p = 0; p < numPoints; ++p) { 2984 PetscInt point = partArray[offset+p], closureSize, c; 2985 PetscInt *closure = PETSC_NULL; 2986 2987 /* TODO Include support for height > 0 case */ 2988 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2989 /* Merge into existing points */ 2990 if (partSize+closureSize > maxPartSize) { 2991 PetscInt *tmpPoints; 2992 2993 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2994 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2995 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2996 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2997 partPoints = tmpPoints; 2998 } 2999 for (c = 0; c < closureSize; ++c) { 3000 partPoints[partSize+c] = closure[c*2]; 3001 } 3002 partSize += closureSize; 3003 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3004 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3005 } 3006 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3007 } 3008 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3009 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3010 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3011 3012 for (rank = rStart; rank < rEnd; ++rank) { 3013 PetscInt partSize = 0, newOffset; 3014 PetscInt numPoints, offset, p; 3015 3016 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3017 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3018 for (p = 0; p < numPoints; ++p) { 3019 PetscInt point = partArray[offset+p], closureSize, c; 3020 PetscInt *closure = PETSC_NULL; 3021 3022 /* TODO Include support for height > 0 case */ 3023 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3024 /* Merge into existing points */ 3025 for (c = 0; c < closureSize; ++c) { 3026 partPoints[partSize+c] = closure[c*2]; 3027 } 3028 partSize += closureSize; 3029 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3030 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3031 } 3032 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3033 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3034 } 3035 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3036 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3037 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3038 PetscFunctionReturn(0); 3039 } 3040 3041 #undef __FUNCT__ 3042 #define __FUNCT__ "DMPlexDistributeField" 3043 /* 3044 Input Parameters: 3045 . originalSection 3046 , originalVec 3047 3048 Output Parameters: 3049 . newSection 3050 . newVec 3051 */ 3052 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3053 { 3054 PetscSF fieldSF; 3055 PetscInt *remoteOffsets, fieldSize; 3056 PetscScalar *originalValues, *newValues; 3057 PetscErrorCode ierr; 3058 3059 PetscFunctionBegin; 3060 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3061 3062 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3063 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3064 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3065 3066 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3067 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3068 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3069 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3070 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3071 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3072 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3073 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3074 PetscFunctionReturn(0); 3075 } 3076 3077 #undef __FUNCT__ 3078 #define __FUNCT__ "DMPlexDistribute" 3079 /*@C 3080 DMPlexDistribute - Distributes the mesh and any associated sections. 3081 3082 Not Collective 3083 3084 Input Parameter: 3085 + dm - The original DMPlex object 3086 . partitioner - The partitioning package, or NULL for the default 3087 - overlap - The overlap of partitions, 0 is the default 3088 3089 Output Parameter: 3090 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3091 3092 Note: If the mesh was not distributed, the return value is PETSC_NULL 3093 3094 Level: intermediate 3095 3096 .keywords: mesh, elements 3097 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3098 @*/ 3099 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3100 { 3101 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3102 MPI_Comm comm = ((PetscObject) dm)->comm; 3103 const PetscInt height = 0; 3104 PetscInt dim, numRemoteRanks; 3105 IS origCellPart, cellPart, part; 3106 PetscSection origCellPartSection, cellPartSection, partSection; 3107 PetscSFNode *remoteRanks; 3108 PetscSF partSF, pointSF, coneSF; 3109 ISLocalToGlobalMapping renumbering; 3110 PetscSection originalConeSection, newConeSection; 3111 PetscInt *remoteOffsets; 3112 PetscInt *cones, *newCones, newConesSize; 3113 PetscBool flg; 3114 PetscMPIInt rank, numProcs, p; 3115 PetscErrorCode ierr; 3116 3117 PetscFunctionBegin; 3118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3119 PetscValidPointer(dmParallel,4); 3120 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3121 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3122 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3123 *dmParallel = PETSC_NULL; 3124 if (numProcs == 1) PetscFunctionReturn(0); 3125 3126 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3127 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3128 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3129 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3130 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3131 if (!rank) { 3132 numRemoteRanks = numProcs; 3133 } else { 3134 numRemoteRanks = 0; 3135 } 3136 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3137 for (p = 0; p < numRemoteRanks; ++p) { 3138 remoteRanks[p].rank = p; 3139 remoteRanks[p].index = 0; 3140 } 3141 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3142 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3143 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3144 if (flg) { 3145 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3146 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3147 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3148 if (origCellPart) { 3149 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3150 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3151 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3152 } 3153 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3154 } 3155 /* Close the partition over the mesh */ 3156 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3157 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3158 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3159 /* Create new mesh */ 3160 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3161 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3162 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3163 pmesh = (DM_Plex *) (*dmParallel)->data; 3164 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3165 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3166 if (flg) { 3167 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3168 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3169 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3170 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3171 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3172 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3173 } 3174 /* Distribute cone section */ 3175 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3176 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3177 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3178 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3179 { 3180 PetscInt pStart, pEnd, p; 3181 3182 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3183 for (p = pStart; p < pEnd; ++p) { 3184 PetscInt coneSize; 3185 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3186 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3187 } 3188 } 3189 /* Communicate and renumber cones */ 3190 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3191 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3192 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3193 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3194 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3195 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3196 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3197 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3198 if (flg) { 3199 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3200 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3201 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3202 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3203 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3204 } 3205 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3206 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3207 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3208 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3209 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3210 /* Create supports and stratify sieve */ 3211 { 3212 PetscInt pStart, pEnd; 3213 3214 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3215 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3216 } 3217 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3218 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3219 /* Distribute Coordinates */ 3220 { 3221 PetscSection originalCoordSection, newCoordSection; 3222 Vec originalCoordinates, newCoordinates; 3223 const char *name; 3224 3225 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3226 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3227 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3228 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3229 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3230 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3231 3232 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3233 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3234 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3235 } 3236 /* Distribute labels */ 3237 { 3238 DMLabel next = mesh->labels, newNext = pmesh->labels; 3239 PetscInt numLabels = 0, l; 3240 3241 /* Bcast number of labels */ 3242 while (next) {++numLabels; next = next->next;} 3243 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3244 next = mesh->labels; 3245 for (l = 0; l < numLabels; ++l) { 3246 DMLabel newLabel; 3247 const PetscInt *partArray; 3248 char *name; 3249 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3250 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3251 PetscInt nameSize, s, p; 3252 PetscBool isdepth; 3253 size_t len = 0; 3254 3255 /* Bcast name (could filter for no points) */ 3256 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3257 nameSize = len; 3258 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3259 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3260 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3261 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3262 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3263 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3264 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3265 newLabel->name = name; 3266 /* Bcast numStrata (could filter for no points in stratum) */ 3267 if (!rank) {newLabel->numStrata = next->numStrata;} 3268 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3269 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3270 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3271 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3272 /* Bcast stratumValues (could filter for no points in stratum) */ 3273 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3274 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3275 /* Find size on each process and Scatter */ 3276 if (!rank) { 3277 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3278 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3279 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3280 for (s = 0; s < next->numStrata; ++s) { 3281 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3282 const PetscInt point = next->points[p]; 3283 PetscInt proc; 3284 3285 for (proc = 0; proc < numProcs; ++proc) { 3286 PetscInt dof, off, pPart; 3287 3288 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3289 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3290 for (pPart = off; pPart < off+dof; ++pPart) { 3291 if (partArray[pPart] == point) { 3292 ++stratumSizes[proc*next->numStrata+s]; 3293 break; 3294 } 3295 } 3296 } 3297 } 3298 } 3299 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3300 } 3301 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3302 /* Calculate stratumOffsets */ 3303 newLabel->stratumOffsets[0] = 0; 3304 for (s = 0; s < newLabel->numStrata; ++s) { 3305 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3306 } 3307 /* Pack points and Scatter */ 3308 if (!rank) { 3309 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3310 displs[0] = 0; 3311 for (p = 0; p < numProcs; ++p) { 3312 sendcnts[p] = 0; 3313 for (s = 0; s < next->numStrata; ++s) { 3314 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3315 } 3316 offsets[p] = displs[p]; 3317 displs[p+1] = displs[p] + sendcnts[p]; 3318 } 3319 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3320 for (s = 0; s < next->numStrata; ++s) { 3321 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3322 const PetscInt point = next->points[p]; 3323 PetscInt proc; 3324 3325 for (proc = 0; proc < numProcs; ++proc) { 3326 PetscInt dof, off, pPart; 3327 3328 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3329 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3330 for (pPart = off; pPart < off+dof; ++pPart) { 3331 if (partArray[pPart] == point) { 3332 points[offsets[proc]++] = point; 3333 break; 3334 } 3335 } 3336 } 3337 } 3338 } 3339 } 3340 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3341 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3342 ierr = PetscFree(points);CHKERRQ(ierr); 3343 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3344 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3345 /* Renumber points */ 3346 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3347 /* Sort points */ 3348 for (s = 0; s < newLabel->numStrata; ++s) { 3349 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3350 } 3351 /* Insert into list */ 3352 if (newNext) { 3353 newNext->next = newLabel; 3354 } else { 3355 pmesh->labels = newLabel; 3356 } 3357 newNext = newLabel; 3358 if (!rank) {next = next->next;} 3359 } 3360 } 3361 /* Cleanup Partition */ 3362 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3363 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3364 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3365 ierr = ISDestroy(&part);CHKERRQ(ierr); 3366 /* Create point SF for parallel mesh */ 3367 { 3368 const PetscInt *leaves; 3369 PetscSFNode *remotePoints, *rowners, *lowners; 3370 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3371 PetscInt pStart, pEnd; 3372 3373 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3374 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3375 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3376 for (p=0; p<numRoots; p++) { 3377 rowners[p].rank = -1; 3378 rowners[p].index = -1; 3379 } 3380 if (origCellPart) { 3381 /* Make sure cells in the original partition are not assigned to other procs */ 3382 const PetscInt *origCells; 3383 3384 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3385 for (p = 0; p < numProcs; ++p) { 3386 PetscInt dof, off, d; 3387 3388 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3389 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3390 for (d = off; d < off+dof; ++d) { 3391 rowners[origCells[d]].rank = p; 3392 } 3393 } 3394 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3395 } 3396 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3397 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3398 3399 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3400 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3401 for (p = 0; p < numLeaves; ++p) { 3402 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3403 lowners[p].rank = rank; 3404 lowners[p].index = leaves ? leaves[p] : p; 3405 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3406 lowners[p].rank = -2; 3407 lowners[p].index = -2; 3408 } 3409 } 3410 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3411 rowners[p].rank = -3; 3412 rowners[p].index = -3; 3413 } 3414 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3415 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3416 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3417 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3418 for (p = 0; p < numLeaves; ++p) { 3419 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3420 if (lowners[p].rank != rank) ++numGhostPoints; 3421 } 3422 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3423 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3424 for (p = 0, gp = 0; p < numLeaves; ++p) { 3425 if (lowners[p].rank != rank) { 3426 ghostPoints[gp] = leaves ? leaves[p] : p; 3427 remotePoints[gp].rank = lowners[p].rank; 3428 remotePoints[gp].index = lowners[p].index; 3429 ++gp; 3430 } 3431 } 3432 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3433 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3434 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3435 } 3436 /* Cleanup */ 3437 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3438 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3439 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3440 PetscFunctionReturn(0); 3441 } 3442 3443 #undef __FUNCT__ 3444 #define __FUNCT__ "DMPlexRenumber_Private" 3445 /* 3446 Reasons to renumber: 3447 3448 1) Permute points, e.g. bandwidth reduction (Renumber) 3449 3450 a) Must not mix strata 3451 3452 2) Shift numbers for point insertion (Shift) 3453 3454 a) Want operation brken into parts so that insertion can be interleaved 3455 3456 renumbering - An IS which provides the new numbering 3457 */ 3458 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3459 { 3460 PetscFunctionBegin; 3461 PetscFunctionReturn(0); 3462 } 3463 3464 #undef __FUNCT__ 3465 #define __FUNCT__ "DMPlexShiftPoint_Private" 3466 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3467 { 3468 if (depth < 0) return p; 3469 /* Cells */ if (p < depthEnd[depth]) return p; 3470 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3471 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3472 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3473 } 3474 3475 #undef __FUNCT__ 3476 #define __FUNCT__ "DMPlexShiftSizes_Private" 3477 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3478 { 3479 PetscInt *depthEnd; 3480 PetscInt depth = 0, d, pStart, pEnd, p; 3481 PetscErrorCode ierr; 3482 3483 PetscFunctionBegin; 3484 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3485 if (depth < 0) PetscFunctionReturn(0); 3486 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3487 /* Step 1: Expand chart */ 3488 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3489 for (d = 0; d <= depth; ++d) { 3490 pEnd += depthShift[d]; 3491 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3492 } 3493 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3494 /* Step 2: Set cone and support sizes */ 3495 for (d = 0; d <= depth; ++d) { 3496 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3497 for (p = pStart; p < pEnd; ++p) { 3498 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3499 PetscInt size; 3500 3501 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3502 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3503 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3504 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3505 } 3506 } 3507 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3508 PetscFunctionReturn(0); 3509 } 3510 3511 #undef __FUNCT__ 3512 #define __FUNCT__ "DMPlexShiftPoints_Private" 3513 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3514 { 3515 PetscInt *depthEnd, *newpoints; 3516 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3517 PetscErrorCode ierr; 3518 3519 PetscFunctionBegin; 3520 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3521 if (depth < 0) PetscFunctionReturn(0); 3522 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3523 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3524 for (d = 0; d <= depth; ++d) { 3525 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3526 } 3527 /* Step 5: Set cones and supports */ 3528 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3529 for (p = pStart; p < pEnd; ++p) { 3530 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3531 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3532 3533 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3534 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3535 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3536 for (i = 0; i < size; ++i) { 3537 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3538 } 3539 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3540 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3541 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3542 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3543 for (i = 0; i < size; ++i) { 3544 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3545 } 3546 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3547 } 3548 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3549 PetscFunctionReturn(0); 3550 } 3551 3552 #undef __FUNCT__ 3553 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3554 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3555 { 3556 PetscSection coordSection, newCoordSection; 3557 Vec coordinates; 3558 PetscInt *depthEnd; 3559 PetscInt dim, depth = 0, d, vStart, vEnd, v; 3560 PetscErrorCode ierr; 3561 3562 PetscFunctionBegin; 3563 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3564 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3565 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3566 for (d = 0; d <= depth; ++d) { 3567 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3568 } 3569 /* Step 8: Convert coordinates */ 3570 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3571 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3572 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3573 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3574 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3575 ierr = PetscSectionSetChart(newCoordSection, DMPlexShiftPoint_Private(vStart, depth, depthEnd, depthShift), DMPlexShiftPoint_Private(vEnd, depth, depthEnd, depthShift));CHKERRQ(ierr); 3576 for (v = vStart; v < vEnd; ++v) { 3577 const PetscInt newv = DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift); 3578 ierr = PetscSectionSetDof(newCoordSection, newv, dim);CHKERRQ(ierr); 3579 ierr = PetscSectionSetFieldDof(newCoordSection, newv, 0, dim);CHKERRQ(ierr); 3580 } 3581 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3582 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3583 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3584 ierr = DMSetCoordinatesLocal(dmNew, coordinates);CHKERRQ(ierr); 3585 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3586 PetscFunctionReturn(0); 3587 } 3588 3589 #undef __FUNCT__ 3590 #define __FUNCT__ "DMPlexShiftSF_Private" 3591 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3592 { 3593 PetscInt *depthEnd; 3594 PetscInt depth = 0, d; 3595 PetscSF sfPoint, sfPointNew; 3596 const PetscSFNode *remotePoints; 3597 PetscSFNode *gremotePoints; 3598 const PetscInt *localPoints; 3599 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3600 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3601 PetscMPIInt numProcs; 3602 PetscErrorCode ierr; 3603 3604 PetscFunctionBegin; 3605 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3606 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3607 for (d = 0; d <= depth; ++d) { 3608 totShift += depthShift[d]; 3609 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3610 } 3611 /* Step 9: Convert pointSF */ 3612 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3613 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3614 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3615 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3616 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3617 if (numRoots >= 0) { 3618 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3619 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3620 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3621 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3622 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3623 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3624 for (l = 0; l < numLeaves; ++l) { 3625 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3626 gremotePoints[l].rank = remotePoints[l].rank; 3627 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3628 } 3629 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3630 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3631 } 3632 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3633 PetscFunctionReturn(0); 3634 } 3635 3636 #undef __FUNCT__ 3637 #define __FUNCT__ "DMPlexShiftLabels_Private" 3638 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3639 { 3640 PetscSF sfPoint; 3641 DMLabel vtkLabel, ghostLabel; 3642 PetscInt *depthEnd; 3643 const PetscSFNode *leafRemote; 3644 const PetscInt *leafLocal; 3645 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3646 PetscMPIInt rank; 3647 PetscErrorCode ierr; 3648 3649 PetscFunctionBegin; 3650 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3651 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3652 for (d = 0; d <= depth; ++d) { 3653 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3654 } 3655 /* Step 10: Convert labels */ 3656 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3657 for (l = 0; l < numLabels; ++l) { 3658 DMLabel label, newlabel; 3659 const char *lname; 3660 PetscBool isDepth; 3661 IS valueIS; 3662 const PetscInt *values; 3663 PetscInt numValues, val; 3664 3665 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3666 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3667 if (isDepth) continue; 3668 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3669 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3670 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3671 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3672 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3673 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3674 for (val = 0; val < numValues; ++val) { 3675 IS pointIS; 3676 const PetscInt *points; 3677 PetscInt numPoints, p; 3678 3679 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3680 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3681 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3682 for (p = 0; p < numPoints; ++p) { 3683 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3684 3685 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3686 } 3687 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3688 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3689 } 3690 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3691 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3692 } 3693 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3694 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3695 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3696 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3697 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3698 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3699 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3700 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3701 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3702 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3703 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3704 for (; c < leafLocal[l] && c < cEnd; ++c) { 3705 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3706 } 3707 if (leafLocal[l] >= cEnd) break; 3708 if (leafRemote[l].rank == rank) { 3709 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3710 } else { 3711 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3712 } 3713 } 3714 for (; c < cEnd; ++c) { 3715 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3716 } 3717 if (0) { 3718 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3719 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3720 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3721 } 3722 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3723 for (f = fStart; f < fEnd; ++f) { 3724 PetscInt numCells; 3725 3726 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3727 if (numCells < 2) { 3728 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3729 } else { 3730 const PetscInt *cells = PETSC_NULL; 3731 PetscInt vA, vB; 3732 3733 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3734 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3735 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3736 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3737 } 3738 } 3739 if (0) { 3740 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3741 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3742 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3743 } 3744 PetscFunctionReturn(0); 3745 } 3746 3747 #undef __FUNCT__ 3748 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3749 /*@C 3750 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3751 3752 Collective on dm 3753 3754 Input Parameters: 3755 + dm - The original DM 3756 - labelName - The label specifying the boundary faces (this could be auto-generated) 3757 3758 Output Parameters: 3759 + numGhostCells - The number of ghost cells added to the DM 3760 - dmGhosted - The new DM 3761 3762 Level: developer 3763 3764 .seealso: DMCreate() 3765 */ 3766 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3767 { 3768 DMLabel label; 3769 IS valueIS; 3770 const PetscInt *values; 3771 PetscInt *depthShift; 3772 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3773 PetscErrorCode ierr; 3774 3775 PetscFunctionBegin; 3776 /* Count ghost cells */ 3777 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3778 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3779 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3780 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3781 *numGhostCells = 0; 3782 for (fs = 0; fs < numFS; ++fs) { 3783 PetscInt numBdFaces; 3784 3785 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3786 *numGhostCells += numBdFaces; 3787 } 3788 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3789 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3790 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3791 if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3792 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3793 /* Step 3: Set cone/support sizes for new points */ 3794 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3795 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3796 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3797 } 3798 for (fs = 0; fs < numFS; ++fs) { 3799 IS faceIS; 3800 const PetscInt *faces; 3801 PetscInt numFaces, f; 3802 3803 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3804 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3805 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3806 for (f = 0; f < numFaces; ++f) { 3807 PetscInt size; 3808 3809 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3810 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3811 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3812 } 3813 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3814 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3815 } 3816 /* Step 4: Setup ghosted DM */ 3817 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3818 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3819 /* Step 6: Set cones and supports for new points */ 3820 ghostCell = cEnd; 3821 for (fs = 0; fs < numFS; ++fs) { 3822 IS faceIS; 3823 const PetscInt *faces; 3824 PetscInt numFaces, f; 3825 3826 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3827 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3828 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3829 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3830 PetscInt newFace = faces[f] + *numGhostCells; 3831 3832 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3833 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3834 } 3835 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3836 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3837 } 3838 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3839 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3840 /* Step 7: Stratify */ 3841 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3842 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3843 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3844 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3845 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3846 PetscFunctionReturn(0); 3847 } 3848 3849 #undef __FUNCT__ 3850 #define __FUNCT__ "DMPlexConstructGhostCells" 3851 /*@C 3852 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3853 3854 Collective on dm 3855 3856 Input Parameters: 3857 + dm - The original DM 3858 - labelName - The label specifying the boundary faces (this could be auto-generated) 3859 3860 Output Parameters: 3861 + numGhostCells - The number of ghost cells added to the DM 3862 - dmGhosted - The new DM 3863 3864 Level: developer 3865 3866 .seealso: DMCreate() 3867 */ 3868 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3869 { 3870 DM gdm; 3871 PetscInt dim; 3872 PetscErrorCode ierr; 3873 3874 PetscFunctionBegin; 3875 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3876 PetscValidPointer(numGhostCells, 3); 3877 PetscValidPointer(dmGhosted, 4); 3878 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3879 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3880 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3881 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3882 switch (dim) { 3883 case 2: 3884 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3885 break; 3886 default: 3887 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3888 } 3889 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3890 *dmGhosted = gdm; 3891 PetscFunctionReturn(0); 3892 } 3893 3894 #undef __FUNCT__ 3895 #define __FUNCT__ "DMPlexInterpolate_2D" 3896 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 3897 { 3898 DM idm; 3899 DM_Plex *mesh; 3900 PetscHashIJ edgeTable; 3901 PetscInt *off; 3902 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 3903 PetscInt numEdges, firstEdge, edge, e; 3904 PetscErrorCode ierr; 3905 3906 PetscFunctionBegin; 3907 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3908 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3909 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3910 numCells = cEnd - cStart; 3911 numVertices = vEnd - vStart; 3912 firstEdge = numCells + numVertices; 3913 numEdges = 0 ; 3914 /* Count edges using algorithm from CreateNeighborCSR */ 3915 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 3916 if (off) { 3917 PetscInt numCorners = 0; 3918 3919 numEdges = off[numCells]/2; 3920 #if 0 3921 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 3922 numEdges += 3*numCells - off[numCells]; 3923 #else 3924 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 3925 for (c = cStart; c < cEnd; ++c) { 3926 PetscInt coneSize; 3927 3928 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 3929 numCorners += coneSize; 3930 } 3931 numEdges += numCorners - off[numCells]; 3932 #endif 3933 } 3934 #if 0 3935 /* Check Euler characteristic V - E + F = 1 */ 3936 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 3937 #endif 3938 /* Create interpolated mesh */ 3939 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 3940 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 3941 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 3942 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 3943 for (c = 0; c < numCells; ++c) { 3944 PetscInt numCorners; 3945 3946 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 3947 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 3948 } 3949 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 3950 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 3951 } 3952 ierr = DMSetUp(idm);CHKERRQ(ierr); 3953 /* Get edge cones from subsets of cell vertices */ 3954 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 3955 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 3956 3957 for (c = 0, edge = firstEdge; c < numCells; ++c) { 3958 const PetscInt *cellFaces; 3959 PetscInt numCellFaces, faceSize, cf; 3960 3961 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 3962 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 3963 for (cf = 0; cf < numCellFaces; ++cf) { 3964 #if 1 3965 PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]), 3966 PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])}; 3967 3968 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 3969 if (e < 0) { 3970 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3971 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 3972 e = edge++; 3973 } 3974 #else 3975 PetscBool found = PETSC_FALSE; 3976 3977 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 3978 for (e = firstEdge; e < edge; ++e) { 3979 const PetscInt *cone; 3980 3981 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 3982 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 3983 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 3984 found = PETSC_TRUE; 3985 break; 3986 } 3987 } 3988 if (!found) { 3989 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3990 ++edge; 3991 } 3992 #endif 3993 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 3994 } 3995 } 3996 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 3997 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 3998 ierr = PetscFree(off);CHKERRQ(ierr); 3999 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4000 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4001 mesh = (DM_Plex *) (idm)->data; 4002 /* Orient edges */ 4003 for (c = 0; c < numCells; ++c) { 4004 const PetscInt *cone = PETSC_NULL, *cellFaces; 4005 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4006 4007 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4008 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4009 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4010 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4011 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4012 for (cf = 0; cf < numCellFaces; ++cf) { 4013 const PetscInt *econe = PETSC_NULL; 4014 PetscInt esize; 4015 4016 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4017 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4018 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]); 4019 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4020 /* Correctly oriented */ 4021 mesh->coneOrientations[coff+cf] = 0; 4022 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4023 /* Start at index 1, and reverse orientation */ 4024 mesh->coneOrientations[coff+cf] = -(1+1); 4025 } 4026 } 4027 } 4028 *dmInt = idm; 4029 PetscFunctionReturn(0); 4030 } 4031 4032 #undef __FUNCT__ 4033 #define __FUNCT__ "DMPlexInterpolate_3D" 4034 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4035 { 4036 DM idm, fdm; 4037 DM_Plex *mesh; 4038 PetscInt *off; 4039 const PetscInt numCorners = 4; 4040 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4041 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4042 PetscErrorCode ierr; 4043 4044 PetscFunctionBegin; 4045 { 4046 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4047 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4048 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4049 } 4050 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4051 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4052 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4053 numCells = cEnd - cStart; 4054 numVertices = vEnd - vStart; 4055 firstFace = numCells + numVertices; 4056 numFaces = 0 ; 4057 /* Count faces using algorithm from CreateNeighborCSR */ 4058 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4059 if (off) { 4060 numFaces = off[numCells]/2; 4061 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4062 numFaces += 4*numCells - off[numCells]; 4063 } 4064 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4065 firstEdge = firstFace + numFaces; 4066 numEdges = numVertices + numFaces - numCells - 1; 4067 /* Create interpolated mesh */ 4068 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4069 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4070 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4071 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4072 for (c = 0; c < numCells; ++c) { 4073 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4074 } 4075 for (f = firstFace; f < firstFace+numFaces; ++f) { 4076 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4077 } 4078 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4079 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4080 } 4081 ierr = DMSetUp(idm);CHKERRQ(ierr); 4082 /* Get face cones from subsets of cell vertices */ 4083 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4084 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4085 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4086 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4087 for (f = firstFace; f < firstFace+numFaces; ++f) { 4088 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4089 } 4090 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4091 for (c = 0, face = firstFace; c < numCells; ++c) { 4092 const PetscInt *cellFaces; 4093 PetscInt numCellFaces, faceSize, cf; 4094 4095 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4096 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4097 for (cf = 0; cf < numCellFaces; ++cf) { 4098 PetscBool found = PETSC_FALSE; 4099 4100 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4101 for (f = firstFace; f < face; ++f) { 4102 const PetscInt *cone = PETSC_NULL; 4103 4104 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4105 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4106 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4107 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4108 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4109 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4110 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4111 found = PETSC_TRUE; 4112 break; 4113 } 4114 } 4115 if (!found) { 4116 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4117 /* Save the vertices for orientation calculation */ 4118 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4119 ++face; 4120 } 4121 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4122 } 4123 } 4124 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4125 /* Get edge cones from subsets of face vertices */ 4126 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4127 const PetscInt *cellFaces; 4128 PetscInt numCellFaces, faceSize, cf; 4129 4130 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4131 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4132 for (cf = 0; cf < numCellFaces; ++cf) { 4133 PetscBool found = PETSC_FALSE; 4134 4135 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4136 for (e = firstEdge; e < edge; ++e) { 4137 const PetscInt *cone = PETSC_NULL; 4138 4139 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4140 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4141 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4142 found = PETSC_TRUE; 4143 break; 4144 } 4145 } 4146 if (!found) { 4147 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4148 ++edge; 4149 } 4150 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4151 } 4152 } 4153 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4154 ierr = PetscFree(off);CHKERRQ(ierr); 4155 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4156 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4157 mesh = (DM_Plex *) (idm)->data; 4158 /* Orient edges */ 4159 for (f = firstFace; f < firstFace+numFaces; ++f) { 4160 const PetscInt *cone, *cellFaces; 4161 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4162 4163 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4164 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4165 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4166 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4167 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4168 for (cf = 0; cf < numCellFaces; ++cf) { 4169 const PetscInt *econe; 4170 PetscInt esize; 4171 4172 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4173 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4174 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]); 4175 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4176 /* Correctly oriented */ 4177 mesh->coneOrientations[coff+cf] = 0; 4178 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4179 /* Start at index 1, and reverse orientation */ 4180 mesh->coneOrientations[coff+cf] = -(1+1); 4181 } 4182 } 4183 } 4184 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4185 /* Orient faces */ 4186 for (c = 0; c < numCells; ++c) { 4187 const PetscInt *cone, *cellFaces; 4188 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4189 4190 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4191 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4192 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4193 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4194 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4195 for (cf = 0; cf < numCellFaces; ++cf) { 4196 PetscInt *origClosure = PETSC_NULL, *closure; 4197 PetscInt closureSize, i; 4198 4199 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4200 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4201 for (i = 4; i < 7; ++i) { 4202 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); 4203 } 4204 closure = &origClosure[4*2]; 4205 /* Remember that this is the orientation for edges, not vertices */ 4206 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4207 /* Correctly oriented */ 4208 mesh->coneOrientations[coff+cf] = 0; 4209 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4210 /* Shifted by 1 */ 4211 mesh->coneOrientations[coff+cf] = 1; 4212 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4213 /* Shifted by 2 */ 4214 mesh->coneOrientations[coff+cf] = 2; 4215 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4216 /* Start at edge 1, and reverse orientation */ 4217 mesh->coneOrientations[coff+cf] = -(1+1); 4218 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4219 /* Start at index 0, and reverse orientation */ 4220 mesh->coneOrientations[coff+cf] = -(0+1); 4221 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4222 /* Start at index 2, and reverse orientation */ 4223 mesh->coneOrientations[coff+cf] = -(2+1); 4224 } 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); 4225 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4226 } 4227 } 4228 { 4229 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4230 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4231 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4232 } 4233 *dmInt = idm; 4234 PetscFunctionReturn(0); 4235 } 4236 4237 #undef __FUNCT__ 4238 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4239 /* 4240 This takes as input the common mesh generator output, a list of the vertices for each cell 4241 */ 4242 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4243 { 4244 PetscInt *cone, c, p; 4245 PetscErrorCode ierr; 4246 4247 PetscFunctionBegin; 4248 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4249 for (c = 0; c < numCells; ++c) { 4250 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4251 } 4252 ierr = DMSetUp(dm);CHKERRQ(ierr); 4253 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4254 for (c = 0; c < numCells; ++c) { 4255 for (p = 0; p < numCorners; ++p) { 4256 cone[p] = cells[c*numCorners+p]+numCells; 4257 } 4258 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4259 } 4260 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4261 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4262 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4263 PetscFunctionReturn(0); 4264 } 4265 4266 #undef __FUNCT__ 4267 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4268 /* 4269 This takes as input the coordinates for each vertex 4270 */ 4271 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4272 { 4273 PetscSection coordSection; 4274 Vec coordinates; 4275 PetscScalar *coords; 4276 PetscInt coordSize, v, d; 4277 PetscErrorCode ierr; 4278 4279 PetscFunctionBegin; 4280 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4281 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4282 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4283 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4284 for (v = numCells; v < numCells+numVertices; ++v) { 4285 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4286 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4287 } 4288 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4289 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4290 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4291 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4292 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4293 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4294 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4295 for (v = 0; v < numVertices; ++v) { 4296 for (d = 0; d < spaceDim; ++d) { 4297 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4298 } 4299 } 4300 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4301 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4302 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4303 PetscFunctionReturn(0); 4304 } 4305 4306 #undef __FUNCT__ 4307 #define __FUNCT__ "DMPlexCreateFromCellList" 4308 /* 4309 This takes as input the common mesh generator output, a list of the vertices for each cell 4310 */ 4311 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4312 { 4313 PetscErrorCode ierr; 4314 4315 PetscFunctionBegin; 4316 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4317 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4318 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4319 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4320 if (interpolate) { 4321 DM idm; 4322 4323 switch (dim) { 4324 case 2: 4325 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4326 case 3: 4327 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4328 default: 4329 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4330 } 4331 ierr = DMDestroy(dm);CHKERRQ(ierr); 4332 *dm = idm; 4333 } 4334 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4335 PetscFunctionReturn(0); 4336 } 4337 4338 #if defined(PETSC_HAVE_TRIANGLE) 4339 #include <triangle.h> 4340 4341 #undef __FUNCT__ 4342 #define __FUNCT__ "InitInput_Triangle" 4343 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4344 { 4345 PetscFunctionBegin; 4346 inputCtx->numberofpoints = 0; 4347 inputCtx->numberofpointattributes = 0; 4348 inputCtx->pointlist = PETSC_NULL; 4349 inputCtx->pointattributelist = PETSC_NULL; 4350 inputCtx->pointmarkerlist = PETSC_NULL; 4351 inputCtx->numberofsegments = 0; 4352 inputCtx->segmentlist = PETSC_NULL; 4353 inputCtx->segmentmarkerlist = PETSC_NULL; 4354 inputCtx->numberoftriangleattributes = 0; 4355 inputCtx->trianglelist = PETSC_NULL; 4356 inputCtx->numberofholes = 0; 4357 inputCtx->holelist = PETSC_NULL; 4358 inputCtx->numberofregions = 0; 4359 inputCtx->regionlist = PETSC_NULL; 4360 PetscFunctionReturn(0); 4361 } 4362 4363 #undef __FUNCT__ 4364 #define __FUNCT__ "InitOutput_Triangle" 4365 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4366 { 4367 PetscFunctionBegin; 4368 outputCtx->numberofpoints = 0; 4369 outputCtx->pointlist = PETSC_NULL; 4370 outputCtx->pointattributelist = PETSC_NULL; 4371 outputCtx->pointmarkerlist = PETSC_NULL; 4372 outputCtx->numberoftriangles = 0; 4373 outputCtx->trianglelist = PETSC_NULL; 4374 outputCtx->triangleattributelist = PETSC_NULL; 4375 outputCtx->neighborlist = PETSC_NULL; 4376 outputCtx->segmentlist = PETSC_NULL; 4377 outputCtx->segmentmarkerlist = PETSC_NULL; 4378 outputCtx->numberofedges = 0; 4379 outputCtx->edgelist = PETSC_NULL; 4380 outputCtx->edgemarkerlist = PETSC_NULL; 4381 PetscFunctionReturn(0); 4382 } 4383 4384 #undef __FUNCT__ 4385 #define __FUNCT__ "FiniOutput_Triangle" 4386 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4387 { 4388 PetscFunctionBegin; 4389 free(outputCtx->pointmarkerlist); 4390 free(outputCtx->edgelist); 4391 free(outputCtx->edgemarkerlist); 4392 free(outputCtx->trianglelist); 4393 free(outputCtx->neighborlist); 4394 PetscFunctionReturn(0); 4395 } 4396 4397 #undef __FUNCT__ 4398 #define __FUNCT__ "DMPlexGenerate_Triangle" 4399 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4400 { 4401 MPI_Comm comm = ((PetscObject) boundary)->comm; 4402 PetscInt dim = 2; 4403 const PetscBool createConvexHull = PETSC_FALSE; 4404 const PetscBool constrained = PETSC_FALSE; 4405 struct triangulateio in; 4406 struct triangulateio out; 4407 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4408 PetscMPIInt rank; 4409 PetscErrorCode ierr; 4410 4411 PetscFunctionBegin; 4412 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4413 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4414 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4415 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4416 in.numberofpoints = vEnd - vStart; 4417 if (in.numberofpoints > 0) { 4418 PetscSection coordSection; 4419 Vec coordinates; 4420 PetscScalar *array; 4421 4422 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4423 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4424 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4425 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4426 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4427 for (v = vStart; v < vEnd; ++v) { 4428 const PetscInt idx = v - vStart; 4429 PetscInt off, d; 4430 4431 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4432 for (d = 0; d < dim; ++d) { 4433 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4434 } 4435 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4436 } 4437 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4438 } 4439 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4440 in.numberofsegments = eEnd - eStart; 4441 if (in.numberofsegments > 0) { 4442 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4443 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4444 for (e = eStart; e < eEnd; ++e) { 4445 const PetscInt idx = e - eStart; 4446 const PetscInt *cone; 4447 4448 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4449 in.segmentlist[idx*2+0] = cone[0] - vStart; 4450 in.segmentlist[idx*2+1] = cone[1] - vStart; 4451 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4452 } 4453 } 4454 #if 0 /* Do not currently support holes */ 4455 PetscReal *holeCoords; 4456 PetscInt h, d; 4457 4458 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4459 if (in.numberofholes > 0) { 4460 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4461 for (h = 0; h < in.numberofholes; ++h) { 4462 for (d = 0; d < dim; ++d) { 4463 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4464 } 4465 } 4466 } 4467 #endif 4468 if (!rank) { 4469 char args[32]; 4470 4471 /* Take away 'Q' for verbose output */ 4472 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4473 if (createConvexHull) { 4474 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4475 } 4476 if (constrained) { 4477 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4478 } 4479 triangulate(args, &in, &out, PETSC_NULL); 4480 } 4481 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4482 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4483 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4484 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4485 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4486 4487 { 4488 const PetscInt numCorners = 3; 4489 const PetscInt numCells = out.numberoftriangles; 4490 const PetscInt numVertices = out.numberofpoints; 4491 const int *cells = out.trianglelist; 4492 const double *meshCoords = out.pointlist; 4493 4494 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4495 /* Set labels */ 4496 for (v = 0; v < numVertices; ++v) { 4497 if (out.pointmarkerlist[v]) { 4498 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4499 } 4500 } 4501 if (interpolate) { 4502 for (e = 0; e < out.numberofedges; e++) { 4503 if (out.edgemarkerlist[e]) { 4504 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4505 const PetscInt *edges; 4506 PetscInt numEdges; 4507 4508 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4509 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4510 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4511 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4512 } 4513 } 4514 } 4515 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4516 } 4517 #if 0 /* Do not currently support holes */ 4518 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4519 #endif 4520 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4521 PetscFunctionReturn(0); 4522 } 4523 4524 #undef __FUNCT__ 4525 #define __FUNCT__ "DMPlexRefine_Triangle" 4526 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4527 { 4528 MPI_Comm comm = ((PetscObject) dm)->comm; 4529 PetscInt dim = 2; 4530 struct triangulateio in; 4531 struct triangulateio out; 4532 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4533 PetscMPIInt rank; 4534 PetscErrorCode ierr; 4535 4536 PetscFunctionBegin; 4537 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4538 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4539 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4540 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4541 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4542 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4543 in.numberofpoints = vEnd - vStart; 4544 if (in.numberofpoints > 0) { 4545 PetscSection coordSection; 4546 Vec coordinates; 4547 PetscScalar *array; 4548 4549 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4550 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4551 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4552 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4553 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4554 for (v = vStart; v < vEnd; ++v) { 4555 const PetscInt idx = v - vStart; 4556 PetscInt off, d; 4557 4558 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4559 for (d = 0; d < dim; ++d) { 4560 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4561 } 4562 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4563 } 4564 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4565 } 4566 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4567 in.numberofcorners = 3; 4568 in.numberoftriangles = cEnd - cStart; 4569 in.trianglearealist = (double *) maxVolumes; 4570 if (in.numberoftriangles > 0) { 4571 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4572 for (c = cStart; c < cEnd; ++c) { 4573 const PetscInt idx = c - cStart; 4574 PetscInt *closure = PETSC_NULL; 4575 PetscInt closureSize; 4576 4577 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4578 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4579 for (v = 0; v < 3; ++v) { 4580 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4581 } 4582 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4583 } 4584 } 4585 /* TODO: Segment markers are missing on input */ 4586 #if 0 /* Do not currently support holes */ 4587 PetscReal *holeCoords; 4588 PetscInt h, d; 4589 4590 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4591 if (in.numberofholes > 0) { 4592 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4593 for (h = 0; h < in.numberofholes; ++h) { 4594 for (d = 0; d < dim; ++d) { 4595 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4596 } 4597 } 4598 } 4599 #endif 4600 if (!rank) { 4601 char args[32]; 4602 4603 /* Take away 'Q' for verbose output */ 4604 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4605 triangulate(args, &in, &out, PETSC_NULL); 4606 } 4607 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4608 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4609 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4610 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4611 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4612 4613 { 4614 const PetscInt numCorners = 3; 4615 const PetscInt numCells = out.numberoftriangles; 4616 const PetscInt numVertices = out.numberofpoints; 4617 const int *cells = out.trianglelist; 4618 const double *meshCoords = out.pointlist; 4619 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4620 4621 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4622 /* Set labels */ 4623 for (v = 0; v < numVertices; ++v) { 4624 if (out.pointmarkerlist[v]) { 4625 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4626 } 4627 } 4628 if (interpolate) { 4629 PetscInt e; 4630 4631 for (e = 0; e < out.numberofedges; e++) { 4632 if (out.edgemarkerlist[e]) { 4633 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4634 const PetscInt *edges; 4635 PetscInt numEdges; 4636 4637 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4638 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4639 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4640 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4641 } 4642 } 4643 } 4644 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4645 } 4646 #if 0 /* Do not currently support holes */ 4647 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4648 #endif 4649 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4650 PetscFunctionReturn(0); 4651 } 4652 #endif 4653 4654 #if defined(PETSC_HAVE_TETGEN) 4655 #include <tetgen.h> 4656 #undef __FUNCT__ 4657 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4658 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4659 { 4660 MPI_Comm comm = ((PetscObject) boundary)->comm; 4661 const PetscInt dim = 3; 4662 ::tetgenio in; 4663 ::tetgenio out; 4664 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4665 PetscMPIInt rank; 4666 PetscErrorCode ierr; 4667 4668 PetscFunctionBegin; 4669 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4670 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4671 in.numberofpoints = vEnd - vStart; 4672 if (in.numberofpoints > 0) { 4673 PetscSection coordSection; 4674 Vec coordinates; 4675 PetscScalar *array; 4676 4677 in.pointlist = new double[in.numberofpoints*dim]; 4678 in.pointmarkerlist = new int[in.numberofpoints]; 4679 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4680 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4681 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4682 for (v = vStart; v < vEnd; ++v) { 4683 const PetscInt idx = v - vStart; 4684 PetscInt off, d; 4685 4686 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4687 for (d = 0; d < dim; ++d) { 4688 in.pointlist[idx*dim + d] = array[off+d]; 4689 } 4690 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4691 } 4692 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4693 } 4694 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4695 in.numberoffacets = fEnd - fStart; 4696 if (in.numberoffacets > 0) { 4697 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4698 in.facetmarkerlist = new int[in.numberoffacets]; 4699 for (f = fStart; f < fEnd; ++f) { 4700 const PetscInt idx = f - fStart; 4701 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 4702 4703 in.facetlist[idx].numberofpolygons = 1; 4704 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4705 in.facetlist[idx].numberofholes = 0; 4706 in.facetlist[idx].holelist = NULL; 4707 4708 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4709 for (p = 0; p < numPoints*2; p += 2) { 4710 const PetscInt point = points[p]; 4711 if ((point >= vStart) && (point < vEnd)) { 4712 points[numVertices++] = point; 4713 } 4714 } 4715 4716 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4717 poly->numberofvertices = numVertices; 4718 poly->vertexlist = new int[poly->numberofvertices]; 4719 for (v = 0; v < numVertices; ++v) { 4720 const PetscInt vIdx = points[v] - vStart; 4721 poly->vertexlist[v] = vIdx; 4722 } 4723 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4724 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4725 } 4726 } 4727 if (!rank) { 4728 char args[32]; 4729 4730 /* Take away 'Q' for verbose output */ 4731 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4732 ::tetrahedralize(args, &in, &out); 4733 } 4734 { 4735 const PetscInt numCorners = 4; 4736 const PetscInt numCells = out.numberoftetrahedra; 4737 const PetscInt numVertices = out.numberofpoints; 4738 const int *cells = out.tetrahedronlist; 4739 const double *meshCoords = out.pointlist; 4740 4741 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4742 /* Set labels */ 4743 for (v = 0; v < numVertices; ++v) { 4744 if (out.pointmarkerlist[v]) { 4745 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4746 } 4747 } 4748 if (interpolate) { 4749 PetscInt e; 4750 4751 for (e = 0; e < out.numberofedges; e++) { 4752 if (out.edgemarkerlist[e]) { 4753 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4754 const PetscInt *edges; 4755 PetscInt numEdges; 4756 4757 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4758 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4759 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4760 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4761 } 4762 } 4763 for (f = 0; f < out.numberoftrifaces; f++) { 4764 if (out.trifacemarkerlist[f]) { 4765 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4766 const PetscInt *faces; 4767 PetscInt numFaces; 4768 4769 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4770 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4771 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4772 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4773 } 4774 } 4775 } 4776 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4777 } 4778 PetscFunctionReturn(0); 4779 } 4780 4781 #undef __FUNCT__ 4782 #define __FUNCT__ "DMPlexRefine_Tetgen" 4783 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4784 { 4785 MPI_Comm comm = ((PetscObject) dm)->comm; 4786 const PetscInt dim = 3; 4787 ::tetgenio in; 4788 ::tetgenio out; 4789 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4790 PetscMPIInt rank; 4791 PetscErrorCode ierr; 4792 4793 PetscFunctionBegin; 4794 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4795 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4796 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4797 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4798 in.numberofpoints = vEnd - vStart; 4799 if (in.numberofpoints > 0) { 4800 PetscSection coordSection; 4801 Vec coordinates; 4802 PetscScalar *array; 4803 4804 in.pointlist = new double[in.numberofpoints*dim]; 4805 in.pointmarkerlist = new int[in.numberofpoints]; 4806 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4807 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4808 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4809 for (v = vStart; v < vEnd; ++v) { 4810 const PetscInt idx = v - vStart; 4811 PetscInt off, d; 4812 4813 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4814 for (d = 0; d < dim; ++d) { 4815 in.pointlist[idx*dim + d] = array[off+d]; 4816 } 4817 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4818 } 4819 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4820 } 4821 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4822 in.numberofcorners = 4; 4823 in.numberoftetrahedra = cEnd - cStart; 4824 in.tetrahedronvolumelist = (double *) maxVolumes; 4825 if (in.numberoftetrahedra > 0) { 4826 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4827 for (c = cStart; c < cEnd; ++c) { 4828 const PetscInt idx = c - cStart; 4829 PetscInt *closure = PETSC_NULL; 4830 PetscInt closureSize; 4831 4832 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4833 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 4834 for (v = 0; v < 4; ++v) { 4835 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4836 } 4837 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4838 } 4839 } 4840 /* TODO: Put in boundary faces with markers */ 4841 if (!rank) { 4842 char args[32]; 4843 4844 /* Take away 'Q' for verbose output */ 4845 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 4846 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4847 ::tetrahedralize(args, &in, &out); 4848 } 4849 in.tetrahedronvolumelist = NULL; 4850 4851 { 4852 const PetscInt numCorners = 4; 4853 const PetscInt numCells = out.numberoftetrahedra; 4854 const PetscInt numVertices = out.numberofpoints; 4855 const int *cells = out.tetrahedronlist; 4856 const double *meshCoords = out.pointlist; 4857 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4858 4859 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4860 /* Set labels */ 4861 for (v = 0; v < numVertices; ++v) { 4862 if (out.pointmarkerlist[v]) { 4863 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4864 } 4865 } 4866 if (interpolate) { 4867 PetscInt e, f; 4868 4869 for (e = 0; e < out.numberofedges; e++) { 4870 if (out.edgemarkerlist[e]) { 4871 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4872 const PetscInt *edges; 4873 PetscInt numEdges; 4874 4875 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4876 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4877 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4878 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4879 } 4880 } 4881 for (f = 0; f < out.numberoftrifaces; f++) { 4882 if (out.trifacemarkerlist[f]) { 4883 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4884 const PetscInt *faces; 4885 PetscInt numFaces; 4886 4887 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4888 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4889 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4890 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4891 } 4892 } 4893 } 4894 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4895 } 4896 PetscFunctionReturn(0); 4897 } 4898 #endif 4899 4900 #if defined(PETSC_HAVE_CTETGEN) 4901 #include "ctetgen.h" 4902 4903 #undef __FUNCT__ 4904 #define __FUNCT__ "DMPlexGenerate_CTetgen" 4905 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 4906 { 4907 MPI_Comm comm = ((PetscObject) boundary)->comm; 4908 const PetscInt dim = 3; 4909 PLC *in, *out; 4910 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 4911 PetscMPIInt rank; 4912 PetscErrorCode ierr; 4913 4914 PetscFunctionBegin; 4915 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 4916 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4917 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4918 ierr = PLCCreate(&in);CHKERRQ(ierr); 4919 ierr = PLCCreate(&out);CHKERRQ(ierr); 4920 in->numberofpoints = vEnd - vStart; 4921 if (in->numberofpoints > 0) { 4922 PetscSection coordSection; 4923 Vec coordinates; 4924 PetscScalar *array; 4925 4926 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 4927 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 4928 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4929 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4930 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4931 for (v = vStart; v < vEnd; ++v) { 4932 const PetscInt idx = v - vStart; 4933 PetscInt off, d, m; 4934 4935 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4936 for (d = 0; d < dim; ++d) { 4937 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4938 } 4939 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 4940 in->pointmarkerlist[idx] = (int) m; 4941 } 4942 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4943 } 4944 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4945 in->numberoffacets = fEnd - fStart; 4946 if (in->numberoffacets > 0) { 4947 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 4948 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 4949 for (f = fStart; f < fEnd; ++f) { 4950 const PetscInt idx = f - fStart; 4951 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 4952 polygon *poly; 4953 4954 in->facetlist[idx].numberofpolygons = 1; 4955 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 4956 in->facetlist[idx].numberofholes = 0; 4957 in->facetlist[idx].holelist = PETSC_NULL; 4958 4959 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4960 for (p = 0; p < numPoints*2; p += 2) { 4961 const PetscInt point = points[p]; 4962 if ((point >= vStart) && (point < vEnd)) { 4963 points[numVertices++] = point; 4964 } 4965 } 4966 4967 poly = in->facetlist[idx].polygonlist; 4968 poly->numberofvertices = numVertices; 4969 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 4970 for (v = 0; v < numVertices; ++v) { 4971 const PetscInt vIdx = points[v] - vStart; 4972 poly->vertexlist[v] = vIdx; 4973 } 4974 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 4975 in->facetmarkerlist[idx] = (int) m; 4976 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4977 } 4978 } 4979 if (!rank) { 4980 TetGenOpts t; 4981 4982 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 4983 t.in = boundary; /* Should go away */ 4984 t.plc = 1; 4985 t.quality = 1; 4986 t.edgesout = 1; 4987 t.zeroindex = 1; 4988 t.quiet = 1; 4989 t.verbose = verbose; 4990 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 4991 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 4992 } 4993 { 4994 const PetscInt numCorners = 4; 4995 const PetscInt numCells = out->numberoftetrahedra; 4996 const PetscInt numVertices = out->numberofpoints; 4997 const int *cells = out->tetrahedronlist; 4998 const double *meshCoords = out->pointlist; 4999 5000 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5001 /* Set labels */ 5002 for (v = 0; v < numVertices; ++v) { 5003 if (out->pointmarkerlist[v]) { 5004 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5005 } 5006 } 5007 if (interpolate) { 5008 PetscInt e; 5009 5010 for (e = 0; e < out->numberofedges; e++) { 5011 if (out->edgemarkerlist[e]) { 5012 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5013 const PetscInt *edges; 5014 PetscInt numEdges; 5015 5016 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5017 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5018 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5019 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5020 } 5021 } 5022 for (f = 0; f < out->numberoftrifaces; f++) { 5023 if (out->trifacemarkerlist[f]) { 5024 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5025 const PetscInt *faces; 5026 PetscInt numFaces; 5027 5028 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5029 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5030 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5031 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5032 } 5033 } 5034 } 5035 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5036 } 5037 5038 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5039 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5040 PetscFunctionReturn(0); 5041 } 5042 5043 #undef __FUNCT__ 5044 #define __FUNCT__ "DMPlexRefine_CTetgen" 5045 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5046 { 5047 MPI_Comm comm = ((PetscObject) dm)->comm; 5048 const PetscInt dim = 3; 5049 PLC *in, *out; 5050 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5051 PetscMPIInt rank; 5052 PetscErrorCode ierr; 5053 5054 PetscFunctionBegin; 5055 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5056 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5057 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5058 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5059 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5060 ierr = PLCCreate(&in);CHKERRQ(ierr); 5061 ierr = PLCCreate(&out);CHKERRQ(ierr); 5062 in->numberofpoints = vEnd - vStart; 5063 if (in->numberofpoints > 0) { 5064 PetscSection coordSection; 5065 Vec coordinates; 5066 PetscScalar *array; 5067 5068 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5069 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5070 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5071 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5072 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5073 for (v = vStart; v < vEnd; ++v) { 5074 const PetscInt idx = v - vStart; 5075 PetscInt off, d, m; 5076 5077 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5078 for (d = 0; d < dim; ++d) { 5079 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5080 } 5081 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5082 in->pointmarkerlist[idx] = (int) m; 5083 } 5084 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5085 } 5086 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5087 in->numberofcorners = 4; 5088 in->numberoftetrahedra = cEnd - cStart; 5089 in->tetrahedronvolumelist = maxVolumes; 5090 if (in->numberoftetrahedra > 0) { 5091 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5092 for (c = cStart; c < cEnd; ++c) { 5093 const PetscInt idx = c - cStart; 5094 PetscInt *closure = PETSC_NULL; 5095 PetscInt closureSize; 5096 5097 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5098 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5099 for (v = 0; v < 4; ++v) { 5100 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5101 } 5102 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5103 } 5104 } 5105 if (!rank) { 5106 TetGenOpts t; 5107 5108 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5109 t.in = dm; /* Should go away */ 5110 t.refine = 1; 5111 t.varvolume = 1; 5112 t.quality = 1; 5113 t.edgesout = 1; 5114 t.zeroindex = 1; 5115 t.quiet = 1; 5116 t.verbose = verbose; /* Change this */ 5117 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5118 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5119 } 5120 { 5121 const PetscInt numCorners = 4; 5122 const PetscInt numCells = out->numberoftetrahedra; 5123 const PetscInt numVertices = out->numberofpoints; 5124 const int *cells = out->tetrahedronlist; 5125 const double *meshCoords = out->pointlist; 5126 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5127 5128 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5129 /* Set labels */ 5130 for (v = 0; v < numVertices; ++v) { 5131 if (out->pointmarkerlist[v]) { 5132 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5133 } 5134 } 5135 if (interpolate) { 5136 PetscInt e, f; 5137 5138 for (e = 0; e < out->numberofedges; e++) { 5139 if (out->edgemarkerlist[e]) { 5140 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5141 const PetscInt *edges; 5142 PetscInt numEdges; 5143 5144 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5145 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5146 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5147 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5148 } 5149 } 5150 for (f = 0; f < out->numberoftrifaces; f++) { 5151 if (out->trifacemarkerlist[f]) { 5152 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5153 const PetscInt *faces; 5154 PetscInt numFaces; 5155 5156 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5157 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5158 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5159 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5160 } 5161 } 5162 } 5163 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5164 } 5165 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5166 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5167 PetscFunctionReturn(0); 5168 } 5169 #endif 5170 5171 #undef __FUNCT__ 5172 #define __FUNCT__ "DMPlexGenerate" 5173 /*@C 5174 DMPlexGenerate - Generates a mesh. 5175 5176 Not Collective 5177 5178 Input Parameters: 5179 + boundary - The DMPlex boundary object 5180 . name - The mesh generation package name 5181 - interpolate - Flag to create intermediate mesh elements 5182 5183 Output Parameter: 5184 . mesh - The DMPlex object 5185 5186 Level: intermediate 5187 5188 .keywords: mesh, elements 5189 .seealso: DMPlexCreate(), DMRefine() 5190 @*/ 5191 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5192 { 5193 PetscInt dim; 5194 char genname[1024]; 5195 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5196 PetscErrorCode ierr; 5197 5198 PetscFunctionBegin; 5199 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5200 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5201 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5202 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5203 if (flg) {name = genname;} 5204 if (name) { 5205 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5206 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5207 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5208 } 5209 switch (dim) { 5210 case 1: 5211 if (!name || isTriangle) { 5212 #if defined(PETSC_HAVE_TRIANGLE) 5213 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5214 #else 5215 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5216 #endif 5217 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5218 break; 5219 case 2: 5220 if (!name || isCTetgen) { 5221 #if defined(PETSC_HAVE_CTETGEN) 5222 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5223 #else 5224 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5225 #endif 5226 } else if (isTetgen) { 5227 #if defined(PETSC_HAVE_TETGEN) 5228 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5229 #else 5230 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5231 #endif 5232 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5233 break; 5234 default: 5235 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5236 } 5237 PetscFunctionReturn(0); 5238 } 5239 5240 typedef PetscInt CellRefiner; 5241 5242 #undef __FUNCT__ 5243 #define __FUNCT__ "GetDepthStart_Private" 5244 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5245 { 5246 PetscFunctionBegin; 5247 if (cStart) *cStart = 0; 5248 if (vStart) *vStart = depthSize[depth]; 5249 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5250 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5251 PetscFunctionReturn(0); 5252 } 5253 5254 #undef __FUNCT__ 5255 #define __FUNCT__ "GetDepthEnd_Private" 5256 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5257 { 5258 PetscFunctionBegin; 5259 if (cEnd) *cEnd = depthSize[depth]; 5260 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5261 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5262 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5263 PetscFunctionReturn(0); 5264 } 5265 5266 #undef __FUNCT__ 5267 #define __FUNCT__ "CellRefinerGetSizes" 5268 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5269 { 5270 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5271 PetscErrorCode ierr; 5272 5273 PetscFunctionBegin; 5274 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5275 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5276 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5277 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5278 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5279 switch (refiner) { 5280 case 1: 5281 /* Simplicial 2D */ 5282 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5283 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5284 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5285 break; 5286 case 3: 5287 /* Hybrid 2D */ 5288 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5289 cMax = PetscMin(cEnd, cMax); 5290 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5291 fMax = PetscMin(fEnd, fMax); 5292 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5293 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 */ 5294 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5295 break; 5296 case 2: 5297 /* Hex 2D */ 5298 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5299 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5300 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5301 break; 5302 default: 5303 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5304 } 5305 PetscFunctionReturn(0); 5306 } 5307 5308 #undef __FUNCT__ 5309 #define __FUNCT__ "CellRefinerSetConeSizes" 5310 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5311 { 5312 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5313 PetscErrorCode ierr; 5314 5315 PetscFunctionBegin; 5316 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5317 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5318 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5319 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5320 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5321 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5322 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5323 switch (refiner) { 5324 case 1: 5325 /* Simplicial 2D */ 5326 /* All cells have 3 faces */ 5327 for (c = cStart; c < cEnd; ++c) { 5328 for (r = 0; r < 4; ++r) { 5329 const PetscInt newp = (c - cStart)*4 + r; 5330 5331 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5332 } 5333 } 5334 /* Split faces have 2 vertices and the same cells as the parent */ 5335 for (f = fStart; f < fEnd; ++f) { 5336 for (r = 0; r < 2; ++r) { 5337 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5338 PetscInt size; 5339 5340 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5341 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5342 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5343 } 5344 } 5345 /* Interior faces have 2 vertices and 2 cells */ 5346 for (c = cStart; c < cEnd; ++c) { 5347 for (r = 0; r < 3; ++r) { 5348 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5349 5350 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5351 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5352 } 5353 } 5354 /* Old vertices have identical supports */ 5355 for (v = vStart; v < vEnd; ++v) { 5356 const PetscInt newp = vStartNew + (v - vStart); 5357 PetscInt size; 5358 5359 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5360 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5361 } 5362 /* Face vertices have 2 + cells*2 supports */ 5363 for (f = fStart; f < fEnd; ++f) { 5364 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5365 PetscInt size; 5366 5367 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5368 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5369 } 5370 break; 5371 case 2: 5372 /* Hex 2D */ 5373 /* All cells have 4 faces */ 5374 for (c = cStart; c < cEnd; ++c) { 5375 for (r = 0; r < 4; ++r) { 5376 const PetscInt newp = (c - cStart)*4 + r; 5377 5378 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5379 } 5380 } 5381 /* Split faces have 2 vertices and the same cells as the parent */ 5382 for (f = fStart; f < fEnd; ++f) { 5383 for (r = 0; r < 2; ++r) { 5384 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5385 PetscInt size; 5386 5387 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5388 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5389 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5390 } 5391 } 5392 /* Interior faces have 2 vertices and 2 cells */ 5393 for (c = cStart; c < cEnd; ++c) { 5394 for (r = 0; r < 4; ++r) { 5395 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5396 5397 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5398 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5399 } 5400 } 5401 /* Old vertices have identical supports */ 5402 for (v = vStart; v < vEnd; ++v) { 5403 const PetscInt newp = vStartNew + (v - vStart); 5404 PetscInt size; 5405 5406 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5407 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5408 } 5409 /* Face vertices have 2 + cells supports */ 5410 for (f = fStart; f < fEnd; ++f) { 5411 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5412 PetscInt size; 5413 5414 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5415 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5416 } 5417 /* Cell vertices have 4 supports */ 5418 for (c = cStart; c < cEnd; ++c) { 5419 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5420 5421 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5422 } 5423 break; 5424 case 3: 5425 /* Hybrid 2D */ 5426 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5427 cMax = PetscMin(cEnd, cMax); 5428 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5429 fMax = PetscMin(fEnd, fMax); 5430 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5431 /* Interior cells have 3 faces */ 5432 for (c = cStart; c < cMax; ++c) { 5433 for (r = 0; r < 4; ++r) { 5434 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5435 5436 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5437 } 5438 } 5439 /* Hybrid cells have 4 faces */ 5440 for (c = cMax; c < cEnd; ++c) { 5441 for (r = 0; r < 2; ++r) { 5442 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5443 5444 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5445 } 5446 } 5447 /* Interior split faces have 2 vertices and the same cells as the parent */ 5448 for (f = fStart; f < fMax; ++f) { 5449 for (r = 0; r < 2; ++r) { 5450 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5451 PetscInt size; 5452 5453 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5454 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5455 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5456 } 5457 } 5458 /* Interior cell faces have 2 vertices and 2 cells */ 5459 for (c = cStart; c < cMax; ++c) { 5460 for (r = 0; r < 3; ++r) { 5461 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5462 5463 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5464 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5465 } 5466 } 5467 /* Hybrid faces have 2 vertices and the same cells */ 5468 for (f = fMax; f < fEnd; ++f) { 5469 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5470 PetscInt size; 5471 5472 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5473 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5474 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5475 } 5476 /* Hybrid cell faces have 2 vertices and 2 cells */ 5477 for (c = cMax; c < cEnd; ++c) { 5478 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5479 5480 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5481 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5482 } 5483 /* Old vertices have identical supports */ 5484 for (v = vStart; v < vEnd; ++v) { 5485 const PetscInt newp = vStartNew + (v - vStart); 5486 PetscInt size; 5487 5488 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5489 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5490 } 5491 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5492 for (f = fStart; f < fMax; ++f) { 5493 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5494 const PetscInt *support; 5495 PetscInt size, newSize = 2, s; 5496 5497 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5498 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5499 for (s = 0; s < size; ++s) { 5500 if (support[s] >= cMax) { 5501 newSize += 1; 5502 } else { 5503 newSize += 2; 5504 } 5505 } 5506 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5507 } 5508 break; 5509 default: 5510 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5511 } 5512 PetscFunctionReturn(0); 5513 } 5514 5515 #undef __FUNCT__ 5516 #define __FUNCT__ "CellRefinerSetCones" 5517 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5518 { 5519 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; 5520 PetscInt maxSupportSize, *supportRef; 5521 PetscErrorCode ierr; 5522 5523 PetscFunctionBegin; 5524 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5525 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5526 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5527 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5528 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5529 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5530 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5531 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5532 switch (refiner) { 5533 case 1: 5534 /* Simplicial 2D */ 5535 /* 5536 2 5537 |\ 5538 | \ 5539 | \ 5540 | \ 5541 | C \ 5542 | \ 5543 | \ 5544 2---1---1 5545 |\ D / \ 5546 | 2 0 \ 5547 |A \ / B \ 5548 0---0-------1 5549 */ 5550 /* All cells have 3 faces */ 5551 for (c = cStart; c < cEnd; ++c) { 5552 const PetscInt newp = cStartNew + (c - cStart)*4; 5553 const PetscInt *cone, *ornt; 5554 PetscInt coneNew[3], orntNew[3]; 5555 5556 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5557 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5558 /* A triangle */ 5559 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5560 orntNew[0] = ornt[0]; 5561 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5562 orntNew[1] = -2; 5563 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5564 orntNew[2] = ornt[2]; 5565 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5566 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5567 #if 1 5568 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); 5569 for (p = 0; p < 3; ++p) { 5570 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); 5571 } 5572 #endif 5573 /* B triangle */ 5574 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5575 orntNew[0] = ornt[0]; 5576 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5577 orntNew[1] = ornt[1]; 5578 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5579 orntNew[2] = -2; 5580 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5581 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5582 #if 1 5583 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); 5584 for (p = 0; p < 3; ++p) { 5585 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); 5586 } 5587 #endif 5588 /* C triangle */ 5589 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5590 orntNew[0] = -2; 5591 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5592 orntNew[1] = ornt[1]; 5593 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5594 orntNew[2] = ornt[2]; 5595 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5596 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5597 #if 1 5598 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); 5599 for (p = 0; p < 3; ++p) { 5600 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); 5601 } 5602 #endif 5603 /* D triangle */ 5604 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5605 orntNew[0] = 0; 5606 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5607 orntNew[1] = 0; 5608 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5609 orntNew[2] = 0; 5610 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5611 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5612 #if 1 5613 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); 5614 for (p = 0; p < 3; ++p) { 5615 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); 5616 } 5617 #endif 5618 } 5619 /* Split faces have 2 vertices and the same cells as the parent */ 5620 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5621 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5622 for (f = fStart; f < fEnd; ++f) { 5623 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5624 5625 for (r = 0; r < 2; ++r) { 5626 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5627 const PetscInt *cone, *support; 5628 PetscInt coneNew[2], coneSize, c, supportSize, s; 5629 5630 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5631 coneNew[0] = vStartNew + (cone[0] - vStart); 5632 coneNew[1] = vStartNew + (cone[1] - vStart); 5633 coneNew[(r+1)%2] = newv; 5634 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5635 #if 1 5636 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5637 for (p = 0; p < 2; ++p) { 5638 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); 5639 } 5640 #endif 5641 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5642 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5643 for (s = 0; s < supportSize; ++s) { 5644 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5645 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5646 for (c = 0; c < coneSize; ++c) { 5647 if (cone[c] == f) { 5648 break; 5649 } 5650 } 5651 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5652 } 5653 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5654 #if 1 5655 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5656 for (p = 0; p < supportSize; ++p) { 5657 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); 5658 } 5659 #endif 5660 } 5661 } 5662 /* Interior faces have 2 vertices and 2 cells */ 5663 for (c = cStart; c < cEnd; ++c) { 5664 const PetscInt *cone; 5665 5666 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5667 for (r = 0; r < 3; ++r) { 5668 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5669 PetscInt coneNew[2]; 5670 PetscInt supportNew[2]; 5671 5672 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5673 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5674 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5675 #if 1 5676 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5677 for (p = 0; p < 2; ++p) { 5678 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); 5679 } 5680 #endif 5681 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5682 supportNew[1] = (c - cStart)*4 + 3; 5683 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5684 #if 1 5685 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5686 for (p = 0; p < 2; ++p) { 5687 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); 5688 } 5689 #endif 5690 } 5691 } 5692 /* Old vertices have identical supports */ 5693 for (v = vStart; v < vEnd; ++v) { 5694 const PetscInt newp = vStartNew + (v - vStart); 5695 const PetscInt *support, *cone; 5696 PetscInt size, s; 5697 5698 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5699 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5700 for (s = 0; s < size; ++s) { 5701 PetscInt r = 0; 5702 5703 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5704 if (cone[1] == v) r = 1; 5705 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5706 } 5707 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5708 #if 1 5709 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5710 for (p = 0; p < size; ++p) { 5711 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); 5712 } 5713 #endif 5714 } 5715 /* Face vertices have 2 + cells*2 supports */ 5716 for (f = fStart; f < fEnd; ++f) { 5717 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5718 const PetscInt *cone, *support; 5719 PetscInt size, s; 5720 5721 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5722 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5723 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5724 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5725 for (s = 0; s < size; ++s) { 5726 PetscInt r = 0; 5727 5728 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5729 if (cone[1] == f) r = 1; 5730 else if (cone[2] == f) r = 2; 5731 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5732 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5733 } 5734 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5735 #if 1 5736 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5737 for (p = 0; p < 2+size*2; ++p) { 5738 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); 5739 } 5740 #endif 5741 } 5742 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5743 break; 5744 case 2: 5745 /* Hex 2D */ 5746 /* 5747 3---------2---------2 5748 | | | 5749 | D 2 C | 5750 | | | 5751 3----3----0----1----1 5752 | | | 5753 | A 0 B | 5754 | | | 5755 0---------0---------1 5756 */ 5757 /* All cells have 4 faces */ 5758 for (c = cStart; c < cEnd; ++c) { 5759 const PetscInt newp = (c - cStart)*4; 5760 const PetscInt *cone, *ornt; 5761 PetscInt coneNew[4], orntNew[4]; 5762 5763 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5764 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5765 /* A quad */ 5766 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5767 orntNew[0] = ornt[0]; 5768 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5769 orntNew[1] = 0; 5770 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5771 orntNew[2] = -2; 5772 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5773 orntNew[3] = ornt[3]; 5774 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5775 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5776 #if 1 5777 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); 5778 for (p = 0; p < 4; ++p) { 5779 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); 5780 } 5781 #endif 5782 /* B quad */ 5783 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5784 orntNew[0] = ornt[0]; 5785 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5786 orntNew[1] = ornt[1]; 5787 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5788 orntNew[2] = 0; 5789 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5790 orntNew[3] = -2; 5791 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5792 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5793 #if 1 5794 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); 5795 for (p = 0; p < 4; ++p) { 5796 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); 5797 } 5798 #endif 5799 /* C quad */ 5800 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5801 orntNew[0] = -2; 5802 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5803 orntNew[1] = ornt[1]; 5804 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5805 orntNew[2] = ornt[2]; 5806 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5807 orntNew[3] = 0; 5808 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5809 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5810 #if 1 5811 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); 5812 for (p = 0; p < 4; ++p) { 5813 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); 5814 } 5815 #endif 5816 /* D quad */ 5817 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5818 orntNew[0] = 0; 5819 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5820 orntNew[1] = -2; 5821 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5822 orntNew[2] = ornt[2]; 5823 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5824 orntNew[3] = ornt[3]; 5825 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5826 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5827 #if 1 5828 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); 5829 for (p = 0; p < 4; ++p) { 5830 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); 5831 } 5832 #endif 5833 } 5834 /* Split faces have 2 vertices and the same cells as the parent */ 5835 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5836 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5837 for (f = fStart; f < fEnd; ++f) { 5838 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5839 5840 for (r = 0; r < 2; ++r) { 5841 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5842 const PetscInt *cone, *support; 5843 PetscInt coneNew[2], coneSize, c, supportSize, s; 5844 5845 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5846 coneNew[0] = vStartNew + (cone[0] - vStart); 5847 coneNew[1] = vStartNew + (cone[1] - vStart); 5848 coneNew[(r+1)%2] = newv; 5849 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5850 #if 1 5851 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5852 for (p = 0; p < 2; ++p) { 5853 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); 5854 } 5855 #endif 5856 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5857 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5858 for (s = 0; s < supportSize; ++s) { 5859 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5860 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5861 for (c = 0; c < coneSize; ++c) { 5862 if (cone[c] == f) { 5863 break; 5864 } 5865 } 5866 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5867 } 5868 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5869 #if 1 5870 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5871 for (p = 0; p < supportSize; ++p) { 5872 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); 5873 } 5874 #endif 5875 } 5876 } 5877 /* Interior faces have 2 vertices and 2 cells */ 5878 for (c = cStart; c < cEnd; ++c) { 5879 const PetscInt *cone; 5880 PetscInt coneNew[2], supportNew[2]; 5881 5882 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5883 for (r = 0; r < 4; ++r) { 5884 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5885 5886 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5887 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5888 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5889 #if 1 5890 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5891 for (p = 0; p < 2; ++p) { 5892 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); 5893 } 5894 #endif 5895 supportNew[0] = (c - cStart)*4 + r; 5896 supportNew[1] = (c - cStart)*4 + (r+1)%4; 5897 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5898 #if 1 5899 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5900 for (p = 0; p < 2; ++p) { 5901 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); 5902 } 5903 #endif 5904 } 5905 } 5906 /* Old vertices have identical supports */ 5907 for (v = vStart; v < vEnd; ++v) { 5908 const PetscInt newp = vStartNew + (v - vStart); 5909 const PetscInt *support, *cone; 5910 PetscInt size, s; 5911 5912 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5913 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5914 for (s = 0; s < size; ++s) { 5915 PetscInt r = 0; 5916 5917 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5918 if (cone[1] == v) r = 1; 5919 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5920 } 5921 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5922 #if 1 5923 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5924 for (p = 0; p < size; ++p) { 5925 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); 5926 } 5927 #endif 5928 } 5929 /* Face vertices have 2 + cells supports */ 5930 for (f = fStart; f < fEnd; ++f) { 5931 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5932 const PetscInt *cone, *support; 5933 PetscInt size, s; 5934 5935 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5936 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5937 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5938 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5939 for (s = 0; s < size; ++s) { 5940 PetscInt r = 0; 5941 5942 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5943 if (cone[1] == f) r = 1; 5944 else if (cone[2] == f) r = 2; 5945 else if (cone[3] == f) r = 3; 5946 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 5947 } 5948 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5949 #if 1 5950 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5951 for (p = 0; p < 2+size; ++p) { 5952 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); 5953 } 5954 #endif 5955 } 5956 /* Cell vertices have 4 supports */ 5957 for (c = cStart; c < cEnd; ++c) { 5958 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5959 PetscInt supportNew[4]; 5960 5961 for (r = 0; r < 4; ++r) { 5962 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5963 } 5964 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5965 } 5966 break; 5967 case 3: 5968 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5969 cMax = PetscMin(cEnd, cMax); 5970 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5971 fMax = PetscMin(fEnd, fMax); 5972 /* Interior cells have 3 faces */ 5973 for (c = cStart; c < cMax; ++c) { 5974 const PetscInt newp = cStartNew + (c - cStart)*4; 5975 const PetscInt *cone, *ornt; 5976 PetscInt coneNew[3], orntNew[3]; 5977 5978 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5979 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5980 /* A triangle */ 5981 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5982 orntNew[0] = ornt[0]; 5983 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 5984 orntNew[1] = -2; 5985 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5986 orntNew[2] = ornt[2]; 5987 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5988 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5989 #if 1 5990 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); 5991 for (p = 0; p < 3; ++p) { 5992 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); 5993 } 5994 #endif 5995 /* B triangle */ 5996 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5997 orntNew[0] = ornt[0]; 5998 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5999 orntNew[1] = ornt[1]; 6000 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6001 orntNew[2] = -2; 6002 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6003 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6004 #if 1 6005 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); 6006 for (p = 0; p < 3; ++p) { 6007 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); 6008 } 6009 #endif 6010 /* C triangle */ 6011 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6012 orntNew[0] = -2; 6013 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6014 orntNew[1] = ornt[1]; 6015 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6016 orntNew[2] = ornt[2]; 6017 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6018 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6019 #if 1 6020 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); 6021 for (p = 0; p < 3; ++p) { 6022 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); 6023 } 6024 #endif 6025 /* D triangle */ 6026 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6027 orntNew[0] = 0; 6028 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6029 orntNew[1] = 0; 6030 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6031 orntNew[2] = 0; 6032 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6033 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6034 #if 1 6035 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); 6036 for (p = 0; p < 3; ++p) { 6037 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); 6038 } 6039 #endif 6040 } 6041 /* 6042 2----3----3 6043 | | 6044 | B | 6045 | | 6046 0----4--- 1 6047 | | 6048 | A | 6049 | | 6050 0----2----1 6051 */ 6052 /* Hybrid cells have 4 faces */ 6053 for (c = cMax; c < cEnd; ++c) { 6054 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6055 const PetscInt *cone, *ornt; 6056 PetscInt coneNew[4], orntNew[4]; 6057 6058 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6059 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6060 /* A quad */ 6061 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6062 orntNew[0] = ornt[0]; 6063 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6064 orntNew[1] = ornt[1]; 6065 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6066 orntNew[2] = 0; 6067 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6068 orntNew[3] = 0; 6069 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6070 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6071 #if 1 6072 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); 6073 for (p = 0; p < 4; ++p) { 6074 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); 6075 } 6076 #endif 6077 /* B quad */ 6078 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6079 orntNew[0] = ornt[0]; 6080 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6081 orntNew[1] = ornt[1]; 6082 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6083 orntNew[2] = 0; 6084 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6085 orntNew[3] = 0; 6086 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6087 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6088 #if 1 6089 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); 6090 for (p = 0; p < 4; ++p) { 6091 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); 6092 } 6093 #endif 6094 } 6095 /* Interior split faces have 2 vertices and the same cells as the parent */ 6096 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6097 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6098 for (f = fStart; f < fMax; ++f) { 6099 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6100 6101 for (r = 0; r < 2; ++r) { 6102 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6103 const PetscInt *cone, *support; 6104 PetscInt coneNew[2], coneSize, c, supportSize, s; 6105 6106 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6107 coneNew[0] = vStartNew + (cone[0] - vStart); 6108 coneNew[1] = vStartNew + (cone[1] - vStart); 6109 coneNew[(r+1)%2] = newv; 6110 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6111 #if 1 6112 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6113 for (p = 0; p < 2; ++p) { 6114 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); 6115 } 6116 #endif 6117 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6118 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6119 for (s = 0; s < supportSize; ++s) { 6120 if (support[s] >= cMax) { 6121 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6122 } else { 6123 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6124 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6125 for (c = 0; c < coneSize; ++c) { 6126 if (cone[c] == f) { 6127 break; 6128 } 6129 } 6130 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6131 } 6132 } 6133 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6134 #if 1 6135 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6136 for (p = 0; p < supportSize; ++p) { 6137 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); 6138 } 6139 #endif 6140 } 6141 } 6142 /* Interior cell faces have 2 vertices and 2 cells */ 6143 for (c = cStart; c < cMax; ++c) { 6144 const PetscInt *cone; 6145 6146 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6147 for (r = 0; r < 3; ++r) { 6148 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6149 PetscInt coneNew[2]; 6150 PetscInt supportNew[2]; 6151 6152 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6153 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6154 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6155 #if 1 6156 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6157 for (p = 0; p < 2; ++p) { 6158 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); 6159 } 6160 #endif 6161 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6162 supportNew[1] = (c - cStart)*4 + 3; 6163 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6164 #if 1 6165 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6166 for (p = 0; p < 2; ++p) { 6167 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); 6168 } 6169 #endif 6170 } 6171 } 6172 /* Interior hybrid faces have 2 vertices and the same cells */ 6173 for (f = fMax; f < fEnd; ++f) { 6174 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6175 const PetscInt *cone; 6176 const PetscInt *support; 6177 PetscInt coneNew[2]; 6178 PetscInt supportNew[2]; 6179 PetscInt size, s, r; 6180 6181 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6182 coneNew[0] = vStartNew + (cone[0] - vStart); 6183 coneNew[1] = vStartNew + (cone[1] - vStart); 6184 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6185 #if 1 6186 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6187 for (p = 0; p < 2; ++p) { 6188 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); 6189 } 6190 #endif 6191 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6192 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6193 for (s = 0; s < size; ++s) { 6194 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6195 for (r = 0; r < 2; ++r) { 6196 if (cone[r+2] == f) break; 6197 } 6198 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6199 } 6200 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6201 #if 1 6202 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6203 for (p = 0; p < size; ++p) { 6204 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); 6205 } 6206 #endif 6207 } 6208 /* Cell hybrid faces have 2 vertices and 2 cells */ 6209 for (c = cMax; c < cEnd; ++c) { 6210 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6211 const PetscInt *cone; 6212 PetscInt coneNew[2]; 6213 PetscInt supportNew[2]; 6214 6215 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6216 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6217 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6218 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6219 #if 1 6220 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6221 for (p = 0; p < 2; ++p) { 6222 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); 6223 } 6224 #endif 6225 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6226 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6227 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6228 #if 1 6229 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6230 for (p = 0; p < 2; ++p) { 6231 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); 6232 } 6233 #endif 6234 } 6235 /* Old vertices have identical supports */ 6236 for (v = vStart; v < vEnd; ++v) { 6237 const PetscInt newp = vStartNew + (v - vStart); 6238 const PetscInt *support, *cone; 6239 PetscInt size, s; 6240 6241 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6242 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6243 for (s = 0; s < size; ++s) { 6244 if (support[s] >= fMax) { 6245 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6246 } else { 6247 PetscInt r = 0; 6248 6249 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6250 if (cone[1] == v) r = 1; 6251 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6252 } 6253 } 6254 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6255 #if 1 6256 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6257 for (p = 0; p < size; ++p) { 6258 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); 6259 } 6260 #endif 6261 } 6262 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6263 for (f = fStart; f < fMax; ++f) { 6264 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6265 const PetscInt *cone, *support; 6266 PetscInt size, newSize = 2, s; 6267 6268 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6269 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6270 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6271 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6272 for (s = 0; s < size; ++s) { 6273 PetscInt r = 0; 6274 6275 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6276 if (support[s] >= cMax) { 6277 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6278 newSize += 1; 6279 } else { 6280 if (cone[1] == f) r = 1; 6281 else if (cone[2] == f) r = 2; 6282 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6283 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6284 newSize += 2; 6285 } 6286 } 6287 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6288 #if 1 6289 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6290 for (p = 0; p < newSize; ++p) { 6291 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); 6292 } 6293 #endif 6294 } 6295 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6296 break; 6297 default: 6298 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6299 } 6300 PetscFunctionReturn(0); 6301 } 6302 6303 #undef __FUNCT__ 6304 #define __FUNCT__ "CellRefinerSetCoordinates" 6305 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6306 { 6307 PetscSection coordSection, coordSectionNew; 6308 Vec coordinates, coordinatesNew; 6309 PetscScalar *coords, *coordsNew; 6310 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6311 PetscErrorCode ierr; 6312 6313 PetscFunctionBegin; 6314 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6315 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6316 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6317 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6318 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6319 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6320 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6321 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6322 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6323 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6324 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6325 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6326 if (fMax < 0) fMax = fEnd; 6327 switch (refiner) { 6328 case 1: 6329 case 2: 6330 case 3: 6331 /* Simplicial and Hex 2D */ 6332 /* All vertices have the dim coordinates */ 6333 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6334 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6335 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6336 } 6337 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6338 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6339 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6340 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6341 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6342 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6343 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6344 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6345 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6346 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6347 /* Old vertices have the same coordinates */ 6348 for (v = vStart; v < vEnd; ++v) { 6349 const PetscInt newv = vStartNew + (v - vStart); 6350 PetscInt off, offnew, d; 6351 6352 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6353 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6354 for (d = 0; d < dim; ++d) { 6355 coordsNew[offnew+d] = coords[off+d]; 6356 } 6357 } 6358 /* Face vertices have the average of endpoint coordinates */ 6359 for (f = fStart; f < fMax; ++f) { 6360 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6361 const PetscInt *cone; 6362 PetscInt coneSize, offA, offB, offnew, d; 6363 6364 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6365 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6366 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6367 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6368 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6369 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6370 for (d = 0; d < dim; ++d) { 6371 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6372 } 6373 } 6374 /* Just Hex 2D */ 6375 if (refiner == 2) { 6376 /* Cell vertices have the average of corner coordinates */ 6377 for (c = cStart; c < cEnd; ++c) { 6378 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6379 PetscInt *cone = PETSC_NULL; 6380 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6381 6382 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6383 for (p = 0; p < closureSize*2; p += 2) { 6384 const PetscInt point = cone[p]; 6385 if ((point >= vStart) && (point < vEnd)) { 6386 cone[coneSize++] = point; 6387 } 6388 } 6389 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6390 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6391 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6392 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6393 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6394 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6395 for (d = 0; d < dim; ++d) { 6396 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6397 } 6398 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6399 } 6400 } 6401 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6402 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6403 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6404 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6405 break; 6406 default: 6407 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6408 } 6409 PetscFunctionReturn(0); 6410 } 6411 6412 #undef __FUNCT__ 6413 #define __FUNCT__ "DMPlexCreateProcessSF" 6414 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6415 { 6416 PetscInt numRoots, numLeaves, l; 6417 const PetscInt *localPoints; 6418 const PetscSFNode *remotePoints; 6419 PetscInt *localPointsNew; 6420 PetscSFNode *remotePointsNew; 6421 PetscInt *ranks, *ranksNew; 6422 PetscErrorCode ierr; 6423 6424 PetscFunctionBegin; 6425 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6426 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6427 for (l = 0; l < numLeaves; ++l) { 6428 ranks[l] = remotePoints[l].rank; 6429 } 6430 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6431 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6432 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6433 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6434 for (l = 0; l < numLeaves; ++l) { 6435 ranksNew[l] = ranks[l]; 6436 localPointsNew[l] = l; 6437 remotePointsNew[l].index = 0; 6438 remotePointsNew[l].rank = ranksNew[l]; 6439 } 6440 ierr = PetscFree(ranks);CHKERRQ(ierr); 6441 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6442 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6443 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6444 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6445 PetscFunctionReturn(0); 6446 } 6447 6448 #undef __FUNCT__ 6449 #define __FUNCT__ "CellRefinerCreateSF" 6450 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6451 { 6452 PetscSF sf, sfNew, sfProcess; 6453 IS processRanks; 6454 MPI_Datatype depthType; 6455 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6456 const PetscInt *localPoints, *neighbors; 6457 const PetscSFNode *remotePoints; 6458 PetscInt *localPointsNew; 6459 PetscSFNode *remotePointsNew; 6460 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6461 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6462 PetscErrorCode ierr; 6463 6464 PetscFunctionBegin; 6465 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6466 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6467 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6468 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6469 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6470 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6471 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6472 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6473 switch (refiner) { 6474 case 3: 6475 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6476 cMax = PetscMin(cEnd, cMax); 6477 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6478 fMax = PetscMin(fEnd, fMax); 6479 } 6480 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6481 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6482 /* Caculate size of new SF */ 6483 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6484 if (numRoots < 0) PetscFunctionReturn(0); 6485 for (l = 0; l < numLeaves; ++l) { 6486 const PetscInt p = localPoints[l]; 6487 6488 switch (refiner) { 6489 case 1: 6490 /* Simplicial 2D */ 6491 if ((p >= vStart) && (p < vEnd)) { 6492 /* Old vertices stay the same */ 6493 ++numLeavesNew; 6494 } else if ((p >= fStart) && (p < fEnd)) { 6495 /* Old faces add new faces and vertex */ 6496 numLeavesNew += 1 + 2; 6497 } else if ((p >= cStart) && (p < cEnd)) { 6498 /* Old cells add new cells and interior faces */ 6499 numLeavesNew += 4 + 3; 6500 } 6501 break; 6502 case 2: 6503 /* Hex 2D */ 6504 if ((p >= vStart) && (p < vEnd)) { 6505 /* Old vertices stay the same */ 6506 ++numLeavesNew; 6507 } else if ((p >= fStart) && (p < fEnd)) { 6508 /* Old faces add new faces and vertex */ 6509 numLeavesNew += 1 + 2; 6510 } else if ((p >= cStart) && (p < cEnd)) { 6511 /* Old cells add new cells and interior faces */ 6512 numLeavesNew += 4 + 4; 6513 } 6514 break; 6515 default: 6516 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6517 } 6518 } 6519 /* Communicate depthSizes for each remote rank */ 6520 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6521 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6522 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6523 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); 6524 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6525 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6526 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6527 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6528 for (n = 0; n < numNeighbors; ++n) { 6529 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6530 } 6531 depthSizeOld[depth] = cMax; 6532 depthSizeOld[0] = vMax; 6533 depthSizeOld[depth-1] = fMax; 6534 depthSizeOld[1] = eMax; 6535 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6536 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6537 depthSizeOld[depth] = cEnd - cStart; 6538 depthSizeOld[0] = vEnd - vStart; 6539 depthSizeOld[depth-1] = fEnd - fStart; 6540 depthSizeOld[1] = eEnd - eStart; 6541 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6542 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6543 for (n = 0; n < numNeighbors; ++n) { 6544 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6545 } 6546 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6547 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6548 /* Calculate new point SF */ 6549 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6550 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6551 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6552 for (l = 0, m = 0; l < numLeaves; ++l) { 6553 PetscInt p = localPoints[l]; 6554 PetscInt rp = remotePoints[l].index, n; 6555 PetscMPIInt rrank = remotePoints[l].rank; 6556 6557 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6558 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6559 switch (refiner) { 6560 case 1: 6561 /* Simplicial 2D */ 6562 if ((p >= vStart) && (p < vEnd)) { 6563 /* Old vertices stay the same */ 6564 localPointsNew[m] = vStartNew + (p - vStart); 6565 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6566 remotePointsNew[m].rank = rrank; 6567 ++m; 6568 } else if ((p >= fStart) && (p < fEnd)) { 6569 /* Old faces add new faces and vertex */ 6570 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6571 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6572 remotePointsNew[m].rank = rrank; 6573 ++m; 6574 for (r = 0; r < 2; ++r, ++m) { 6575 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6576 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6577 remotePointsNew[m].rank = rrank; 6578 } 6579 } else if ((p >= cStart) && (p < cEnd)) { 6580 /* Old cells add new cells and interior faces */ 6581 for (r = 0; r < 4; ++r, ++m) { 6582 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6583 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6584 remotePointsNew[m].rank = rrank; 6585 } 6586 for (r = 0; r < 3; ++r, ++m) { 6587 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6588 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6589 remotePointsNew[m].rank = rrank; 6590 } 6591 } 6592 break; 6593 case 2: 6594 /* Hex 2D */ 6595 if ((p >= vStart) && (p < vEnd)) { 6596 /* Old vertices stay the same */ 6597 localPointsNew[m] = vStartNew + (p - vStart); 6598 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6599 remotePointsNew[m].rank = rrank; 6600 ++m; 6601 } else if ((p >= fStart) && (p < fEnd)) { 6602 /* Old faces add new faces and vertex */ 6603 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6604 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6605 remotePointsNew[m].rank = rrank; 6606 ++m; 6607 for (r = 0; r < 2; ++r, ++m) { 6608 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6609 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6610 remotePointsNew[m].rank = rrank; 6611 } 6612 } else if ((p >= cStart) && (p < cEnd)) { 6613 /* Old cells add new cells and interior faces */ 6614 for (r = 0; r < 4; ++r, ++m) { 6615 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6616 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6617 remotePointsNew[m].rank = rrank; 6618 } 6619 for (r = 0; r < 4; ++r, ++m) { 6620 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6621 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6622 remotePointsNew[m].rank = rrank; 6623 } 6624 } 6625 break; 6626 case 3: 6627 /* Hybrid simplicial 2D */ 6628 if ((p >= vStart) && (p < vEnd)) { 6629 /* Old vertices stay the same */ 6630 localPointsNew[m] = vStartNew + (p - vStart); 6631 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6632 remotePointsNew[m].rank = rrank; 6633 ++m; 6634 } else if ((p >= fStart) && (p < fMax)) { 6635 /* Old interior faces add new faces and vertex */ 6636 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6637 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6638 remotePointsNew[m].rank = rrank; 6639 ++m; 6640 for (r = 0; r < 2; ++r, ++m) { 6641 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6642 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6643 remotePointsNew[m].rank = rrank; 6644 } 6645 } else if ((p >= fMax) && (p < fEnd)) { 6646 /* Old hybrid faces stay the same */ 6647 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6648 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6649 remotePointsNew[m].rank = rrank; 6650 ++m; 6651 } else if ((p >= cStart) && (p < cMax)) { 6652 /* Old interior cells add new cells and interior faces */ 6653 for (r = 0; r < 4; ++r, ++m) { 6654 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6655 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6656 remotePointsNew[m].rank = rrank; 6657 } 6658 for (r = 0; r < 3; ++r, ++m) { 6659 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6660 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6661 remotePointsNew[m].rank = rrank; 6662 } 6663 } else if ((p >= cStart) && (p < cMax)) { 6664 /* Old hybrid cells add new cells and hybrid face */ 6665 for (r = 0; r < 2; ++r, ++m) { 6666 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6667 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6668 remotePointsNew[m].rank = rrank; 6669 } 6670 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6671 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]); 6672 remotePointsNew[m].rank = rrank; 6673 ++m; 6674 } 6675 break; 6676 default: 6677 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6678 } 6679 } 6680 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6681 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6682 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6683 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6684 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6685 PetscFunctionReturn(0); 6686 } 6687 6688 #undef __FUNCT__ 6689 #define __FUNCT__ "CellRefinerCreateLabels" 6690 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6691 { 6692 PetscInt numLabels, l; 6693 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6694 PetscErrorCode ierr; 6695 6696 PetscFunctionBegin; 6697 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6698 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6699 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6700 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6701 cStartNew = 0; 6702 vStartNew = depthSize[2]; 6703 fStartNew = depthSize[2] + depthSize[0]; 6704 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6705 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6706 switch (refiner) { 6707 case 3: 6708 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6709 cMax = PetscMin(cEnd, cMax); 6710 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6711 fMax = PetscMin(fEnd, fMax); 6712 } 6713 for (l = 0; l < numLabels; ++l) { 6714 DMLabel label, labelNew; 6715 const char *lname; 6716 PetscBool isDepth; 6717 IS valueIS; 6718 const PetscInt *values; 6719 PetscInt numValues, val; 6720 6721 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6722 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6723 if (isDepth) continue; 6724 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6725 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6726 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6727 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6728 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6729 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6730 for (val = 0; val < numValues; ++val) { 6731 IS pointIS; 6732 const PetscInt *points; 6733 PetscInt numPoints, n; 6734 6735 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6736 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6737 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6738 for (n = 0; n < numPoints; ++n) { 6739 const PetscInt p = points[n]; 6740 switch (refiner) { 6741 case 1: 6742 /* Simplicial 2D */ 6743 if ((p >= vStart) && (p < vEnd)) { 6744 /* Old vertices stay the same */ 6745 newp = vStartNew + (p - vStart); 6746 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6747 } else if ((p >= fStart) && (p < fEnd)) { 6748 /* Old faces add new faces and vertex */ 6749 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6750 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6751 for (r = 0; r < 2; ++r) { 6752 newp = fStartNew + (p - fStart)*2 + r; 6753 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6754 } 6755 } else if ((p >= cStart) && (p < cEnd)) { 6756 /* Old cells add new cells and interior faces */ 6757 for (r = 0; r < 4; ++r) { 6758 newp = cStartNew + (p - cStart)*4 + r; 6759 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6760 } 6761 for (r = 0; r < 3; ++r) { 6762 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6763 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6764 } 6765 } 6766 break; 6767 case 2: 6768 /* Hex 2D */ 6769 if ((p >= vStart) && (p < vEnd)) { 6770 /* Old vertices stay the same */ 6771 newp = vStartNew + (p - vStart); 6772 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6773 } else if ((p >= fStart) && (p < fEnd)) { 6774 /* Old faces add new faces and vertex */ 6775 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6776 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6777 for (r = 0; r < 2; ++r) { 6778 newp = fStartNew + (p - fStart)*2 + r; 6779 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6780 } 6781 } else if ((p >= cStart) && (p < cEnd)) { 6782 /* Old cells add new cells and interior faces and vertex */ 6783 for (r = 0; r < 4; ++r) { 6784 newp = cStartNew + (p - cStart)*4 + r; 6785 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6786 } 6787 for (r = 0; r < 4; ++r) { 6788 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6789 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6790 } 6791 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6792 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6793 } 6794 break; 6795 case 3: 6796 /* Hybrid simplicial 2D */ 6797 if ((p >= vStart) && (p < vEnd)) { 6798 /* Old vertices stay the same */ 6799 newp = vStartNew + (p - vStart); 6800 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6801 } else if ((p >= fStart) && (p < fMax)) { 6802 /* Old interior faces add new faces and vertex */ 6803 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6804 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6805 for (r = 0; r < 2; ++r) { 6806 newp = fStartNew + (p - fStart)*2 + r; 6807 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6808 } 6809 } else if ((p >= fMax) && (p < fEnd)) { 6810 /* Old hybrid faces stay the same */ 6811 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 6812 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6813 } else if ((p >= cStart) && (p < cMax)) { 6814 /* Old interior cells add new cells and interior faces */ 6815 for (r = 0; r < 4; ++r) { 6816 newp = cStartNew + (p - cStart)*4 + r; 6817 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6818 } 6819 for (r = 0; r < 3; ++r) { 6820 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6821 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6822 } 6823 } else if ((p >= cMax) && (p < cEnd)) { 6824 /* Old hybrid cells add new cells and hybrid face */ 6825 for (r = 0; r < 2; ++r) { 6826 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 6827 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6828 } 6829 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6830 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6831 } 6832 break; 6833 default: 6834 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6835 } 6836 } 6837 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6838 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6839 } 6840 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6841 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6842 if (0) { 6843 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6844 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6845 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6846 } 6847 } 6848 PetscFunctionReturn(0); 6849 } 6850 6851 #undef __FUNCT__ 6852 #define __FUNCT__ "DMPlexRefine_Uniform" 6853 /* This will only work for interpolated meshes */ 6854 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6855 { 6856 DM rdm; 6857 PetscInt *depthSize; 6858 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6859 PetscErrorCode ierr; 6860 6861 PetscFunctionBegin; 6862 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 6863 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6864 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6865 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6866 /* Calculate number of new points of each depth */ 6867 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6868 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6869 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6870 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6871 /* Step 1: Set chart */ 6872 for (d = 0; d <= depth; ++d) { 6873 pEnd += depthSize[d]; 6874 } 6875 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6876 /* Step 2: Set cone/support sizes */ 6877 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6878 /* Step 3: Setup refined DM */ 6879 ierr = DMSetUp(rdm);CHKERRQ(ierr); 6880 /* Step 4: Set cones and supports */ 6881 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6882 /* Step 5: Stratify */ 6883 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6884 /* Step 6: Set coordinates for vertices */ 6885 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6886 /* Step 7: Create pointSF */ 6887 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6888 /* Step 8: Create labels */ 6889 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6890 ierr = PetscFree(depthSize);CHKERRQ(ierr); 6891 6892 *dmRefined = rdm; 6893 #if 0 6894 DM_Plex *mesh = (DM_Plex *) dm->data; 6895 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 6896 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 6897 6898 PetscFunctionBegin; 6899 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6900 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 6901 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6902 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6903 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 6904 6905 /* Count number of new cells which are normal and extra */ 6906 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 6907 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 6908 for (c = cStart; c < cEnd2; ++c) { 6909 PetscInt n; 6910 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 6911 newNumCellsNormal += n; 6912 } 6913 for (c = cEnd2; c < cEnd; ++c) { 6914 PetscInt n; 6915 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 6916 newNumCellsExtra += n; 6917 } 6918 newNumCells = newNumCellsNormal + newNumCellsExtra; 6919 /* Count number of new vertices which are normal and extra */ 6920 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 6921 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 6922 for (c = cStart; c < cEnd; ++c) { 6923 PetscInt *closure = PETSC_NULL; 6924 PetscInt closureSize, numCorners = 0, p; 6925 6926 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6927 for (p = 0; p < closureSize*2; p += 2) { 6928 const PetscInt point = closure[p]; 6929 if ((point >= vStart) && (point < vEnd)) { 6930 closure[numCorners++] = point; 6931 } 6932 } 6933 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 6934 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6935 } 6936 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 6937 for (c = cEnd2; c < cEnd; ++c) { 6938 PetscInt *closure = PETSC_NULL; 6939 PetscInt closureSize, numCorners = 0, p; 6940 6941 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6942 for (p = 0; p < closureSize*2; p += 2) { 6943 const PetscInt point = closure[p]; 6944 if ((point >= vStart) && (point < vEnd)) { 6945 closure[numCorners++] = point; 6946 } 6947 } 6948 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 6949 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6950 } /* for */ 6951 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 6952 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 6953 6954 #if 1 6955 PetscInt oldNumCellsNormal = cEnd2 - cStart; 6956 PetscInt oldNumCellsExtra = cEnd - cEnd2; 6957 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 6958 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 6959 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 6960 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 6961 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 6962 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 6963 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 6964 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 6965 ierr = PetscSynchronizedFlush(comm); 6966 #endif 6967 6968 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 6969 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 6970 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 6971 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 6972 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 6973 /* Set cone and support sizes for new normal cells */ 6974 PetscInt newCell = 0; 6975 for (c = cStart; c < cEnd2; ++c) { 6976 PetscInt coneSize, n, i; 6977 6978 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6979 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 6980 for (i = 0; i < n; ++i, ++newCell) { 6981 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 6982 } 6983 6984 PetscInt *closure = PETSC_NULL; 6985 PetscInt closureSize, numCorners = 0, p; 6986 6987 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6988 for (p = 0; p < closureSize*2; p += 2) { 6989 const PetscInt point = closure[p]; 6990 if ((point >= vStart) && (point < vEnd)) { 6991 closure[numCorners++] = point; 6992 } 6993 } 6994 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); */ /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 6995 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6996 } 6997 6998 /* Reset current new cell value and loop over censored cells. */ 6999 curNewCell = _orderNewMesh->cellsCensored().min(); 7000 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7001 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7002 /* Set new cone and support sizes */ 7003 cV.clear(); 7004 sieve->cone(*c_iter, cV); 7005 const point_type* cone = cV.getPoints(); 7006 const int coneSize = cV.getSize(); 7007 7008 const point_type* newCells; 7009 int numNewCells = 0; 7010 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7011 7012 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7013 newSieve->setConeSize(curNewCell, coneSize); 7014 for (int iVertex=0; iVertex < coneSize; ++iVertex) { 7015 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7016 } /* for */ 7017 } /* for */ 7018 } /* for */ 7019 newSieve->allocate(); 7020 7021 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7022 7023 /* Create refined cells in new sieve. */ 7024 curNewCell = _orderNewMesh->cellsNormal().min(); 7025 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7026 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7027 cV.clear(); 7028 sieve->cone(*c_iter, cV); 7029 const point_type *cone = cV.getPoints(); 7030 const int coneSize = cV.getSize(); 7031 7032 const point_type* newCells; 7033 int numNewCells = 0; 7034 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7035 7036 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7037 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7038 } /* for */ 7039 } /* for */ 7040 curNewCell = _orderNewMesh->cellsCensored().min(); 7041 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7042 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7043 cV.clear(); 7044 sieve->cone(*c_iter, cV); 7045 const point_type *cone = cV.getPoints(); 7046 const int coneSize = cV.getSize(); 7047 7048 const point_type* newCells; 7049 int numNewCells = 0; 7050 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7051 7052 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7053 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7054 } /* for */ 7055 } /* for */ 7056 newSieve->symmetrize(); 7057 7058 /* Set coordinates in refined mesh. */ 7059 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7060 assert(!coordinates.isNull()); 7061 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7062 assert(!newCoordinates.isNull()); 7063 7064 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7065 assert(vertices->size() > 0); 7066 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7067 assert(spaceDim > 0); 7068 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7069 7070 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7071 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7072 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7073 } /* for */ 7074 newCoordinates->allocatePoint(); 7075 7076 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7077 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7078 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7079 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7080 } /* for */ 7081 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7082 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7083 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7084 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7085 } /* for */ 7086 7087 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7088 7089 /* Create sensored depth */ 7090 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7091 assert(!censoredLabel.isNull()); 7092 7093 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7094 7095 newSieve->roots(depthVisitor); 7096 while (depthVisitor.isModified()) { 7097 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7098 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7099 7100 depthVisitor.clear(); 7101 newSieve->support(modifiedPoints, depthVisitor); 7102 } /* while */ 7103 /* Stratify refined mesh */ 7104 /* Calculate new point SF */ 7105 _calcNewOverlap(newMesh, mesh, refiner); 7106 /* Calculate new labels */ 7107 _createLabels(newMesh, mesh, refiner); 7108 #endif 7109 PetscFunctionReturn(0); 7110 } 7111 7112 #undef __FUNCT__ 7113 #define __FUNCT__ "DMPlexSetRefinementUniform" 7114 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7115 { 7116 DM_Plex *mesh = (DM_Plex *) dm->data; 7117 7118 PetscFunctionBegin; 7119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7120 mesh->refinementUniform = refinementUniform; 7121 PetscFunctionReturn(0); 7122 } 7123 7124 #undef __FUNCT__ 7125 #define __FUNCT__ "DMPlexGetRefinementUniform" 7126 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7127 { 7128 DM_Plex *mesh = (DM_Plex *) dm->data; 7129 7130 PetscFunctionBegin; 7131 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7132 PetscValidPointer(refinementUniform, 2); 7133 *refinementUniform = mesh->refinementUniform; 7134 PetscFunctionReturn(0); 7135 } 7136 7137 #undef __FUNCT__ 7138 #define __FUNCT__ "DMPlexSetRefinementLimit" 7139 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7140 { 7141 DM_Plex *mesh = (DM_Plex *) dm->data; 7142 7143 PetscFunctionBegin; 7144 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7145 mesh->refinementLimit = refinementLimit; 7146 PetscFunctionReturn(0); 7147 } 7148 7149 #undef __FUNCT__ 7150 #define __FUNCT__ "DMPlexGetRefinementLimit" 7151 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7152 { 7153 DM_Plex *mesh = (DM_Plex *) dm->data; 7154 7155 PetscFunctionBegin; 7156 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7157 PetscValidPointer(refinementLimit, 2); 7158 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7159 *refinementLimit = mesh->refinementLimit; 7160 PetscFunctionReturn(0); 7161 } 7162 7163 #undef __FUNCT__ 7164 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7165 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7166 { 7167 PetscInt dim, cStart, coneSize, cMax; 7168 PetscErrorCode ierr; 7169 7170 PetscFunctionBegin; 7171 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7172 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7173 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7174 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7175 switch (dim) { 7176 case 2: 7177 switch (coneSize) { 7178 case 3: 7179 if (cMax >= 0) { 7180 *cellRefiner = 3; /* Hybrid */ 7181 } else { 7182 *cellRefiner = 1; /* Triangular */ 7183 } 7184 break; 7185 case 4: 7186 if (cMax >= 0) { 7187 *cellRefiner = 4; /* Hybrid */ 7188 } else { 7189 *cellRefiner = 2; /* Quadrilateral */ 7190 } 7191 break; 7192 default: 7193 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7194 } 7195 break; 7196 default: 7197 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7198 } 7199 PetscFunctionReturn(0); 7200 } 7201 7202 #undef __FUNCT__ 7203 #define __FUNCT__ "DMRefine_Plex" 7204 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7205 { 7206 PetscReal refinementLimit; 7207 PetscInt dim, cStart, cEnd; 7208 char genname[1024], *name = PETSC_NULL; 7209 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7210 PetscErrorCode ierr; 7211 7212 PetscFunctionBegin; 7213 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7214 if (isUniform) { 7215 CellRefiner cellRefiner; 7216 7217 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7218 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7219 PetscFunctionReturn(0); 7220 } 7221 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7222 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7223 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7224 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7225 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7226 if (flg) {name = genname;} 7227 if (name) { 7228 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7229 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7230 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7231 } 7232 switch (dim) { 7233 case 2: 7234 if (!name || isTriangle) { 7235 #if defined(PETSC_HAVE_TRIANGLE) 7236 double *maxVolumes; 7237 PetscInt c; 7238 7239 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7240 for (c = 0; c < cEnd-cStart; ++c) { 7241 maxVolumes[c] = refinementLimit; 7242 } 7243 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7244 #else 7245 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7246 #endif 7247 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7248 break; 7249 case 3: 7250 if (!name || isCTetgen) { 7251 #if defined(PETSC_HAVE_CTETGEN) 7252 PetscReal *maxVolumes; 7253 PetscInt c; 7254 7255 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7256 for (c = 0; c < cEnd-cStart; ++c) { 7257 maxVolumes[c] = refinementLimit; 7258 } 7259 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7260 #else 7261 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7262 #endif 7263 } else if (isTetgen) { 7264 #if defined(PETSC_HAVE_TETGEN) 7265 double *maxVolumes; 7266 PetscInt c; 7267 7268 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7269 for (c = 0; c < cEnd-cStart; ++c) { 7270 maxVolumes[c] = refinementLimit; 7271 } 7272 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7273 #else 7274 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7275 #endif 7276 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7277 break; 7278 default: 7279 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7280 } 7281 PetscFunctionReturn(0); 7282 } 7283 7284 #undef __FUNCT__ 7285 #define __FUNCT__ "DMPlexGetDepth" 7286 /*@ 7287 DMPlexGetDepth - get the number of strata 7288 7289 Not Collective 7290 7291 Input Parameters: 7292 . dm - The DMPlex object 7293 7294 Output Parameters: 7295 . depth - number of strata 7296 7297 Level: developer 7298 7299 Notes: 7300 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7301 7302 .keywords: mesh, points 7303 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7304 @*/ 7305 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7306 { 7307 PetscInt d; 7308 PetscErrorCode ierr; 7309 7310 PetscFunctionBegin; 7311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7312 PetscValidPointer(depth, 2); 7313 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7314 *depth = d-1; 7315 PetscFunctionReturn(0); 7316 } 7317 7318 #undef __FUNCT__ 7319 #define __FUNCT__ "DMPlexGetDepthStratum" 7320 /*@ 7321 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7322 7323 Not Collective 7324 7325 Input Parameters: 7326 + dm - The DMPlex object 7327 - stratumValue - The requested depth 7328 7329 Output Parameters: 7330 + start - The first point at this depth 7331 - end - One beyond the last point at this depth 7332 7333 Level: developer 7334 7335 .keywords: mesh, points 7336 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7337 @*/ 7338 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7339 { 7340 DM_Plex *mesh = (DM_Plex *) dm->data; 7341 DMLabel next = mesh->labels; 7342 PetscBool flg = PETSC_FALSE; 7343 PetscInt depth; 7344 PetscErrorCode ierr; 7345 7346 PetscFunctionBegin; 7347 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7348 if (stratumValue < 0) { 7349 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7350 PetscFunctionReturn(0); 7351 } else { 7352 PetscInt pStart, pEnd; 7353 7354 if (start) {*start = 0;} 7355 if (end) {*end = 0;} 7356 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7357 if (pStart == pEnd) {PetscFunctionReturn(0);} 7358 } 7359 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7360 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7361 /* We should have a generic GetLabel() and a Label class */ 7362 while (next) { 7363 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7364 if (flg) break; 7365 next = next->next; 7366 } 7367 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7368 depth = stratumValue; 7369 if ((depth < 0) || (depth >= next->numStrata)) { 7370 if (start) {*start = 0;} 7371 if (end) {*end = 0;} 7372 } else { 7373 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7374 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7375 } 7376 PetscFunctionReturn(0); 7377 } 7378 7379 #undef __FUNCT__ 7380 #define __FUNCT__ "DMPlexGetHeightStratum" 7381 /*@ 7382 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7383 7384 Not Collective 7385 7386 Input Parameters: 7387 + dm - The DMPlex object 7388 - stratumValue - The requested height 7389 7390 Output Parameters: 7391 + start - The first point at this height 7392 - end - One beyond the last point at this height 7393 7394 Level: developer 7395 7396 .keywords: mesh, points 7397 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7398 @*/ 7399 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7400 { 7401 DM_Plex *mesh = (DM_Plex *) dm->data; 7402 DMLabel next = mesh->labels; 7403 PetscBool flg = PETSC_FALSE; 7404 PetscInt depth; 7405 PetscErrorCode ierr; 7406 7407 PetscFunctionBegin; 7408 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7409 if (stratumValue < 0) { 7410 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7411 } else { 7412 PetscInt pStart, pEnd; 7413 7414 if (start) {*start = 0;} 7415 if (end) {*end = 0;} 7416 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7417 if (pStart == pEnd) {PetscFunctionReturn(0);} 7418 } 7419 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7420 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7421 /* We should have a generic GetLabel() and a Label class */ 7422 while (next) { 7423 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7424 if (flg) break; 7425 next = next->next; 7426 } 7427 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7428 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7429 if ((depth < 0) || (depth >= next->numStrata)) { 7430 if (start) {*start = 0;} 7431 if (end) {*end = 0;} 7432 } else { 7433 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7434 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7435 } 7436 PetscFunctionReturn(0); 7437 } 7438 7439 #undef __FUNCT__ 7440 #define __FUNCT__ "DMPlexCreateSectionInitial" 7441 /* Set the number of dof on each point and separate by fields */ 7442 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7443 { 7444 PetscInt *numDofTot; 7445 PetscInt pStart = 0, pEnd = 0; 7446 PetscInt p, d, f; 7447 PetscErrorCode ierr; 7448 7449 PetscFunctionBegin; 7450 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7451 for (d = 0; d <= dim; ++d) { 7452 numDofTot[d] = 0; 7453 for (f = 0; f < numFields; ++f) { 7454 numDofTot[d] += numDof[f*(dim+1)+d]; 7455 } 7456 } 7457 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7458 if (numFields > 0) { 7459 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7460 if (numComp) { 7461 for (f = 0; f < numFields; ++f) { 7462 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7463 } 7464 } 7465 } 7466 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7467 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7468 for (d = 0; d <= dim; ++d) { 7469 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7470 for (p = pStart; p < pEnd; ++p) { 7471 for (f = 0; f < numFields; ++f) { 7472 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7473 } 7474 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7475 } 7476 } 7477 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7478 PetscFunctionReturn(0); 7479 } 7480 7481 #undef __FUNCT__ 7482 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7483 /* Set the number of dof on each point and separate by fields 7484 If constDof is PETSC_DETERMINE, constrain every dof on the point 7485 */ 7486 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7487 { 7488 PetscInt numFields; 7489 PetscInt bc; 7490 PetscErrorCode ierr; 7491 7492 PetscFunctionBegin; 7493 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7494 for (bc = 0; bc < numBC; ++bc) { 7495 PetscInt field = 0; 7496 const PetscInt *idx; 7497 PetscInt n, i; 7498 7499 if (numFields) {field = bcField[bc];} 7500 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7501 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7502 for (i = 0; i < n; ++i) { 7503 const PetscInt p = idx[i]; 7504 PetscInt numConst = constDof; 7505 7506 /* Constrain every dof on the point */ 7507 if (numConst < 0) { 7508 if (numFields) { 7509 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7510 } else { 7511 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7512 } 7513 } 7514 if (numFields) { 7515 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7516 } 7517 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7518 } 7519 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7520 } 7521 PetscFunctionReturn(0); 7522 } 7523 7524 #undef __FUNCT__ 7525 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7526 /* Set the constrained indices on each point and separate by fields */ 7527 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7528 { 7529 PetscInt *maxConstraints; 7530 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7531 PetscErrorCode ierr; 7532 7533 PetscFunctionBegin; 7534 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7535 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7536 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7537 for (f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 7538 for (p = pStart; p < pEnd; ++p) { 7539 PetscInt cdof; 7540 7541 if (numFields) { 7542 for (f = 0; f < numFields; ++f) { 7543 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7544 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7545 } 7546 } else { 7547 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7548 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7549 } 7550 } 7551 for (f = 0; f < numFields; ++f) { 7552 maxConstraints[numFields] += maxConstraints[f]; 7553 } 7554 if (maxConstraints[numFields]) { 7555 PetscInt *indices; 7556 7557 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7558 for (p = pStart; p < pEnd; ++p) { 7559 PetscInt cdof, d; 7560 7561 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7562 if (cdof) { 7563 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7564 if (numFields) { 7565 PetscInt numConst = 0, foff = 0; 7566 7567 for (f = 0; f < numFields; ++f) { 7568 PetscInt cfdof, fdof; 7569 7570 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7571 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7572 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7573 for (d = 0; d < cfdof; ++d) { 7574 indices[numConst+d] = d; 7575 } 7576 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7577 for (d = 0; d < cfdof; ++d) { 7578 indices[numConst+d] += foff; 7579 } 7580 numConst += cfdof; 7581 foff += fdof; 7582 } 7583 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7584 } else { 7585 for (d = 0; d < cdof; ++d) { 7586 indices[d] = d; 7587 } 7588 } 7589 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7590 } 7591 } 7592 ierr = PetscFree(indices);CHKERRQ(ierr); 7593 } 7594 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7595 PetscFunctionReturn(0); 7596 } 7597 7598 #undef __FUNCT__ 7599 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7600 /* Set the constrained field indices on each point */ 7601 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7602 { 7603 const PetscInt *points, *indices; 7604 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7605 PetscErrorCode ierr; 7606 7607 PetscFunctionBegin; 7608 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7609 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7610 7611 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7612 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7613 if (!constraintIndices) { 7614 PetscInt *idx, i; 7615 7616 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7617 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7618 for (i = 0; i < maxDof; ++i) {idx[i] = i;} 7619 for (p = 0; p < numPoints; ++p) { 7620 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7621 } 7622 ierr = PetscFree(idx);CHKERRQ(ierr); 7623 } else { 7624 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7625 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7626 for (p = 0; p < numPoints; ++p) { 7627 PetscInt fcdof; 7628 7629 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7630 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); 7631 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7632 } 7633 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7634 } 7635 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7636 PetscFunctionReturn(0); 7637 } 7638 7639 #undef __FUNCT__ 7640 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7641 /* Set the constrained indices on each point and separate by fields */ 7642 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7643 { 7644 PetscInt *indices; 7645 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7646 PetscErrorCode ierr; 7647 7648 PetscFunctionBegin; 7649 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7650 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7651 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7652 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7653 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7654 for (p = pStart; p < pEnd; ++p) { 7655 PetscInt cdof, d; 7656 7657 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7658 if (cdof) { 7659 PetscInt numConst = 0, foff = 0; 7660 7661 for (f = 0; f < numFields; ++f) { 7662 const PetscInt *fcind; 7663 PetscInt fdof, fcdof; 7664 7665 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7666 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7667 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7668 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7669 for (d = 0; d < fcdof; ++d) { 7670 indices[numConst+d] = fcind[d]+foff; 7671 } 7672 foff += fdof; 7673 numConst += fcdof; 7674 } 7675 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7676 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7677 } 7678 } 7679 ierr = PetscFree(indices);CHKERRQ(ierr); 7680 PetscFunctionReturn(0); 7681 } 7682 7683 #undef __FUNCT__ 7684 #define __FUNCT__ "DMPlexCreateSection" 7685 /*@C 7686 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7687 7688 Not Collective 7689 7690 Input Parameters: 7691 + dm - The DMPlex object 7692 . dim - The spatial dimension of the problem 7693 . numFields - The number of fields in the problem 7694 . numComp - An array of size numFields that holds the number of components for each field 7695 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7696 . numBC - The number of boundary conditions 7697 . bcField - An array of size numBC giving the field number for each boundry condition 7698 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7699 7700 Output Parameter: 7701 . section - The PetscSection object 7702 7703 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 7704 nubmer of dof for field 0 on each edge. 7705 7706 Level: developer 7707 7708 .keywords: mesh, elements 7709 .seealso: DMPlexCreate(), PetscSectionCreate() 7710 @*/ 7711 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 7712 { 7713 PetscErrorCode ierr; 7714 7715 PetscFunctionBegin; 7716 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7717 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7718 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7719 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7720 { 7721 PetscBool view = PETSC_FALSE; 7722 7723 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7724 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7725 } 7726 PetscFunctionReturn(0); 7727 } 7728 7729 #undef __FUNCT__ 7730 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7731 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7732 { 7733 PetscSection section; 7734 PetscErrorCode ierr; 7735 7736 PetscFunctionBegin; 7737 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7738 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 7739 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7740 PetscFunctionReturn(0); 7741 } 7742 7743 #undef __FUNCT__ 7744 #define __FUNCT__ "DMPlexGetCoordinateSection" 7745 /*@ 7746 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7747 7748 Not Collective 7749 7750 Input Parameter: 7751 . dm - The DMPlex object 7752 7753 Output Parameter: 7754 . section - The PetscSection object 7755 7756 Level: intermediate 7757 7758 .keywords: mesh, coordinates 7759 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7760 @*/ 7761 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7762 { 7763 DM cdm; 7764 PetscErrorCode ierr; 7765 7766 PetscFunctionBegin; 7767 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7768 PetscValidPointer(section, 2); 7769 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7770 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7771 PetscFunctionReturn(0); 7772 } 7773 7774 #undef __FUNCT__ 7775 #define __FUNCT__ "DMPlexSetCoordinateSection" 7776 /*@ 7777 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7778 7779 Not Collective 7780 7781 Input Parameters: 7782 + dm - The DMPlex object 7783 - section - The PetscSection object 7784 7785 Level: intermediate 7786 7787 .keywords: mesh, coordinates 7788 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7789 @*/ 7790 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7791 { 7792 DM cdm; 7793 PetscErrorCode ierr; 7794 7795 PetscFunctionBegin; 7796 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7797 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7798 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7799 PetscFunctionReturn(0); 7800 } 7801 7802 #undef __FUNCT__ 7803 #define __FUNCT__ "DMPlexGetConeSection" 7804 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7805 { 7806 DM_Plex *mesh = (DM_Plex *) dm->data; 7807 7808 PetscFunctionBegin; 7809 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7810 if (section) *section = mesh->coneSection; 7811 PetscFunctionReturn(0); 7812 } 7813 7814 #undef __FUNCT__ 7815 #define __FUNCT__ "DMPlexGetCones" 7816 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 7817 { 7818 DM_Plex *mesh = (DM_Plex *) dm->data; 7819 7820 PetscFunctionBegin; 7821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7822 if (cones) *cones = mesh->cones; 7823 PetscFunctionReturn(0); 7824 } 7825 7826 #undef __FUNCT__ 7827 #define __FUNCT__ "DMPlexGetConeOrientations" 7828 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 7829 { 7830 DM_Plex *mesh = (DM_Plex *) dm->data; 7831 7832 PetscFunctionBegin; 7833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7834 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7835 PetscFunctionReturn(0); 7836 } 7837 7838 #undef __FUNCT__ 7839 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7840 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7841 { 7842 const PetscInt embedDim = 2; 7843 PetscReal x = PetscRealPart(point[0]); 7844 PetscReal y = PetscRealPart(point[1]); 7845 PetscReal v0[2], J[4], invJ[4], detJ; 7846 PetscReal xi, eta; 7847 PetscErrorCode ierr; 7848 7849 PetscFunctionBegin; 7850 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7851 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7852 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7853 7854 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 7855 *cell = c; 7856 } else { 7857 *cell = -1; 7858 } 7859 PetscFunctionReturn(0); 7860 } 7861 7862 #undef __FUNCT__ 7863 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7864 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7865 { 7866 PetscSection coordSection; 7867 Vec coordsLocal; 7868 const PetscScalar *coords; 7869 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7870 PetscReal x = PetscRealPart(point[0]); 7871 PetscReal y = PetscRealPart(point[1]); 7872 PetscInt crossings = 0, f; 7873 PetscErrorCode ierr; 7874 7875 PetscFunctionBegin; 7876 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7877 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7878 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7879 for (f = 0; f < 4; ++f) { 7880 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7881 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7882 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7883 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7884 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7885 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7886 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7887 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7888 if ((cond1 || cond2) && above) ++crossings; 7889 } 7890 if (crossings % 2) { 7891 *cell = c; 7892 } else { 7893 *cell = -1; 7894 } 7895 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7896 PetscFunctionReturn(0); 7897 } 7898 7899 #undef __FUNCT__ 7900 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7901 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7902 { 7903 const PetscInt embedDim = 3; 7904 PetscReal v0[3], J[9], invJ[9], detJ; 7905 PetscReal x = PetscRealPart(point[0]); 7906 PetscReal y = PetscRealPart(point[1]); 7907 PetscReal z = PetscRealPart(point[2]); 7908 PetscReal xi, eta, zeta; 7909 PetscErrorCode ierr; 7910 7911 PetscFunctionBegin; 7912 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7913 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7914 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7915 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7916 7917 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 7918 *cell = c; 7919 } else { 7920 *cell = -1; 7921 } 7922 PetscFunctionReturn(0); 7923 } 7924 7925 #undef __FUNCT__ 7926 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7927 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7928 { 7929 PetscSection coordSection; 7930 Vec coordsLocal; 7931 const PetscScalar *coords; 7932 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7933 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7934 PetscBool found = PETSC_TRUE; 7935 PetscInt f; 7936 PetscErrorCode ierr; 7937 7938 PetscFunctionBegin; 7939 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7940 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7941 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7942 for (f = 0; f < 6; ++f) { 7943 /* Check the point is under plane */ 7944 /* Get face normal */ 7945 PetscReal v_i[3] = {PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]), 7946 PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]), 7947 PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2])}; 7948 PetscReal v_j[3] = {PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]), 7949 PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]), 7950 PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2])}; 7951 PetscReal normal[3] = {v_i[1]*v_j[2] - v_i[2]*v_j[1], v_i[2]*v_j[0] - v_i[0]*v_j[2], v_i[0]*v_j[1] - v_i[1]*v_j[0]}; 7952 PetscReal pp[3] = {PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]), 7953 PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]), 7954 PetscRealPart(coords[faces[f*4+0]*3+2] - point[2])}; 7955 PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7956 /* Check that projected point is in face (2D location problem) */ 7957 if (dot < 0.0) { 7958 found = PETSC_FALSE; 7959 break; 7960 } 7961 } 7962 if (found) { 7963 *cell = c; 7964 } else { 7965 *cell = -1; 7966 } 7967 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7968 PetscFunctionReturn(0); 7969 } 7970 7971 #undef __FUNCT__ 7972 #define __FUNCT__ "DMLocatePoints_Plex" 7973 /* 7974 Need to implement using the guess 7975 */ 7976 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7977 { 7978 PetscInt cell = -1/*, guess = -1*/; 7979 PetscInt bs, numPoints, p; 7980 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7981 PetscInt *cells; 7982 PetscScalar *a; 7983 PetscErrorCode ierr; 7984 7985 PetscFunctionBegin; 7986 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7987 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7988 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7989 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 7990 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7991 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7992 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7993 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); 7994 numPoints /= bs; 7995 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7996 for (p = 0; p < numPoints; ++p) { 7997 const PetscScalar *point = &a[p*bs]; 7998 7999 switch (dim) { 8000 case 2: 8001 for (c = cStart; c < cEnd; ++c) { 8002 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8003 switch (coneSize) { 8004 case 3: 8005 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8006 break; 8007 case 4: 8008 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8009 break; 8010 default: 8011 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8012 } 8013 if (cell >= 0) break; 8014 } 8015 break; 8016 case 3: 8017 for (c = cStart; c < cEnd; ++c) { 8018 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8019 switch (coneSize) { 8020 case 4: 8021 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8022 break; 8023 case 8: 8024 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8025 break; 8026 default: 8027 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8028 } 8029 if (cell >= 0) break; 8030 } 8031 break; 8032 default: 8033 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8034 } 8035 cells[p] = cell; 8036 } 8037 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8038 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8039 PetscFunctionReturn(0); 8040 } 8041 8042 /******************************** FEM Support **********************************/ 8043 8044 #undef __FUNCT__ 8045 #define __FUNCT__ "DMPlexVecGetClosure" 8046 /*@C 8047 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8048 8049 Not collective 8050 8051 Input Parameters: 8052 + dm - The DM 8053 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8054 . v - The local vector 8055 - point - The sieve point in the DM 8056 8057 Output Parameters: 8058 + csize - The number of values in the closure, or PETSC_NULL 8059 - values - The array of values, which is a borrowed array and should not be freed 8060 8061 Level: intermediate 8062 8063 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8064 @*/ 8065 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8066 { 8067 PetscScalar *array, *vArray; 8068 PetscInt *points = PETSC_NULL; 8069 PetscInt offsets[32]; 8070 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8071 PetscErrorCode ierr; 8072 8073 PetscFunctionBegin; 8074 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8075 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8076 if (!section) { 8077 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8078 } 8079 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8080 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8081 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8082 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8083 /* Compress out points not in the section */ 8084 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8085 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8086 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8087 points[q*2] = points[p]; 8088 points[q*2+1] = points[p+1]; 8089 ++q; 8090 } 8091 } 8092 numPoints = q; 8093 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8094 PetscInt dof, fdof; 8095 8096 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8097 for (f = 0; f < numFields; ++f) { 8098 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8099 offsets[f+1] += fdof; 8100 } 8101 size += dof; 8102 } 8103 for (f = 1; f < numFields; ++f) { 8104 offsets[f+1] += offsets[f]; 8105 } 8106 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8107 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8108 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8109 for (p = 0; p < numPoints*2; p += 2) { 8110 PetscInt o = points[p+1]; 8111 PetscInt dof, off, d; 8112 PetscScalar *varr; 8113 8114 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8115 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8116 varr = &vArray[off]; 8117 if (numFields) { 8118 PetscInt fdof, foff, fcomp, f, c; 8119 8120 for (f = 0, foff = 0; f < numFields; ++f) { 8121 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8122 if (o >= 0) { 8123 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8124 array[offsets[f]] = varr[foff+d]; 8125 } 8126 } else { 8127 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8128 for (d = fdof/fcomp-1; d >= 0; --d) { 8129 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8130 array[offsets[f]] = varr[foff+d*fcomp+c]; 8131 } 8132 } 8133 } 8134 foff += fdof; 8135 } 8136 } else { 8137 if (o >= 0) { 8138 for (d = 0; d < dof; ++d, ++offsets[0]) { 8139 array[offsets[0]] = varr[d]; 8140 } 8141 } else { 8142 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8143 array[offsets[0]] = varr[d]; 8144 } 8145 } 8146 } 8147 } 8148 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8149 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8150 if (csize) *csize = size; 8151 *values = array; 8152 PetscFunctionReturn(0); 8153 } 8154 8155 #undef __FUNCT__ 8156 #define __FUNCT__ "DMPlexVecRestoreClosure" 8157 /*@C 8158 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8159 8160 Not collective 8161 8162 Input Parameters: 8163 + dm - The DM 8164 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8165 . v - The local vector 8166 . point - The sieve point in the DM 8167 . csize - The number of values in the closure, or PETSC_NULL 8168 - values - The array of values, which is a borrowed array and should not be freed 8169 8170 Level: intermediate 8171 8172 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8173 @*/ 8174 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8175 { 8176 PetscInt size = 0; 8177 PetscErrorCode ierr; 8178 8179 PetscFunctionBegin; 8180 /* Should work without recalculating size */ 8181 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 8182 PetscFunctionReturn(0); 8183 } 8184 8185 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8186 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8187 8188 #undef __FUNCT__ 8189 #define __FUNCT__ "updatePoint_private" 8190 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8191 { 8192 PetscInt cdof; /* The number of constraints on this point */ 8193 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8194 PetscScalar *a; 8195 PetscInt off, cind = 0, k; 8196 PetscErrorCode ierr; 8197 8198 PetscFunctionBegin; 8199 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8200 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8201 a = &array[off]; 8202 if (!cdof || setBC) { 8203 if (orientation >= 0) { 8204 for (k = 0; k < dof; ++k) { 8205 fuse(&a[k], values[k]); 8206 } 8207 } else { 8208 for (k = 0; k < dof; ++k) { 8209 fuse(&a[k], values[dof-k-1]); 8210 } 8211 } 8212 } else { 8213 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8214 if (orientation >= 0) { 8215 for (k = 0; k < dof; ++k) { 8216 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8217 fuse(&a[k], values[k]); 8218 } 8219 } else { 8220 for (k = 0; k < dof; ++k) { 8221 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8222 fuse(&a[k], values[dof-k-1]); 8223 } 8224 } 8225 } 8226 PetscFunctionReturn(0); 8227 } 8228 8229 #undef __FUNCT__ 8230 #define __FUNCT__ "updatePointFields_private" 8231 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8232 { 8233 PetscScalar *a; 8234 PetscInt numFields, off, foff, f; 8235 PetscErrorCode ierr; 8236 8237 PetscFunctionBegin; 8238 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8239 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8240 a = &array[off]; 8241 for (f = 0, foff = 0; f < numFields; ++f) { 8242 PetscInt fdof, fcomp, fcdof; 8243 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8244 PetscInt cind = 0, k, c; 8245 8246 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8247 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8248 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8249 if (!fcdof || setBC) { 8250 if (orientation >= 0) { 8251 for (k = 0; k < fdof; ++k) { 8252 fuse(&a[foff+k], values[foffs[f]+k]); 8253 } 8254 } else { 8255 for (k = fdof/fcomp-1; k >= 0; --k) { 8256 for (c = 0; c < fcomp; ++c) { 8257 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8258 } 8259 } 8260 } 8261 } else { 8262 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8263 if (orientation >= 0) { 8264 for (k = 0; k < fdof; ++k) { 8265 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8266 fuse(&a[foff+k], values[foffs[f]+k]); 8267 } 8268 } else { 8269 for (k = fdof/fcomp-1; k >= 0; --k) { 8270 for (c = 0; c < fcomp; ++c) { 8271 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8272 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8273 } 8274 } 8275 } 8276 } 8277 foff += fdof; 8278 foffs[f] += fdof; 8279 } 8280 PetscFunctionReturn(0); 8281 } 8282 8283 #undef __FUNCT__ 8284 #define __FUNCT__ "DMPlexVecSetClosure" 8285 /*@C 8286 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8287 8288 Not collective 8289 8290 Input Parameters: 8291 + dm - The DM 8292 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8293 . v - The local vector 8294 . point - The sieve point in the DM 8295 . values - The array of values, which is a borrowed array and should not be freed 8296 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8297 8298 Level: intermediate 8299 8300 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8301 @*/ 8302 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8303 { 8304 PetscScalar *array; 8305 PetscInt *points = PETSC_NULL; 8306 PetscInt offsets[32]; 8307 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8308 PetscErrorCode ierr; 8309 8310 PetscFunctionBegin; 8311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8312 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8313 if (!section) { 8314 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8315 } 8316 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8317 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8318 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8319 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8320 /* Compress out points not in the section */ 8321 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8322 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8323 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8324 points[q*2] = points[p]; 8325 points[q*2+1] = points[p+1]; 8326 ++q; 8327 } 8328 } 8329 numPoints = q; 8330 for (p = 0; p < numPoints*2; p += 2) { 8331 PetscInt fdof; 8332 8333 for (f = 0; f < numFields; ++f) { 8334 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8335 offsets[f+1] += fdof; 8336 } 8337 } 8338 for (f = 1; f < numFields; ++f) { 8339 offsets[f+1] += offsets[f]; 8340 } 8341 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8342 if (numFields) { 8343 switch (mode) { 8344 case INSERT_VALUES: 8345 for (p = 0; p < numPoints*2; p += 2) { 8346 PetscInt o = points[p+1]; 8347 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8348 } break; 8349 case INSERT_ALL_VALUES: 8350 for (p = 0; p < numPoints*2; p += 2) { 8351 PetscInt o = points[p+1]; 8352 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8353 } break; 8354 case ADD_VALUES: 8355 for (p = 0; p < numPoints*2; p += 2) { 8356 PetscInt o = points[p+1]; 8357 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8358 } break; 8359 case ADD_ALL_VALUES: 8360 for (p = 0; p < numPoints*2; p += 2) { 8361 PetscInt o = points[p+1]; 8362 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8363 } break; 8364 default: 8365 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8366 } 8367 } else { 8368 switch (mode) { 8369 case INSERT_VALUES: 8370 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8371 PetscInt o = points[p+1]; 8372 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8373 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8374 } break; 8375 case INSERT_ALL_VALUES: 8376 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8377 PetscInt o = points[p+1]; 8378 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8379 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8380 } break; 8381 case ADD_VALUES: 8382 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8383 PetscInt o = points[p+1]; 8384 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8385 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8386 } break; 8387 case ADD_ALL_VALUES: 8388 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8389 PetscInt o = points[p+1]; 8390 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8391 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8392 } break; 8393 default: 8394 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8395 } 8396 } 8397 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8398 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8399 PetscFunctionReturn(0); 8400 } 8401 8402 #undef __FUNCT__ 8403 #define __FUNCT__ "DMPlexPrintMatSetValues" 8404 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8405 { 8406 PetscMPIInt rank; 8407 PetscInt i, j; 8408 PetscErrorCode ierr; 8409 8410 PetscFunctionBegin; 8411 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8412 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8413 for (i = 0; i < numIndices; i++) { 8414 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8415 } 8416 for (i = 0; i < numIndices; i++) { 8417 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8418 for (j = 0; j < numIndices; j++) { 8419 #if defined(PETSC_USE_COMPLEX) 8420 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8421 #else 8422 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8423 #endif 8424 } 8425 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8426 } 8427 PetscFunctionReturn(0); 8428 } 8429 8430 #undef __FUNCT__ 8431 #define __FUNCT__ "indicesPoint_private" 8432 /* . off - The global offset of this point */ 8433 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8434 { 8435 PetscInt cdof; /* The number of constraints on this point */ 8436 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8437 PetscInt cind = 0, k; 8438 PetscErrorCode ierr; 8439 8440 PetscFunctionBegin; 8441 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8442 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8443 if (!cdof || setBC) { 8444 if (orientation >= 0) { 8445 for (k = 0; k < dof; ++k) { 8446 indices[k] = off+k; 8447 } 8448 } else { 8449 for (k = 0; k < dof; ++k) { 8450 indices[dof-k-1] = off+k; 8451 } 8452 } 8453 } else { 8454 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8455 if (orientation >= 0) { 8456 for (k = 0; k < dof; ++k) { 8457 if ((cind < cdof) && (k == cdofs[cind])) { 8458 /* Insert check for returning constrained indices */ 8459 indices[k] = -(off+k+1); 8460 ++cind; 8461 } else { 8462 indices[k] = off+k-cind; 8463 } 8464 } 8465 } else { 8466 for (k = 0; k < dof; ++k) { 8467 if ((cind < cdof) && (k == cdofs[cind])) { 8468 /* Insert check for returning constrained indices */ 8469 indices[dof-k-1] = -(off+k+1); 8470 ++cind; 8471 } else { 8472 indices[dof-k-1] = off+k-cind; 8473 } 8474 } 8475 } 8476 } 8477 PetscFunctionReturn(0); 8478 } 8479 8480 #undef __FUNCT__ 8481 #define __FUNCT__ "indicesPointFields_private" 8482 /* . off - The global offset of this point */ 8483 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8484 { 8485 PetscInt numFields, foff, f; 8486 PetscErrorCode ierr; 8487 8488 PetscFunctionBegin; 8489 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8490 for (f = 0, foff = 0; f < numFields; ++f) { 8491 PetscInt fdof, fcomp, cfdof; 8492 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8493 PetscInt cind = 0, k, c; 8494 8495 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8496 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8497 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8498 if (!cfdof || setBC) { 8499 if (orientation >= 0) { 8500 for (k = 0; k < fdof; ++k) { 8501 indices[foffs[f]+k] = off+foff+k; 8502 } 8503 } else { 8504 for (k = fdof/fcomp-1; k >= 0; --k) { 8505 for (c = 0; c < fcomp; ++c) { 8506 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8507 } 8508 } 8509 } 8510 } else { 8511 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8512 if (orientation >= 0) { 8513 for (k = 0; k < fdof; ++k) { 8514 if ((cind < cfdof) && (k == fcdofs[cind])) { 8515 indices[foffs[f]+k] = -(off+foff+k+1); 8516 ++cind; 8517 } else { 8518 indices[foffs[f]+k] = off+foff+k-cind; 8519 } 8520 } 8521 } else { 8522 for (k = fdof/fcomp-1; k >= 0; --k) { 8523 for (c = 0; c < fcomp; ++c) { 8524 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8525 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8526 ++cind; 8527 } else { 8528 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8529 } 8530 } 8531 } 8532 } 8533 } 8534 foff += fdof - cfdof; 8535 foffs[f] += fdof; 8536 } 8537 PetscFunctionReturn(0); 8538 } 8539 8540 #undef __FUNCT__ 8541 #define __FUNCT__ "DMPlexMatSetClosure" 8542 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8543 { 8544 DM_Plex *mesh = (DM_Plex *) dm->data; 8545 PetscInt *points = PETSC_NULL; 8546 PetscInt *indices; 8547 PetscInt offsets[32]; 8548 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8549 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8550 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8551 PetscErrorCode ierr; 8552 8553 PetscFunctionBegin; 8554 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8555 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8556 if (useDefault) { 8557 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8558 } 8559 if (useGlobalDefault) { 8560 if (useDefault) { 8561 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8562 } else { 8563 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8564 } 8565 } 8566 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8567 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8568 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8569 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8570 /* Compress out points not in the section */ 8571 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8572 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8573 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8574 points[q*2] = points[p]; 8575 points[q*2+1] = points[p+1]; 8576 ++q; 8577 } 8578 } 8579 numPoints = q; 8580 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8581 PetscInt fdof; 8582 8583 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8584 for (f = 0; f < numFields; ++f) { 8585 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8586 offsets[f+1] += fdof; 8587 } 8588 numIndices += dof; 8589 } 8590 for (f = 1; f < numFields; ++f) { 8591 offsets[f+1] += offsets[f]; 8592 } 8593 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8594 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8595 if (numFields) { 8596 for (p = 0; p < numPoints*2; p += 2) { 8597 PetscInt o = points[p+1]; 8598 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8599 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8600 } 8601 } else { 8602 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8603 PetscInt o = points[p+1]; 8604 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8605 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8606 } 8607 } 8608 if (useGlobalDefault && !useDefault) { 8609 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8610 } 8611 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8612 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8613 if (ierr) { 8614 PetscMPIInt rank; 8615 PetscErrorCode ierr2; 8616 8617 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8618 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8619 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8620 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8621 CHKERRQ(ierr); 8622 } 8623 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8624 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8625 PetscFunctionReturn(0); 8626 } 8627 8628 #undef __FUNCT__ 8629 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8630 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8631 { 8632 PetscSection coordSection; 8633 Vec coordinates; 8634 const PetscScalar *coords; 8635 const PetscInt dim = 2; 8636 PetscInt d, f; 8637 PetscErrorCode ierr; 8638 8639 PetscFunctionBegin; 8640 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8641 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8642 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8643 if (v0) { 8644 for (d = 0; d < dim; d++) { 8645 v0[d] = PetscRealPart(coords[d]); 8646 } 8647 } 8648 if (J) { 8649 for (d = 0; d < dim; d++) { 8650 for (f = 0; f < dim; f++) { 8651 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8652 } 8653 } 8654 *detJ = J[0]*J[3] - J[1]*J[2]; 8655 #if 0 8656 if (detJ < 0.0) { 8657 const PetscReal xLength = mesh->periodicity[0]; 8658 8659 if (xLength != 0.0) { 8660 PetscReal v0x = coords[0*dim+0]; 8661 8662 if (v0x == 0.0) { 8663 v0x = v0[0] = xLength; 8664 } 8665 for (f = 0; f < dim; f++) { 8666 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8667 8668 J[0*dim+f] = 0.5*(px - v0x); 8669 } 8670 } 8671 detJ = J[0]*J[3] - J[1]*J[2]; 8672 } 8673 #endif 8674 PetscLogFlops(8.0 + 3.0); 8675 } 8676 if (invJ) { 8677 const PetscReal invDet = 1.0/(*detJ); 8678 8679 invJ[0] = invDet*J[3]; 8680 invJ[1] = -invDet*J[1]; 8681 invJ[2] = -invDet*J[2]; 8682 invJ[3] = invDet*J[0]; 8683 PetscLogFlops(5.0); 8684 } 8685 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8686 PetscFunctionReturn(0); 8687 } 8688 8689 #undef __FUNCT__ 8690 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8691 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8692 { 8693 PetscSection coordSection; 8694 Vec coordinates; 8695 const PetscScalar *coords; 8696 const PetscInt dim = 2; 8697 PetscInt d, f; 8698 PetscErrorCode ierr; 8699 8700 PetscFunctionBegin; 8701 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8702 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8703 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8704 if (v0) { 8705 for (d = 0; d < dim; d++) { 8706 v0[d] = PetscRealPart(coords[d]); 8707 } 8708 } 8709 if (J) { 8710 for (d = 0; d < dim; d++) { 8711 for (f = 0; f < dim; f++) { 8712 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8713 } 8714 } 8715 *detJ = J[0]*J[3] - J[1]*J[2]; 8716 PetscLogFlops(8.0 + 3.0); 8717 } 8718 if (invJ) { 8719 const PetscReal invDet = 1.0/(*detJ); 8720 8721 invJ[0] = invDet*J[3]; 8722 invJ[1] = -invDet*J[1]; 8723 invJ[2] = -invDet*J[2]; 8724 invJ[3] = invDet*J[0]; 8725 PetscLogFlops(5.0); 8726 } 8727 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8728 PetscFunctionReturn(0); 8729 } 8730 8731 #undef __FUNCT__ 8732 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8733 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8734 { 8735 PetscSection coordSection; 8736 Vec coordinates; 8737 const PetscScalar *coords; 8738 const PetscInt dim = 3; 8739 PetscInt d, f; 8740 PetscErrorCode ierr; 8741 8742 PetscFunctionBegin; 8743 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8744 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8745 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8746 if (v0) { 8747 for (d = 0; d < dim; d++) { 8748 v0[d] = PetscRealPart(coords[d]); 8749 } 8750 } 8751 if (J) { 8752 for (d = 0; d < dim; d++) { 8753 for (f = 0; f < dim; f++) { 8754 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8755 } 8756 } 8757 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8758 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8759 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8760 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8761 PetscLogFlops(18.0 + 12.0); 8762 } 8763 if (invJ) { 8764 const PetscReal invDet = 1.0/(*detJ); 8765 8766 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8767 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8768 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8769 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8770 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8771 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8772 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8773 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8774 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8775 PetscLogFlops(37.0); 8776 } 8777 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8778 PetscFunctionReturn(0); 8779 } 8780 8781 #undef __FUNCT__ 8782 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8783 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8784 { 8785 PetscSection coordSection; 8786 Vec coordinates; 8787 const PetscScalar *coords; 8788 const PetscInt dim = 3; 8789 PetscInt d; 8790 PetscErrorCode ierr; 8791 8792 PetscFunctionBegin; 8793 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8794 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8795 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8796 if (v0) { 8797 for (d = 0; d < dim; d++) { 8798 v0[d] = PetscRealPart(coords[d]); 8799 } 8800 } 8801 if (J) { 8802 for (d = 0; d < dim; d++) { 8803 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8804 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8805 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8806 } 8807 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8808 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8809 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8810 PetscLogFlops(18.0 + 12.0); 8811 } 8812 if (invJ) { 8813 const PetscReal invDet = -1.0/(*detJ); 8814 8815 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8816 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8817 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8818 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8819 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8820 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8821 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8822 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8823 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8824 PetscLogFlops(37.0); 8825 } 8826 *detJ *= 8.0; 8827 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8828 PetscFunctionReturn(0); 8829 } 8830 8831 #undef __FUNCT__ 8832 #define __FUNCT__ "DMPlexComputeCellGeometry" 8833 /*@C 8834 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8835 8836 Collective on DM 8837 8838 Input Arguments: 8839 + dm - the DM 8840 - cell - the cell 8841 8842 Output Arguments: 8843 + v0 - the translation part of this affine transform 8844 . J - the Jacobian of the transform to the reference element 8845 . invJ - the inverse of the Jacobian 8846 - detJ - the Jacobian determinant 8847 8848 Level: advanced 8849 8850 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8851 @*/ 8852 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8853 { 8854 PetscInt dim, coneSize; 8855 PetscErrorCode ierr; 8856 8857 PetscFunctionBegin; 8858 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8859 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8860 switch (dim) { 8861 case 2: 8862 switch (coneSize) { 8863 case 3: 8864 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8865 break; 8866 case 4: 8867 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8868 break; 8869 default: 8870 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8871 } 8872 break; 8873 case 3: 8874 switch (coneSize) { 8875 case 4: 8876 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8877 break; 8878 case 8: 8879 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8880 break; 8881 default: 8882 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8883 } 8884 break; 8885 default: 8886 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8887 } 8888 PetscFunctionReturn(0); 8889 } 8890 8891 #undef __FUNCT__ 8892 #define __FUNCT__ "DMPlexGetFaceOrientation" 8893 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 8894 { 8895 MPI_Comm comm = ((PetscObject) dm)->comm; 8896 PetscBool posOrient = PETSC_FALSE; 8897 const PetscInt debug = 0; 8898 PetscInt cellDim, faceSize, f; 8899 PetscErrorCode ierr; 8900 8901 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 8902 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 8903 8904 if (cellDim == numCorners-1) { 8905 /* Simplices */ 8906 faceSize = numCorners-1; 8907 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 8908 } else if (cellDim == 1 && numCorners == 3) { 8909 /* Quadratic line */ 8910 faceSize = 1; 8911 posOrient = PETSC_TRUE; 8912 } else if (cellDim == 2 && numCorners == 4) { 8913 /* Quads */ 8914 faceSize = 2; 8915 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 8916 posOrient = PETSC_TRUE; 8917 } else if ((indices[0] == 3) && (indices[1] == 0)) { 8918 posOrient = PETSC_TRUE; 8919 } else { 8920 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 8921 posOrient = PETSC_FALSE; 8922 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 8923 } 8924 } else if (cellDim == 2 && numCorners == 6) { 8925 /* Quadratic triangle (I hate this) */ 8926 /* Edges are determined by the first 2 vertices (corners of edges) */ 8927 const PetscInt faceSizeTri = 3; 8928 PetscInt sortedIndices[3], i, iFace; 8929 PetscBool found = PETSC_FALSE; 8930 PetscInt faceVerticesTriSorted[9] = { 8931 0, 3, 4, /* bottom */ 8932 1, 4, 5, /* right */ 8933 2, 3, 5, /* left */ 8934 }; 8935 PetscInt faceVerticesTri[9] = { 8936 0, 3, 4, /* bottom */ 8937 1, 4, 5, /* right */ 8938 2, 5, 3, /* left */ 8939 }; 8940 8941 faceSize = faceSizeTri; 8942 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 8943 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 8944 for (iFace = 0; iFace < 3; ++iFace) { 8945 const PetscInt ii = iFace*faceSizeTri; 8946 PetscInt fVertex, cVertex; 8947 8948 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 8949 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 8950 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 8951 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 8952 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 8953 faceVertices[fVertex] = origVertices[cVertex]; 8954 break; 8955 } 8956 } 8957 } 8958 found = PETSC_TRUE; 8959 break; 8960 } 8961 } 8962 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 8963 if (posOriented) {*posOriented = PETSC_TRUE;} 8964 PetscFunctionReturn(0); 8965 } else if (cellDim == 2 && numCorners == 9) { 8966 /* Quadratic quad (I hate this) */ 8967 /* Edges are determined by the first 2 vertices (corners of edges) */ 8968 const PetscInt faceSizeQuad = 3; 8969 PetscInt sortedIndices[3], i, iFace; 8970 PetscBool found = PETSC_FALSE; 8971 PetscInt faceVerticesQuadSorted[12] = { 8972 0, 1, 4, /* bottom */ 8973 1, 2, 5, /* right */ 8974 2, 3, 6, /* top */ 8975 0, 3, 7, /* left */ 8976 }; 8977 PetscInt faceVerticesQuad[12] = { 8978 0, 1, 4, /* bottom */ 8979 1, 2, 5, /* right */ 8980 2, 3, 6, /* top */ 8981 3, 0, 7, /* left */ 8982 }; 8983 8984 faceSize = faceSizeQuad; 8985 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 8986 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 8987 for (iFace = 0; iFace < 4; ++iFace) { 8988 const PetscInt ii = iFace*faceSizeQuad; 8989 PetscInt fVertex, cVertex; 8990 8991 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 8992 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 8993 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 8994 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 8995 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 8996 faceVertices[fVertex] = origVertices[cVertex]; 8997 break; 8998 } 8999 } 9000 } 9001 found = PETSC_TRUE; 9002 break; 9003 } 9004 } 9005 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9006 if (posOriented) {*posOriented = PETSC_TRUE;} 9007 PetscFunctionReturn(0); 9008 } else if (cellDim == 3 && numCorners == 8) { 9009 /* Hexes 9010 A hex is two oriented quads with the normal of the first 9011 pointing up at the second. 9012 9013 7---6 9014 /| /| 9015 4---5 | 9016 | 3-|-2 9017 |/ |/ 9018 0---1 9019 9020 Faces are determined by the first 4 vertices (corners of faces) */ 9021 const PetscInt faceSizeHex = 4; 9022 PetscInt sortedIndices[4], i, iFace; 9023 PetscBool found = PETSC_FALSE; 9024 PetscInt faceVerticesHexSorted[24] = { 9025 0, 1, 2, 3, /* bottom */ 9026 4, 5, 6, 7, /* top */ 9027 0, 1, 4, 5, /* front */ 9028 1, 2, 5, 6, /* right */ 9029 2, 3, 6, 7, /* back */ 9030 0, 3, 4, 7, /* left */ 9031 }; 9032 PetscInt faceVerticesHex[24] = { 9033 3, 2, 1, 0, /* bottom */ 9034 4, 5, 6, 7, /* top */ 9035 0, 1, 5, 4, /* front */ 9036 1, 2, 6, 5, /* right */ 9037 2, 3, 7, 6, /* back */ 9038 3, 0, 4, 7, /* left */ 9039 }; 9040 9041 faceSize = faceSizeHex; 9042 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9043 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9044 for (iFace = 0; iFace < 6; ++iFace) { 9045 const PetscInt ii = iFace*faceSizeHex; 9046 PetscInt fVertex, cVertex; 9047 9048 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9049 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9050 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9051 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9052 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9053 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9054 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9055 faceVertices[fVertex] = origVertices[cVertex]; 9056 break; 9057 } 9058 } 9059 } 9060 found = PETSC_TRUE; 9061 break; 9062 } 9063 } 9064 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9065 if (posOriented) {*posOriented = PETSC_TRUE;} 9066 PetscFunctionReturn(0); 9067 } else if (cellDim == 3 && numCorners == 10) { 9068 /* Quadratic tet */ 9069 /* Faces are determined by the first 3 vertices (corners of faces) */ 9070 const PetscInt faceSizeTet = 6; 9071 PetscInt sortedIndices[6], i, iFace; 9072 PetscBool found = PETSC_FALSE; 9073 PetscInt faceVerticesTetSorted[24] = { 9074 0, 1, 2, 6, 7, 8, /* bottom */ 9075 0, 3, 4, 6, 7, 9, /* front */ 9076 1, 4, 5, 7, 8, 9, /* right */ 9077 2, 3, 5, 6, 8, 9, /* left */ 9078 }; 9079 PetscInt faceVerticesTet[24] = { 9080 0, 1, 2, 6, 7, 8, /* bottom */ 9081 0, 4, 3, 6, 7, 9, /* front */ 9082 1, 5, 4, 7, 8, 9, /* right */ 9083 2, 3, 5, 8, 6, 9, /* left */ 9084 }; 9085 9086 faceSize = faceSizeTet; 9087 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9088 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9089 for (iFace=0; iFace < 4; ++iFace) { 9090 const PetscInt ii = iFace*faceSizeTet; 9091 PetscInt fVertex, cVertex; 9092 9093 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9094 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9095 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9096 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9097 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9098 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9099 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9100 faceVertices[fVertex] = origVertices[cVertex]; 9101 break; 9102 } 9103 } 9104 } 9105 found = PETSC_TRUE; 9106 break; 9107 } 9108 } 9109 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9110 if (posOriented) {*posOriented = PETSC_TRUE;} 9111 PetscFunctionReturn(0); 9112 } else if (cellDim == 3 && numCorners == 27) { 9113 /* Quadratic hexes (I hate this) 9114 A hex is two oriented quads with the normal of the first 9115 pointing up at the second. 9116 9117 7---6 9118 /| /| 9119 4---5 | 9120 | 3-|-2 9121 |/ |/ 9122 0---1 9123 9124 Faces are determined by the first 4 vertices (corners of faces) */ 9125 const PetscInt faceSizeQuadHex = 9; 9126 PetscInt sortedIndices[9], i, iFace; 9127 PetscBool found = PETSC_FALSE; 9128 PetscInt faceVerticesQuadHexSorted[54] = { 9129 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9130 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9131 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9132 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9133 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9134 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9135 }; 9136 PetscInt faceVerticesQuadHex[54] = { 9137 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9138 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9139 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9140 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9141 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9142 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9143 }; 9144 9145 faceSize = faceSizeQuadHex; 9146 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9147 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9148 for (iFace = 0; iFace < 6; ++iFace) { 9149 const PetscInt ii = iFace*faceSizeQuadHex; 9150 PetscInt fVertex, cVertex; 9151 9152 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9153 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9154 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9155 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9156 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9157 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9158 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9159 faceVertices[fVertex] = origVertices[cVertex]; 9160 break; 9161 } 9162 } 9163 } 9164 found = PETSC_TRUE; 9165 break; 9166 } 9167 } 9168 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9169 if (posOriented) {*posOriented = PETSC_TRUE;} 9170 PetscFunctionReturn(0); 9171 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9172 if (!posOrient) { 9173 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9174 for (f = 0; f < faceSize; ++f) { 9175 faceVertices[f] = origVertices[faceSize-1 - f]; 9176 } 9177 } else { 9178 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9179 for (f = 0; f < faceSize; ++f) { 9180 faceVertices[f] = origVertices[f]; 9181 } 9182 } 9183 if (posOriented) {*posOriented = posOrient;} 9184 PetscFunctionReturn(0); 9185 } 9186 9187 #undef __FUNCT__ 9188 #define __FUNCT__ "DMPlexGetOrientedFace" 9189 /* 9190 Given a cell and a face, as a set of vertices, 9191 return the oriented face, as a set of vertices, in faceVertices 9192 The orientation is such that the face normal points out of the cell 9193 */ 9194 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9195 { 9196 const PetscInt *cone = PETSC_NULL; 9197 PetscInt coneSize, v, f, v2; 9198 PetscInt oppositeVertex = -1; 9199 PetscErrorCode ierr; 9200 9201 PetscFunctionBegin; 9202 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9203 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9204 for (v = 0, v2 = 0; v < coneSize; ++v) { 9205 PetscBool found = PETSC_FALSE; 9206 9207 for (f = 0; f < faceSize; ++f) { 9208 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 9209 } 9210 if (found) { 9211 indices[v2] = v; 9212 origVertices[v2] = cone[v]; 9213 ++v2; 9214 } else { 9215 oppositeVertex = v; 9216 } 9217 } 9218 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9219 PetscFunctionReturn(0); 9220 } 9221 9222 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9223 { 9224 switch (i) { 9225 case 0: 9226 switch (j) { 9227 case 0: return 0; 9228 case 1: 9229 switch (k) { 9230 case 0: return 0; 9231 case 1: return 0; 9232 case 2: return 1; 9233 } 9234 case 2: 9235 switch (k) { 9236 case 0: return 0; 9237 case 1: return -1; 9238 case 2: return 0; 9239 } 9240 } 9241 case 1: 9242 switch (j) { 9243 case 0: 9244 switch (k) { 9245 case 0: return 0; 9246 case 1: return 0; 9247 case 2: return -1; 9248 } 9249 case 1: return 0; 9250 case 2: 9251 switch (k) { 9252 case 0: return 1; 9253 case 1: return 0; 9254 case 2: return 0; 9255 } 9256 } 9257 case 2: 9258 switch (j) { 9259 case 0: 9260 switch (k) { 9261 case 0: return 0; 9262 case 1: return 1; 9263 case 2: return 0; 9264 } 9265 case 1: 9266 switch (k) { 9267 case 0: return -1; 9268 case 1: return 0; 9269 case 2: return 0; 9270 } 9271 case 2: return 0; 9272 } 9273 } 9274 return 0; 9275 } 9276 9277 #undef __FUNCT__ 9278 #define __FUNCT__ "DMPlexCreateRigidBody" 9279 /*@C 9280 DMPlexCreateRigidBody - create rigid body modes from coordinates 9281 9282 Collective on DM 9283 9284 Input Arguments: 9285 + dm - the DM 9286 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9287 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9288 9289 Output Argument: 9290 . sp - the null space 9291 9292 Note: This is necessary to take account of Dirichlet conditions on the displacements 9293 9294 Level: advanced 9295 9296 .seealso: MatNullSpaceCreate() 9297 @*/ 9298 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9299 { 9300 MPI_Comm comm = ((PetscObject) dm)->comm; 9301 Vec coordinates, localMode, mode[6]; 9302 PetscSection coordSection; 9303 PetscScalar *coords; 9304 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9305 PetscErrorCode ierr; 9306 9307 PetscFunctionBegin; 9308 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9309 if (dim == 1) { 9310 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9311 PetscFunctionReturn(0); 9312 } 9313 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9314 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9315 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9316 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9317 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9318 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9319 m = (dim*(dim+1))/2; 9320 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9321 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9322 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9323 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9324 /* Assume P1 */ 9325 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9326 for (d = 0; d < dim; ++d) { 9327 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9328 9329 values[d] = 1.0; 9330 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9331 for (v = vStart; v < vEnd; ++v) { 9332 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9333 } 9334 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9335 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9336 } 9337 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9338 for (d = dim; d < dim*(dim+1)/2; ++d) { 9339 PetscInt i, j, k = dim > 2 ? d - dim : d; 9340 9341 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9342 for (v = vStart; v < vEnd; ++v) { 9343 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9344 PetscInt off; 9345 9346 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9347 for (i = 0; i < dim; ++i) { 9348 for (j = 0; j < dim; ++j) { 9349 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9350 } 9351 } 9352 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9353 } 9354 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9355 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9356 } 9357 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9358 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9359 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9360 /* Orthonormalize system */ 9361 for (i = dim; i < m; ++i) { 9362 PetscScalar dots[6]; 9363 9364 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9365 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9366 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9367 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9368 } 9369 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9370 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9371 PetscFunctionReturn(0); 9372 } 9373 9374 #undef __FUNCT__ 9375 #define __FUNCT__ "DMPlexGetHybridBounds" 9376 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9377 { 9378 DM_Plex *mesh = (DM_Plex *) dm->data; 9379 PetscInt dim; 9380 PetscErrorCode ierr; 9381 9382 PetscFunctionBegin; 9383 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9384 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9385 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9386 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9387 if (eMax) *eMax = mesh->hybridPointMax[1]; 9388 if (vMax) *vMax = mesh->hybridPointMax[0]; 9389 PetscFunctionReturn(0); 9390 } 9391 9392 #undef __FUNCT__ 9393 #define __FUNCT__ "DMPlexSetHybridBounds" 9394 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9395 { 9396 DM_Plex *mesh = (DM_Plex *) dm->data; 9397 PetscInt dim; 9398 PetscErrorCode ierr; 9399 9400 PetscFunctionBegin; 9401 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9402 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9403 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9404 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9405 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9406 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9407 PetscFunctionReturn(0); 9408 } 9409 9410 #undef __FUNCT__ 9411 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9412 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9413 { 9414 DM_Plex *mesh = (DM_Plex *) dm->data; 9415 9416 PetscFunctionBegin; 9417 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9418 PetscValidPointer(cellHeight, 2); 9419 *cellHeight = mesh->vtkCellHeight; 9420 PetscFunctionReturn(0); 9421 } 9422 9423 #undef __FUNCT__ 9424 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9425 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9426 { 9427 DM_Plex *mesh = (DM_Plex *) dm->data; 9428 9429 PetscFunctionBegin; 9430 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9431 mesh->vtkCellHeight = cellHeight; 9432 PetscFunctionReturn(0); 9433 } 9434 9435 #undef __FUNCT__ 9436 #define __FUNCT__ "DMPlexInsertFace_Private" 9437 /* 9438 DMPlexInsertFace_Private - Puts a face into the mesh 9439 9440 Not collective 9441 9442 Input Parameters: 9443 + dm - The DMPlex 9444 . numFaceVertex - The number of vertices in the face 9445 . faceVertices - The vertices in the face for dm 9446 . subfaceVertices - The vertices in the face for subdm 9447 . numCorners - The number of vertices in the cell 9448 . cell - A cell in dm containing the face 9449 . subcell - A cell in subdm containing the face 9450 . firstFace - First face in the mesh 9451 - newFacePoint - Next face in the mesh 9452 9453 Output Parameters: 9454 . newFacePoint - Contains next face point number on input, updated on output 9455 9456 Level: developer 9457 */ 9458 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) 9459 { 9460 MPI_Comm comm = ((PetscObject) dm)->comm; 9461 DM_Plex *submesh = (DM_Plex *) subdm->data; 9462 const PetscInt *faces; 9463 PetscInt numFaces, coneSize; 9464 PetscErrorCode ierr; 9465 9466 PetscFunctionBegin; 9467 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9468 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9469 #if 0 9470 /* Cannot use this because support() has not been constructed yet */ 9471 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9472 #else 9473 { 9474 PetscInt f; 9475 9476 numFaces = 0; 9477 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 9478 for (f = firstFace; f < *newFacePoint; ++f) { 9479 PetscInt dof, off, d; 9480 9481 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9482 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9483 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9484 for (d = 0; d < dof; ++d) { 9485 const PetscInt p = submesh->cones[off+d]; 9486 PetscInt v; 9487 9488 for (v = 0; v < numFaceVertices; ++v) { 9489 if (subfaceVertices[v] == p) break; 9490 } 9491 if (v == numFaceVertices) break; 9492 } 9493 if (d == dof) { 9494 numFaces = 1; 9495 ((PetscInt *) faces)[0] = f; 9496 } 9497 } 9498 } 9499 #endif 9500 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 9501 else if (numFaces == 1) { 9502 /* Add the other cell neighbor for this face */ 9503 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 9504 } else { 9505 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 9506 PetscBool posOriented; 9507 9508 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9509 origVertices = &orientedVertices[numFaceVertices]; 9510 indices = &orientedVertices[numFaceVertices*2]; 9511 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 9512 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 9513 /* TODO: I know that routine should return a permutation, not the indices */ 9514 for (v = 0; v < numFaceVertices; ++v) { 9515 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 9516 for (ov = 0; ov < numFaceVertices; ++ov) { 9517 if (orientedVertices[ov] == vertex) { 9518 orientedSubVertices[ov] = subvertex; 9519 break; 9520 } 9521 } 9522 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 9523 } 9524 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 9525 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 9526 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 9527 ++(*newFacePoint); 9528 } 9529 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9530 PetscFunctionReturn(0); 9531 } 9532 9533 #undef __FUNCT__ 9534 #define __FUNCT__ "DMPlexCreateSubmesh" 9535 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 9536 { 9537 MPI_Comm comm = ((PetscObject) dm)->comm; 9538 DM_Plex *submesh; 9539 PetscBool boundaryFaces = PETSC_FALSE; 9540 PetscSection coordSection, subCoordSection; 9541 Vec coordinates, subCoordinates; 9542 PetscScalar *coords, *subCoords; 9543 IS labelIS; 9544 const PetscInt *subVertices; 9545 PetscInt *subVerticesActive, *tmpPoints; 9546 PetscInt *subCells = PETSC_NULL; 9547 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 9548 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 9549 PetscInt dim; /* Right now, do not specify dimension */ 9550 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 9551 PetscErrorCode ierr; 9552 9553 PetscFunctionBegin; 9554 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9555 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9556 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9557 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 9558 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9559 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9560 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9561 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9562 subface = &face[maxConeSize]; 9563 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 9564 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 9565 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 9566 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 9567 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 9568 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 9569 maxSubCells = numSubVertices; 9570 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 9571 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 9572 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 9573 for (v = 0; v < numSubVertices; ++v) { 9574 const PetscInt vertex = subVertices[v]; 9575 PetscInt *star = PETSC_NULL; 9576 PetscInt starSize, numCells = 0; 9577 9578 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9579 for (p = 0; p < starSize*2; p += 2) { 9580 const PetscInt point = star[p]; 9581 if ((point >= cStart) && (point < cEnd)) { 9582 star[numCells++] = point; 9583 } 9584 } 9585 numOldSubCells = numSubCells; 9586 for (c = 0; c < numCells; ++c) { 9587 const PetscInt cell = star[c]; 9588 PetscInt *closure = PETSC_NULL; 9589 PetscInt closureSize, numCorners = 0, faceSize = 0; 9590 PetscInt cellLoc; 9591 9592 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 9593 if (cellLoc >= 0) continue; 9594 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9595 for (p = 0; p < closureSize*2; p += 2) { 9596 const PetscInt point = closure[p]; 9597 if ((point >= vStart) && (point < vEnd)) { 9598 closure[numCorners++] = point; 9599 } 9600 } 9601 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9602 for (corner = 0; corner < numCorners; ++corner) { 9603 const PetscInt cellVertex = closure[corner]; 9604 PetscInt subVertex; 9605 9606 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9607 if (subVertex >= 0) { /* contains submesh vertex */ 9608 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9609 if (i == faceSize) { 9610 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9611 face[faceSize] = cellVertex; 9612 subface[faceSize] = subVertex; 9613 ++faceSize; 9614 } 9615 } 9616 } 9617 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9618 if (faceSize >= nFV) { 9619 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9620 if (numSubCells >= maxSubCells) { 9621 PetscInt *tmpCells; 9622 maxSubCells *= 2; 9623 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9624 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9625 ierr = PetscFree(subCells);CHKERRQ(ierr); 9626 subCells = tmpCells; 9627 } 9628 /* TOOD: Maybe overestimate then squeeze out empty faces */ 9629 if (faceSize > nFV) { 9630 /* TODO: This is tricky. Maybe just add all faces */ 9631 numSubFaces++; 9632 } else { 9633 numSubFaces++; 9634 } 9635 for (f = 0; f < faceSize; ++f) { 9636 subVerticesActive[subface[f]] = 1; 9637 } 9638 subCells[numSubCells++] = cell; 9639 } 9640 } 9641 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9642 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9643 } 9644 /* Pick out active subvertices */ 9645 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9646 if (subVerticesActive[v]) { 9647 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9648 } 9649 } 9650 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9651 /* Set cone sizes */ 9652 firstSubVertex = numSubCells; 9653 firstSubFace = numSubCells+numSubVerticesActive; 9654 newFacePoint = firstSubFace; 9655 for (c = 0; c < numSubCells; ++c) { 9656 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 9657 } 9658 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9659 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 9660 } 9661 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 9662 /* Create face cones */ 9663 for (c = 0; c < numSubCells; ++c) { 9664 const PetscInt cell = subCells[c]; 9665 PetscInt *closure = PETSC_NULL; 9666 PetscInt closureSize, numCorners = 0, faceSize = 0; 9667 9668 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9669 for (p = 0; p < closureSize*2; p += 2) { 9670 const PetscInt point = closure[p]; 9671 if ((point >= vStart) && (point < vEnd)) { 9672 closure[numCorners++] = point; 9673 } 9674 } 9675 for (corner = 0; corner < numCorners; ++corner) { 9676 const PetscInt cellVertex = closure[corner]; 9677 PetscInt subVertex; 9678 9679 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9680 if (subVertex >= 0) { /* contains submesh vertex */ 9681 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9682 if (i == faceSize) { 9683 face[faceSize] = cellVertex; 9684 subface[faceSize] = numSubCells+subVertex; 9685 ++faceSize; 9686 } 9687 } 9688 } 9689 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9690 if (faceSize >= nFV) { 9691 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9692 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 9693 /* We have to take all the faces, and discard those in the interior */ 9694 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 9695 #if 0 9696 /* This object just calls insert on each face that comes from subsets() */ 9697 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 9698 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9699 PointArray faceVec(face->begin(), face->end()); 9700 9701 subsets(faceVec, nFV, inserter); 9702 #endif 9703 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 9704 } 9705 } 9706 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 9707 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 9708 /* Build coordinates */ 9709 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9710 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9711 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 9712 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 9713 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 9714 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 9715 } 9716 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 9717 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 9718 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 9719 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 9720 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 9721 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9722 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9723 for (v = 0; v < numSubVerticesActive; ++v) { 9724 const PetscInt vertex = subVerticesActive[v]; 9725 const PetscInt subVertex = firstSubVertex+v; 9726 PetscInt dof, off, sdof, soff; 9727 9728 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 9729 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 9730 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 9731 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 9732 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 9733 for (d = 0; d < dof; ++d) { 9734 subCoords[soff+d] = coords[off+d]; 9735 } 9736 } 9737 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9738 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9739 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 9740 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 9741 9742 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 9743 /* Create map from submesh points to original mesh points */ 9744 submesh = (DM_Plex *) (*subdm)->data; 9745 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 9746 for (c = 0; c < numSubCells; ++c) { 9747 tmpPoints[c] = subCells[c]; 9748 } 9749 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 9750 tmpPoints[v] = subVerticesActive[v-numSubCells]; 9751 } 9752 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 9753 9754 ierr = PetscFree(subCells);CHKERRQ(ierr); 9755 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 9756 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 9757 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 9758 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9759 PetscFunctionReturn(0); 9760 } 9761 9762 #undef __FUNCT__ 9763 #define __FUNCT__ "DMPlexCreateNumbering_Private" 9764 /* We can easily have a form that takes an IS instead */ 9765 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9766 { 9767 PetscSection section, globalSection; 9768 PetscInt *numbers, p; 9769 PetscErrorCode ierr; 9770 9771 PetscFunctionBegin; 9772 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9773 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9774 for (p = pStart; p < pEnd; ++p) { 9775 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9776 } 9777 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9778 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9779 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9780 for (p = pStart; p < pEnd; ++p) { 9781 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9782 } 9783 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9784 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9785 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9786 PetscFunctionReturn(0); 9787 } 9788 9789 #undef __FUNCT__ 9790 #define __FUNCT__ "DMPlexGetCellNumbering" 9791 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9792 { 9793 DM_Plex *mesh = (DM_Plex *) dm->data; 9794 PetscInt cellHeight, cStart, cEnd, cMax; 9795 PetscErrorCode ierr; 9796 9797 PetscFunctionBegin; 9798 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9799 if (!mesh->globalCellNumbers) { 9800 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9801 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9802 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 9803 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9804 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9805 } 9806 *globalCellNumbers = mesh->globalCellNumbers; 9807 PetscFunctionReturn(0); 9808 } 9809 9810 #undef __FUNCT__ 9811 #define __FUNCT__ "DMPlexGetVertexNumbering" 9812 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9813 { 9814 DM_Plex *mesh = (DM_Plex *) dm->data; 9815 PetscInt vStart, vEnd, vMax; 9816 PetscErrorCode ierr; 9817 9818 PetscFunctionBegin; 9819 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9820 if (!mesh->globalVertexNumbers) { 9821 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9822 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 9823 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9824 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9825 } 9826 *globalVertexNumbers = mesh->globalVertexNumbers; 9827 PetscFunctionReturn(0); 9828 } 9829 9830 #undef __FUNCT__ 9831 #define __FUNCT__ "DMPlexGetSubpointMap" 9832 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 9833 { 9834 DM_Plex *mesh = (DM_Plex *) dm->data; 9835 9836 PetscFunctionBegin; 9837 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9838 PetscValidPointer(subpointMap, 2); 9839 *subpointMap = mesh->subpointMap; 9840 PetscFunctionReturn(0); 9841 } 9842 9843 #undef __FUNCT__ 9844 #define __FUNCT__ "DMPlexSetSubpointMap" 9845 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 9846 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 9847 { 9848 DM_Plex *mesh = (DM_Plex *) dm->data; 9849 9850 PetscFunctionBegin; 9851 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9852 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 9853 mesh->subpointMap = subpointMap; 9854 PetscFunctionReturn(0); 9855 } 9856 9857 #undef __FUNCT__ 9858 #define __FUNCT__ "DMPlexGetScale" 9859 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9860 { 9861 DM_Plex *mesh = (DM_Plex *) dm->data; 9862 9863 PetscFunctionBegin; 9864 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9865 PetscValidPointer(scale, 3); 9866 *scale = mesh->scale[unit]; 9867 PetscFunctionReturn(0); 9868 } 9869 9870 #undef __FUNCT__ 9871 #define __FUNCT__ "DMPlexSetScale" 9872 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9873 { 9874 DM_Plex *mesh = (DM_Plex *) dm->data; 9875 9876 PetscFunctionBegin; 9877 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9878 mesh->scale[unit] = scale; 9879 PetscFunctionReturn(0); 9880 } 9881 9882 9883 /******************************************************************************* 9884 This should be in a separate Discretization object, but I am not sure how to lay 9885 it out yet, so I am stuffing things here while I experiment. 9886 *******************************************************************************/ 9887 #undef __FUNCT__ 9888 #define __FUNCT__ "DMPlexSetFEMIntegration" 9889 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9890 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9891 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9892 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9893 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9894 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9895 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9896 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9897 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9898 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9899 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9900 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9901 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9902 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9903 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9904 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9905 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9906 { 9907 DM_Plex *mesh = (DM_Plex *) dm->data; 9908 9909 PetscFunctionBegin; 9910 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9911 mesh->integrateResidualFEM = integrateResidualFEM; 9912 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9913 mesh->integrateJacobianFEM = integrateJacobianFEM; 9914 PetscFunctionReturn(0); 9915 } 9916 9917 #undef __FUNCT__ 9918 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9919 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9920 { 9921 Vec coordinates; 9922 PetscSection section, cSection; 9923 PetscInt dim, vStart, vEnd, v, c, d; 9924 PetscScalar *values, *cArray; 9925 PetscReal *coords; 9926 PetscErrorCode ierr; 9927 9928 PetscFunctionBegin; 9929 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9930 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9931 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9932 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9933 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9934 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9935 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9936 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9937 for (v = vStart; v < vEnd; ++v) { 9938 PetscInt dof, off; 9939 9940 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9941 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9942 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9943 for (d = 0; d < dof; ++d) { 9944 coords[d] = PetscRealPart(cArray[off+d]); 9945 } 9946 for (c = 0; c < numComp; ++c) { 9947 values[c] = (*funcs[c])(coords); 9948 } 9949 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9950 } 9951 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9952 /* Temporary, must be replaced by a projection on the finite element basis */ 9953 { 9954 PetscInt eStart = 0, eEnd = 0, e, depth; 9955 9956 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9957 --depth; 9958 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9959 for (e = eStart; e < eEnd; ++e) { 9960 const PetscInt *cone = PETSC_NULL; 9961 PetscInt coneSize, d; 9962 PetscScalar *coordsA, *coordsB; 9963 9964 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9965 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9966 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9967 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9968 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9969 for (d = 0; d < dim; ++d) { 9970 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9971 } 9972 for (c = 0; c < numComp; ++c) { 9973 values[c] = (*funcs[c])(coords); 9974 } 9975 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9976 } 9977 } 9978 9979 ierr = PetscFree(coords);CHKERRQ(ierr); 9980 ierr = PetscFree(values);CHKERRQ(ierr); 9981 #if 0 9982 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9983 PetscReal detJ; 9984 9985 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9986 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9987 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9988 9989 for (PetscInt c = cStart; c < cEnd; ++c) { 9990 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9991 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9992 const int oSize = pV.getSize(); 9993 int v = 0; 9994 9995 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 9996 for (PetscInt cl = 0; cl < oSize; ++cl) { 9997 const PetscInt fDim; 9998 9999 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10000 if (pointDim) { 10001 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10002 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10003 } 10004 } 10005 } 10006 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10007 pV.clear(); 10008 } 10009 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10010 ierr = PetscFree(values);CHKERRQ(ierr); 10011 #endif 10012 PetscFunctionReturn(0); 10013 } 10014 10015 #undef __FUNCT__ 10016 #define __FUNCT__ "DMPlexProjectFunction" 10017 /*@C 10018 DMPlexProjectFunction - This projects the given function into the function space provided. 10019 10020 Input Parameters: 10021 + dm - The DM 10022 . numComp - The number of components (functions) 10023 . funcs - The coordinate functions to evaluate 10024 - mode - The insertion mode for values 10025 10026 Output Parameter: 10027 . X - vector 10028 10029 Level: developer 10030 10031 Note: 10032 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10033 We will eventually fix it. 10034 10035 ,seealso: DMPlexComputeL2Diff() 10036 */ 10037 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10038 { 10039 Vec localX; 10040 PetscErrorCode ierr; 10041 10042 PetscFunctionBegin; 10043 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10044 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10045 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10046 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10047 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10048 PetscFunctionReturn(0); 10049 } 10050 10051 #undef __FUNCT__ 10052 #define __FUNCT__ "DMPlexComputeL2Diff" 10053 /*@C 10054 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10055 10056 Input Parameters: 10057 + dm - The DM 10058 . quad - The PetscQuadrature object for each field 10059 . funcs - The functions to evaluate for each field component 10060 - X - The coefficient vector u_h 10061 10062 Output Parameter: 10063 . diff - The diff ||u - u_h||_2 10064 10065 Level: developer 10066 10067 .seealso: DMPlexProjectFunction() 10068 */ 10069 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10070 { 10071 const PetscInt debug = 0; 10072 PetscSection section; 10073 Vec localX; 10074 PetscReal *coords, *v0, *J, *invJ, detJ; 10075 PetscReal localDiff = 0.0; 10076 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10077 PetscErrorCode ierr; 10078 10079 PetscFunctionBegin; 10080 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10081 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10082 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10083 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10084 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10085 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10086 for (field = 0; field < numFields; ++field) { 10087 numComponents += quad[field].numComponents; 10088 } 10089 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10090 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10091 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10092 for (c = cStart; c < cEnd; ++c) { 10093 const PetscScalar *x; 10094 PetscReal elemDiff = 0.0; 10095 10096 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10097 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10098 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10099 10100 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10101 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10102 const PetscReal *quadPoints = quad[field].quadPoints; 10103 const PetscReal *quadWeights = quad[field].quadWeights; 10104 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10105 const PetscInt numBasisComps = quad[field].numComponents; 10106 const PetscReal *basis = quad[field].basis; 10107 PetscInt q, d, e, fc, f; 10108 10109 if (debug) { 10110 char title[1024]; 10111 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10112 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10113 } 10114 for (q = 0; q < numQuadPoints; ++q) { 10115 for (d = 0; d < dim; d++) { 10116 coords[d] = v0[d]; 10117 for (e = 0; e < dim; e++) { 10118 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10119 } 10120 } 10121 for (fc = 0; fc < numBasisComps; ++fc) { 10122 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10123 PetscReal interpolant = 0.0; 10124 for (f = 0; f < numBasisFuncs; ++f) { 10125 const PetscInt fidx = f*numBasisComps+fc; 10126 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10127 } 10128 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10129 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10130 } 10131 } 10132 comp += numBasisComps; 10133 fieldOffset += numBasisFuncs*numBasisComps; 10134 } 10135 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10136 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10137 localDiff += elemDiff; 10138 } 10139 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10140 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10141 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10142 *diff = PetscSqrtReal(*diff); 10143 PetscFunctionReturn(0); 10144 } 10145 10146 #undef __FUNCT__ 10147 #define __FUNCT__ "DMPlexComputeResidualFEM" 10148 /*@ 10149 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10150 10151 Input Parameters: 10152 + dm - The mesh 10153 . X - Local input vector 10154 - user - The user context 10155 10156 Output Parameter: 10157 . F - Local output vector 10158 10159 Note: 10160 The second member of the user context must be an FEMContext. 10161 10162 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10163 like a GPU, or vectorize on a multicore machine. 10164 10165 .seealso: DMPlexComputeJacobianActionFEM() 10166 */ 10167 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10168 { 10169 DM_Plex *mesh = (DM_Plex *) dm->data; 10170 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10171 PetscQuadrature *quad = fem->quad; 10172 PetscSection section; 10173 PetscReal *v0, *J, *invJ, *detJ; 10174 PetscScalar *elemVec, *u; 10175 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10176 PetscInt cellDof = 0, numComponents = 0; 10177 PetscErrorCode ierr; 10178 10179 PetscFunctionBegin; 10180 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10181 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10182 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10183 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10184 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10185 numCells = cEnd - cStart; 10186 for (field = 0; field < numFields; ++field) { 10187 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10188 numComponents += quad[field].numComponents; 10189 } 10190 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10191 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10192 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); 10193 for (c = cStart; c < cEnd; ++c) { 10194 const PetscScalar *x; 10195 PetscInt i; 10196 10197 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10198 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10199 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10200 10201 for (i = 0; i < cellDof; ++i) { 10202 u[c*cellDof+i] = x[i]; 10203 } 10204 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10205 } 10206 for (field = 0; field < numFields; ++field) { 10207 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10208 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10209 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10210 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10211 /* Conforming batches */ 10212 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10213 PetscInt numBlocks = 1; 10214 PetscInt batchSize = numBlocks * blockSize; 10215 PetscInt numBatches = numBatchesTmp; 10216 PetscInt numChunks = numCells / (numBatches*batchSize); 10217 /* Remainder */ 10218 PetscInt numRemainder = numCells % (numBatches * batchSize); 10219 PetscInt offset = numCells - numRemainder; 10220 10221 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10222 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10223 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10224 } 10225 for (c = cStart; c < cEnd; ++c) { 10226 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10227 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10228 } 10229 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10230 if (mesh->printFEM) { 10231 PetscMPIInt rank, numProcs; 10232 PetscInt p; 10233 10234 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10235 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10236 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10237 for (p = 0; p < numProcs; ++p) { 10238 if (p == rank) { 10239 Vec f; 10240 10241 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10242 ierr = VecCopy(F, f);CHKERRQ(ierr); 10243 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10244 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10245 ierr = VecDestroy(&f);CHKERRQ(ierr); 10246 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10247 } 10248 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10249 } 10250 } 10251 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10252 PetscFunctionReturn(0); 10253 } 10254 10255 #undef __FUNCT__ 10256 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10257 /*@C 10258 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10259 10260 Input Parameters: 10261 + dm - The mesh 10262 . J - The Jacobian shell matrix 10263 . X - Local input vector 10264 - user - The user context 10265 10266 Output Parameter: 10267 . F - Local output vector 10268 10269 Note: 10270 The second member of the user context must be an FEMContext. 10271 10272 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10273 like a GPU, or vectorize on a multicore machine. 10274 10275 .seealso: DMPlexComputeResidualFEM() 10276 */ 10277 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10278 { 10279 DM_Plex *mesh = (DM_Plex *) dm->data; 10280 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10281 PetscQuadrature *quad = fem->quad; 10282 PetscSection section; 10283 JacActionCtx *jctx; 10284 PetscReal *v0, *J, *invJ, *detJ; 10285 PetscScalar *elemVec, *u, *a; 10286 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10287 PetscInt cellDof = 0; 10288 PetscErrorCode ierr; 10289 10290 PetscFunctionBegin; 10291 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10292 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10293 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10294 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10295 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10296 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10297 numCells = cEnd - cStart; 10298 for (field = 0; field < numFields; ++field) { 10299 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10300 } 10301 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10302 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); 10303 for (c = cStart; c < cEnd; ++c) { 10304 const PetscScalar *x; 10305 PetscInt i; 10306 10307 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10308 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10309 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10310 for (i = 0; i < cellDof; ++i) { 10311 u[c*cellDof+i] = x[i]; 10312 } 10313 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10314 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10315 for (i = 0; i < cellDof; ++i) { 10316 a[c*cellDof+i] = x[i]; 10317 } 10318 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10319 } 10320 for (field = 0; field < numFields; ++field) { 10321 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10322 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10323 /* Conforming batches */ 10324 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10325 PetscInt numBlocks = 1; 10326 PetscInt batchSize = numBlocks * blockSize; 10327 PetscInt numBatches = numBatchesTmp; 10328 PetscInt numChunks = numCells / (numBatches*batchSize); 10329 /* Remainder */ 10330 PetscInt numRemainder = numCells % (numBatches * batchSize); 10331 PetscInt offset = numCells - numRemainder; 10332 10333 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); 10334 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], 10335 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10336 } 10337 for (c = cStart; c < cEnd; ++c) { 10338 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10339 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10340 } 10341 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10342 if (mesh->printFEM) { 10343 PetscMPIInt rank, numProcs; 10344 PetscInt p; 10345 10346 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10347 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10348 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10349 for (p = 0; p < numProcs; ++p) { 10350 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10351 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10352 } 10353 } 10354 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10355 PetscFunctionReturn(0); 10356 } 10357 10358 #undef __FUNCT__ 10359 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10360 /*@ 10361 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10362 10363 Input Parameters: 10364 + dm - The mesh 10365 . X - Local input vector 10366 - user - The user context 10367 10368 Output Parameter: 10369 . Jac - Jacobian matrix 10370 10371 Note: 10372 The second member of the user context must be an FEMContext. 10373 10374 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10375 like a GPU, or vectorize on a multicore machine. 10376 10377 .seealso: FormFunctionLocal() 10378 */ 10379 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10380 { 10381 DM_Plex *mesh = (DM_Plex *) dm->data; 10382 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10383 PetscQuadrature *quad = fem->quad; 10384 PetscSection section; 10385 PetscReal *v0, *J, *invJ, *detJ; 10386 PetscScalar *elemMat, *u; 10387 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10388 PetscInt cellDof = 0, numComponents = 0; 10389 PetscBool isShell; 10390 PetscErrorCode ierr; 10391 10392 PetscFunctionBegin; 10393 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10394 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10395 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10396 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10397 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10398 numCells = cEnd - cStart; 10399 for (field = 0; field < numFields; ++field) { 10400 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10401 numComponents += quad[field].numComponents; 10402 } 10403 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10404 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10405 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); 10406 for (c = cStart; c < cEnd; ++c) { 10407 const PetscScalar *x; 10408 PetscInt i; 10409 10410 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10411 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10412 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10413 10414 for (i = 0; i < cellDof; ++i) { 10415 u[c*cellDof+i] = x[i]; 10416 } 10417 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10418 } 10419 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10420 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10421 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10422 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10423 PetscInt fieldJ; 10424 10425 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10426 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10427 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10428 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10429 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10430 /* Conforming batches */ 10431 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10432 PetscInt numBlocks = 1; 10433 PetscInt batchSize = numBlocks * blockSize; 10434 PetscInt numBatches = numBatchesTmp; 10435 PetscInt numChunks = numCells / (numBatches*batchSize); 10436 /* Remainder */ 10437 PetscInt numRemainder = numCells % (numBatches * batchSize); 10438 PetscInt offset = numCells - numRemainder; 10439 10440 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10441 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10442 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10443 } 10444 } 10445 for (c = cStart; c < cEnd; ++c) { 10446 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10447 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10448 } 10449 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10450 10451 /* Assemble matrix, using the 2-step process: 10452 MatAssemblyBegin(), MatAssemblyEnd(). */ 10453 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10454 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10455 10456 if (mesh->printFEM) { 10457 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10458 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10459 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10460 } 10461 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10462 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10463 if (isShell) { 10464 JacActionCtx *jctx; 10465 10466 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10467 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10468 } 10469 *str = SAME_NONZERO_PATTERN; 10470 PetscFunctionReturn(0); 10471 } 10472 10473 10474 #undef __FUNCT__ 10475 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10476 /*@C 10477 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10478 the local section and an SF describing the section point overlap. 10479 10480 Input Parameters: 10481 + s - The PetscSection for the local field layout 10482 . sf - The SF describing parallel layout of the section points 10483 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10484 . label - The label specifying the points 10485 - labelValue - The label stratum specifying the points 10486 10487 Output Parameter: 10488 . gsection - The PetscSection for the global field layout 10489 10490 Note: This gives negative sizes and offsets to points not owned by this process 10491 10492 Level: developer 10493 10494 .seealso: PetscSectionCreate() 10495 @*/ 10496 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10497 { 10498 PetscInt *neg; 10499 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10500 PetscErrorCode ierr; 10501 10502 PetscFunctionBegin; 10503 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10504 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10505 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10506 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10507 /* Mark ghost points with negative dof */ 10508 for (p = pStart; p < pEnd; ++p) { 10509 PetscInt value; 10510 10511 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 10512 if (value != labelValue) continue; 10513 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 10514 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 10515 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 10516 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 10517 neg[p-pStart] = -(dof+1); 10518 } 10519 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 10520 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10521 if (nroots >= 0) { 10522 if (nroots > pEnd - pStart) { 10523 PetscInt *tmpDof; 10524 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10525 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 10526 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10527 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 10528 for (p = pStart; p < pEnd; ++p) { 10529 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 10530 } 10531 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 10532 } else { 10533 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10534 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 10535 } 10536 } 10537 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 10538 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10539 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 10540 (*gsection)->atlasOff[p] = off; 10541 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 10542 } 10543 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 10544 globalOff -= off; 10545 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 10546 (*gsection)->atlasOff[p] += globalOff; 10547 neg[p] = -((*gsection)->atlasOff[p]+1); 10548 } 10549 /* Put in negative offsets for ghost points */ 10550 if (nroots >= 0) { 10551 if (nroots > pEnd - pStart) { 10552 PetscInt *tmpOff; 10553 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 10554 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 10555 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10556 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 10557 for (p = pStart; p < pEnd; ++p) { 10558 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 10559 } 10560 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 10561 } else { 10562 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10563 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 10564 } 10565 } 10566 ierr = PetscFree(neg);CHKERRQ(ierr); 10567 PetscFunctionReturn(0); 10568 } 10569