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