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