1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex *) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 167 if (size > 1) { 168 PetscSF sf; 169 170 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 171 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 172 } 173 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 174 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 175 const char *name; 176 const char *colors[3] = {"red", "blue", "green"}; 177 const int numColors = 3; 178 PetscReal scale = 2.0; 179 PetscScalar *coords; 180 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 181 PetscMPIInt rank, size; 182 183 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 184 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 185 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 186 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 187 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 188 ierr = PetscViewerASCIIPrintf(viewer, "\ 189 \\documentclass[crop,multi=false]{standalone}\n\n\ 190 \\usepackage{tikz}\n\ 191 \\usepackage{pgflibraryshapes}\n\ 192 \\usetikzlibrary{backgrounds}\n\ 193 \\usetikzlibrary{arrows}\n\ 194 \\begin{document}\n\ 195 \\section{%s}\n\ 196 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 197 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 198 for (p = 0; p < size; ++p) { 199 if (p > 0 && p == size-1) { 200 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 201 } else if (p > 0) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 203 } 204 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 207 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 208 /* Plot vertices */ 209 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 210 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 211 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 212 for (v = vStart; v < vEnd; ++v) { 213 PetscInt off, dof, d; 214 215 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 216 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 217 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 218 for (d = 0; d < dof; ++d) { 219 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 220 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 221 } 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 223 } 224 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 225 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 226 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 227 /* Plot edges */ 228 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 229 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 230 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 231 for (e = eStart; e < eEnd; ++e) { 232 const PetscInt *cone; 233 PetscInt coneSize, offA, offB, dof, d; 234 235 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 236 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 237 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 238 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 239 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 240 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 241 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 242 for (d = 0; d < dof; ++d) { 243 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 244 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 245 } 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 247 } 248 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 249 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 250 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 251 /* Plot cells */ 252 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 253 for (c = cStart; c < cEnd; ++c) { 254 PetscInt *closure = PETSC_NULL; 255 PetscInt closureSize, firstPoint = -1; 256 257 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 258 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 259 for (p = 0; p < closureSize*2; p += 2) { 260 const PetscInt point = closure[p]; 261 262 if ((point < vStart) || (point >= vEnd)) continue; 263 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 264 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 265 if (firstPoint < 0) firstPoint = point; 266 } 267 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 268 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 269 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 270 } 271 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 272 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 273 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 274 } else { 275 MPI_Comm comm = ((PetscObject) dm)->comm; 276 PetscInt *sizes; 277 PetscInt locDepth, depth, dim, d; 278 PetscInt pStart, pEnd, p; 279 PetscMPIInt size; 280 281 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 282 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 283 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 284 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 285 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 286 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 287 if (depth == 1) { 288 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 289 pEnd = pEnd - pStart; 290 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 291 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 292 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 293 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 294 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 295 pEnd = pEnd - pStart; 296 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 297 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 298 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 299 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 300 } else { 301 for (d = 0; d <= dim; d++) { 302 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 303 pEnd = pEnd - pStart; 304 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 305 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 306 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 307 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 308 } 309 } 310 ierr = PetscFree(sizes);CHKERRQ(ierr); 311 } 312 PetscFunctionReturn(0); 313 } 314 315 #undef __FUNCT__ 316 #define __FUNCT__ "DMView_Plex" 317 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 318 { 319 PetscBool iascii, isbinary; 320 PetscErrorCode ierr; 321 322 PetscFunctionBegin; 323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 324 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 325 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 326 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 327 if (iascii) { 328 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 329 #if 0 330 } else if (isbinary) { 331 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 332 #endif 333 } 334 PetscFunctionReturn(0); 335 } 336 337 #undef __FUNCT__ 338 #define __FUNCT__ "DMDestroy_Plex" 339 PetscErrorCode DMDestroy_Plex(DM dm) 340 { 341 DM_Plex *mesh = (DM_Plex *) dm->data; 342 DMLabel next = mesh->labels; 343 PetscErrorCode ierr; 344 345 PetscFunctionBegin; 346 if (--mesh->refct > 0) {PetscFunctionReturn(0);} 347 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 348 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 349 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 350 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 353 while (next) { 354 DMLabel tmp = next->next; 355 356 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 357 next = tmp; 358 } 359 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 360 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 361 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 362 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 363 ierr = PetscFree(mesh);CHKERRQ(ierr); 364 PetscFunctionReturn(0); 365 } 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 369 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 370 { 371 const PetscInt *support = PETSC_NULL; 372 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 373 PetscErrorCode ierr; 374 375 PetscFunctionBegin; 376 if (useClosure) { 377 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 378 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 379 for (s = 0; s < supportSize; ++s) { 380 const PetscInt *cone = PETSC_NULL; 381 PetscInt coneSize, c, q; 382 383 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 384 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 385 for (c = 0; c < coneSize; ++c) { 386 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 387 if (cone[c] == adj[q]) break; 388 } 389 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 390 } 391 } 392 } else { 393 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 394 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 395 for (s = 0; s < supportSize; ++s) { 396 const PetscInt *cone = PETSC_NULL; 397 PetscInt coneSize, c, q; 398 399 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 400 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 401 for (c = 0; c < coneSize; ++c) { 402 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 403 if (cone[c] == adj[q]) break; 404 } 405 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 406 } 407 } 408 } 409 *adjSize = numAdj; 410 PetscFunctionReturn(0); 411 } 412 413 #undef __FUNCT__ 414 #define __FUNCT__ "DMPlexGetAdjacency_Private" 415 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 416 { 417 const PetscInt *star = tmpClosure; 418 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 419 PetscErrorCode ierr; 420 421 PetscFunctionBegin; 422 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 423 for (s = 2; s < starSize*2; s += 2) { 424 const PetscInt *closure = PETSC_NULL; 425 PetscInt closureSize, c, q; 426 427 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 428 for (c = 0; c < closureSize*2; c += 2) { 429 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 430 if (closure[c] == adj[q]) break; 431 } 432 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 433 } 434 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 435 } 436 *adjSize = numAdj; 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNCT__ 441 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 442 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 443 { 444 DM_Plex *mesh = (DM_Plex *) dm->data; 445 446 PetscFunctionBegin; 447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 448 mesh->preallocCenterDim = preallocCenterDim; 449 PetscFunctionReturn(0); 450 } 451 452 #undef __FUNCT__ 453 #define __FUNCT__ "DMPlexPreallocateOperator" 454 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 455 { 456 DM_Plex *mesh = (DM_Plex *) dm->data; 457 MPI_Comm comm = ((PetscObject) dm)->comm; 458 PetscSF sf, sfDof, sfAdj; 459 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 460 PetscInt nleaves, l, p; 461 const PetscInt *leaves; 462 const PetscSFNode *remotes; 463 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 464 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 465 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 466 PetscLayout rLayout; 467 PetscInt locRows, rStart, rEnd, r; 468 PetscMPIInt size; 469 PetscBool useClosure, debug = PETSC_FALSE; 470 PetscErrorCode ierr; 471 472 PetscFunctionBegin; 473 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 474 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 475 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 476 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 477 /* Create dof SF based on point SF */ 478 if (debug) { 479 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 480 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 481 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 485 } 486 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 487 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 488 if (debug) { 489 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 490 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 491 } 492 /* Create section for dof adjacency (dof ==> # adj dof) */ 493 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 494 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 495 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 496 if (mesh->preallocCenterDim == dim) { 497 useClosure = PETSC_FALSE; 498 } else if (mesh->preallocCenterDim == 0) { 499 useClosure = PETSC_TRUE; 500 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 501 502 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 503 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 504 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 505 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 508 /* Fill in the ghost dofs on the interface */ 509 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 510 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 511 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 512 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 513 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 514 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 515 516 /* 517 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 518 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 519 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 520 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 521 Create sfAdj connecting rootSectionAdj and leafSectionAdj 522 3. Visit unowned points on interface, write adjacencies to adj 523 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 524 4. Visit owned points on interface, write adjacencies to rootAdj 525 Remove redundancy in rootAdj 526 ** The last two traversals use transitive closure 527 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 528 Allocate memory addressed by sectionAdj (cols) 529 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 530 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 531 */ 532 533 for (l = 0; l < nleaves; ++l) { 534 PetscInt dof, off, d, q; 535 PetscInt p = leaves[l], numAdj = maxAdjSize; 536 537 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 538 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 539 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 540 for (q = 0; q < numAdj; ++q) { 541 PetscInt ndof, ncdof; 542 543 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 544 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 545 for (d = off; d < off+dof; ++d) { 546 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 547 } 548 } 549 } 550 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 551 if (debug) { 552 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 553 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 554 } 555 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 556 if (size > 1) { 557 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 558 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 559 } 560 if (debug) { 561 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 562 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 563 } 564 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 565 for (p = pStart; p < pEnd; ++p) { 566 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 567 568 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 569 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 570 if (!dof) continue; 571 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 572 if (adof <= 0) continue; 573 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 574 for (q = 0; q < numAdj; ++q) { 575 PetscInt ndof, ncdof; 576 577 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 578 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 579 for (d = off; d < off+dof; ++d) { 580 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 581 } 582 } 583 } 584 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 585 if (debug) { 586 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 587 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 588 } 589 /* Create adj SF based on dof SF */ 590 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 591 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 592 if (debug) { 593 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 594 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 595 } 596 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 597 /* Create leaf adjacency */ 598 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 599 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 600 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 601 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 602 for (l = 0; l < nleaves; ++l) { 603 PetscInt dof, off, d, q; 604 PetscInt p = leaves[l], numAdj = maxAdjSize; 605 606 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 607 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 608 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 609 for (d = off; d < off+dof; ++d) { 610 PetscInt aoff, i = 0; 611 612 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 613 for (q = 0; q < numAdj; ++q) { 614 PetscInt ndof, ncdof, ngoff, nd; 615 616 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 617 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 618 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 619 for (nd = 0; nd < ndof-ncdof; ++nd) { 620 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 621 ++i; 622 } 623 } 624 } 625 } 626 /* Debugging */ 627 if (debug) { 628 IS tmp; 629 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 630 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 631 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 632 } 633 /* Gather adjacenct indices to root */ 634 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 635 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 636 for (r = 0; r < adjSize; ++r) { 637 rootAdj[r] = -1; 638 } 639 if (size > 1) { 640 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 641 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 642 } 643 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 644 ierr = PetscFree(adj);CHKERRQ(ierr); 645 /* Debugging */ 646 if (debug) { 647 IS tmp; 648 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 649 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 650 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 651 } 652 /* Add in local adjacency indices for owned dofs on interface (roots) */ 653 for (p = pStart; p < pEnd; ++p) { 654 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 655 656 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 657 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 658 if (!dof) continue; 659 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 660 if (adof <= 0) continue; 661 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 662 for (d = off; d < off+dof; ++d) { 663 PetscInt adof, aoff, i; 664 665 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 666 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 667 i = adof-1; 668 for (q = 0; q < numAdj; ++q) { 669 PetscInt ndof, ncdof, ngoff, nd; 670 671 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 672 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 673 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 674 for (nd = 0; nd < ndof-ncdof; ++nd) { 675 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 676 --i; 677 } 678 } 679 } 680 } 681 /* Debugging */ 682 if (debug) { 683 IS tmp; 684 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 685 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 686 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 687 } 688 /* Compress indices */ 689 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 690 for (p = pStart; p < pEnd; ++p) { 691 PetscInt dof, cdof, off, d; 692 PetscInt adof, aoff; 693 694 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 695 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 696 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 697 if (!dof) continue; 698 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 699 if (adof <= 0) continue; 700 for (d = off; d < off+dof-cdof; ++d) { 701 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 702 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 703 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 704 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 705 } 706 } 707 /* Debugging */ 708 if (debug) { 709 IS tmp; 710 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 711 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 712 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 713 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 714 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 715 } 716 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 717 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 718 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 719 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 720 for (p = pStart; p < pEnd; ++p) { 721 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 722 PetscBool found = PETSC_TRUE; 723 724 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 725 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 726 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 727 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 728 for (d = 0; d < dof-cdof; ++d) { 729 PetscInt ldof, rdof; 730 731 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 732 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 733 if (ldof > 0) { 734 /* We do not own this point */ 735 } else if (rdof > 0) { 736 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 737 } else { 738 found = PETSC_FALSE; 739 } 740 } 741 if (found) continue; 742 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 743 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 744 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 745 for (q = 0; q < numAdj; ++q) { 746 PetscInt ndof, ncdof, noff; 747 748 /* Adjacent points may not be in the section chart */ 749 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 750 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 751 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 752 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 753 for (d = goff; d < goff+dof-cdof; ++d) { 754 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 755 } 756 } 757 } 758 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 759 if (debug) { 760 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 761 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 762 } 763 /* Get adjacent indices */ 764 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 765 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 766 for (p = pStart; p < pEnd; ++p) { 767 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 768 PetscBool found = PETSC_TRUE; 769 770 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 771 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 772 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 773 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 774 for (d = 0; d < dof-cdof; ++d) { 775 PetscInt ldof, rdof; 776 777 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 778 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 779 if (ldof > 0) { 780 /* We do not own this point */ 781 } else if (rdof > 0) { 782 PetscInt aoff, roff; 783 784 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 786 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 787 } else { 788 found = PETSC_FALSE; 789 } 790 } 791 if (found) continue; 792 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 793 for (d = goff; d < goff+dof-cdof; ++d) { 794 PetscInt adof, aoff, i = 0; 795 796 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 797 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 798 for (q = 0; q < numAdj; ++q) { 799 PetscInt ndof, ncdof, ngoff, nd; 800 const PetscInt *ncind; 801 802 /* Adjacent points may not be in the section chart */ 803 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 804 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 805 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 806 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 807 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 808 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 809 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 810 } 811 } 812 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 813 } 814 } 815 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 816 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 817 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 818 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 819 /* Debugging */ 820 if (debug) { 821 IS tmp; 822 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 823 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 824 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 825 } 826 /* Create allocation vectors from adjacency graph */ 827 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 828 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 829 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 830 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 831 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 832 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 833 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 834 /* Only loop over blocks of rows */ 835 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 836 for (r = rStart/bs; r < rEnd/bs; ++r) { 837 const PetscInt row = r*bs; 838 PetscInt numCols, cStart, c; 839 840 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 841 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 842 for (c = cStart; c < cStart+numCols; ++c) { 843 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 844 ++dnz[r-rStart]; 845 if (cols[c] >= row) {++dnzu[r-rStart];} 846 } else { 847 ++onz[r-rStart]; 848 if (cols[c] >= row) {++onzu[r-rStart];} 849 } 850 } 851 } 852 if (bs > 1) { 853 for (r = 0; r < locRows/bs; ++r) { 854 dnz[r] /= bs; 855 onz[r] /= bs; 856 dnzu[r] /= bs; 857 onzu[r] /= bs; 858 } 859 } 860 /* Set matrix pattern */ 861 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 862 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 863 /* Fill matrix with zeros */ 864 if (fillMatrix) { 865 PetscScalar *values; 866 PetscInt maxRowLen = 0; 867 868 for (r = rStart; r < rEnd; ++r) { 869 PetscInt len; 870 871 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 872 maxRowLen = PetscMax(maxRowLen, len); 873 } 874 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 875 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 876 for (r = rStart; r < rEnd; ++r) { 877 PetscInt numCols, cStart; 878 879 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 880 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 881 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 882 } 883 ierr = PetscFree(values);CHKERRQ(ierr); 884 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 885 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 886 } 887 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 888 ierr = PetscFree(cols);CHKERRQ(ierr); 889 PetscFunctionReturn(0); 890 } 891 892 #if 0 893 #undef __FUNCT__ 894 #define __FUNCT__ "DMPlexPreallocateOperator_2" 895 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 896 { 897 PetscErrorCode ierr; 898 PetscInt c,cStart,cEnd,pStart,pEnd; 899 PetscInt *tmpClosure,*tmpAdj,*visits; 900 901 PetscFunctionBegin; 902 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 903 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 904 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 905 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 906 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 907 npoints = pEnd - pStart; 908 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 909 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 910 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 911 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 912 for (c=cStart; c<cEnd; c++) { 913 PetscInt *support = tmpClosure; 914 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 915 for (p=0; p<supportSize; p++) { 916 lvisits[support[p]]++; 917 } 918 } 919 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 920 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 921 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 922 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 923 924 ierr = PetscSFGetRanks();CHKERRQ(ierr); 925 926 927 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 928 for (c=cStart; c<cEnd; c++) { 929 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 930 /* 931 Depth-first walk of transitive closure. 932 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. 933 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 934 */ 935 } 936 937 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 938 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 939 PetscFunctionReturn(0); 940 } 941 #endif 942 943 #undef __FUNCT__ 944 #define __FUNCT__ "DMCreateMatrix_Plex" 945 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 946 { 947 PetscSection section, sectionGlobal; 948 PetscInt bs = -1; 949 PetscInt localSize; 950 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 951 PetscErrorCode ierr; 952 953 PetscFunctionBegin; 954 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 955 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 956 #endif 957 if (!mtype) mtype = MATAIJ; 958 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 959 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 960 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 961 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 962 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 963 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 964 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 965 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 966 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 967 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 973 /* Check for symmetric storage */ 974 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 975 if (isSymmetric) { 976 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 977 } 978 if (!isShell) { 979 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 980 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal; 981 982 if (bs < 0) { 983 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 984 PetscInt pStart, pEnd, p, dof; 985 986 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 987 for (p = pStart; p < pEnd; ++p) { 988 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 989 if (dof) { 990 bs = dof; 991 break; 992 } 993 } 994 } else { 995 bs = 1; 996 } 997 /* Must have same blocksize on all procs (some might have no points) */ 998 bsLocal = bs; 999 ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1000 } 1001 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1002 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1003 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1004 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1005 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1006 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1007 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1008 } 1009 PetscFunctionReturn(0); 1010 } 1011 1012 #undef __FUNCT__ 1013 #define __FUNCT__ "DMPlexGetDimension" 1014 /*@ 1015 DMPlexGetDimension - Return the topological mesh dimension 1016 1017 Not collective 1018 1019 Input Parameter: 1020 . mesh - The DMPlex 1021 1022 Output Parameter: 1023 . dim - The topological mesh dimension 1024 1025 Level: beginner 1026 1027 .seealso: DMPlexCreate() 1028 @*/ 1029 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1030 { 1031 DM_Plex *mesh = (DM_Plex *) dm->data; 1032 1033 PetscFunctionBegin; 1034 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1035 PetscValidPointer(dim, 2); 1036 *dim = mesh->dim; 1037 PetscFunctionReturn(0); 1038 } 1039 1040 #undef __FUNCT__ 1041 #define __FUNCT__ "DMPlexSetDimension" 1042 /*@ 1043 DMPlexSetDimension - Set the topological mesh dimension 1044 1045 Collective on mesh 1046 1047 Input Parameters: 1048 + mesh - The DMPlex 1049 - dim - The topological mesh dimension 1050 1051 Level: beginner 1052 1053 .seealso: DMPlexCreate() 1054 @*/ 1055 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1056 { 1057 DM_Plex *mesh = (DM_Plex *) dm->data; 1058 1059 PetscFunctionBegin; 1060 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1061 PetscValidLogicalCollectiveInt(dm, dim, 2); 1062 mesh->dim = dim; 1063 mesh->preallocCenterDim = dim; 1064 PetscFunctionReturn(0); 1065 } 1066 1067 #undef __FUNCT__ 1068 #define __FUNCT__ "DMPlexGetChart" 1069 /*@ 1070 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1071 1072 Not collective 1073 1074 Input Parameter: 1075 . mesh - The DMPlex 1076 1077 Output Parameters: 1078 + pStart - The first mesh point 1079 - pEnd - The upper bound for mesh points 1080 1081 Level: beginner 1082 1083 .seealso: DMPlexCreate(), DMPlexSetChart() 1084 @*/ 1085 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1086 { 1087 DM_Plex *mesh = (DM_Plex *) dm->data; 1088 PetscErrorCode ierr; 1089 1090 PetscFunctionBegin; 1091 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1092 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1093 PetscFunctionReturn(0); 1094 } 1095 1096 #undef __FUNCT__ 1097 #define __FUNCT__ "DMPlexSetChart" 1098 /*@ 1099 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1100 1101 Not collective 1102 1103 Input Parameters: 1104 + mesh - The DMPlex 1105 . pStart - The first mesh point 1106 - pEnd - The upper bound for mesh points 1107 1108 Output Parameters: 1109 1110 Level: beginner 1111 1112 .seealso: DMPlexCreate(), DMPlexGetChart() 1113 @*/ 1114 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1115 { 1116 DM_Plex *mesh = (DM_Plex *) dm->data; 1117 PetscErrorCode ierr; 1118 1119 PetscFunctionBegin; 1120 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1121 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1122 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1123 PetscFunctionReturn(0); 1124 } 1125 1126 #undef __FUNCT__ 1127 #define __FUNCT__ "DMPlexGetConeSize" 1128 /*@ 1129 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1130 1131 Not collective 1132 1133 Input Parameters: 1134 + mesh - The DMPlex 1135 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1136 1137 Output Parameter: 1138 . size - The cone size for point p 1139 1140 Level: beginner 1141 1142 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1143 @*/ 1144 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1145 { 1146 DM_Plex *mesh = (DM_Plex *) dm->data; 1147 PetscErrorCode ierr; 1148 1149 PetscFunctionBegin; 1150 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1151 PetscValidPointer(size, 3); 1152 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1153 PetscFunctionReturn(0); 1154 } 1155 1156 #undef __FUNCT__ 1157 #define __FUNCT__ "DMPlexSetConeSize" 1158 /*@ 1159 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1160 1161 Not collective 1162 1163 Input Parameters: 1164 + mesh - The DMPlex 1165 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1166 - size - The cone size for point p 1167 1168 Output Parameter: 1169 1170 Note: 1171 This should be called after DMPlexSetChart(). 1172 1173 Level: beginner 1174 1175 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1176 @*/ 1177 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1178 { 1179 DM_Plex *mesh = (DM_Plex *) dm->data; 1180 PetscErrorCode ierr; 1181 1182 PetscFunctionBegin; 1183 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1184 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1185 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1186 PetscFunctionReturn(0); 1187 } 1188 1189 #undef __FUNCT__ 1190 #define __FUNCT__ "DMPlexGetCone" 1191 /*@C 1192 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1193 1194 Not collective 1195 1196 Input Parameters: 1197 + mesh - The DMPlex 1198 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1199 1200 Output Parameter: 1201 . cone - An array of points which are on the in-edges for point p 1202 1203 Level: beginner 1204 1205 Note: 1206 This routine is not available in Fortran. 1207 1208 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1209 @*/ 1210 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1211 { 1212 DM_Plex *mesh = (DM_Plex *) dm->data; 1213 PetscInt off; 1214 PetscErrorCode ierr; 1215 1216 PetscFunctionBegin; 1217 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1218 PetscValidPointer(cone, 3); 1219 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1220 *cone = &mesh->cones[off]; 1221 PetscFunctionReturn(0); 1222 } 1223 1224 #undef __FUNCT__ 1225 #define __FUNCT__ "DMPlexSetCone" 1226 /*@ 1227 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1228 1229 Not collective 1230 1231 Input Parameters: 1232 + mesh - The DMPlex 1233 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1234 - cone - An array of points which are on the in-edges for point p 1235 1236 Output Parameter: 1237 1238 Note: 1239 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1240 1241 Level: beginner 1242 1243 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1244 @*/ 1245 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1246 { 1247 DM_Plex *mesh = (DM_Plex *) dm->data; 1248 PetscInt pStart, pEnd; 1249 PetscInt dof, off, c; 1250 PetscErrorCode ierr; 1251 1252 PetscFunctionBegin; 1253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1254 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1255 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1256 if (dof) PetscValidPointer(cone, 3); 1257 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1258 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); 1259 for (c = 0; c < dof; ++c) { 1260 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); 1261 mesh->cones[off+c] = cone[c]; 1262 } 1263 PetscFunctionReturn(0); 1264 } 1265 1266 #undef __FUNCT__ 1267 #define __FUNCT__ "DMPlexGetConeOrientation" 1268 /*@C 1269 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1270 1271 Not collective 1272 1273 Input Parameters: 1274 + mesh - The DMPlex 1275 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1276 1277 Output Parameter: 1278 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1279 integer giving the prescription for cone traversal. If it is negative, the cone is 1280 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1281 the index of the cone point on which to start. 1282 1283 Level: beginner 1284 1285 Note: 1286 This routine is not available in Fortran. 1287 1288 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1289 @*/ 1290 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1291 { 1292 DM_Plex *mesh = (DM_Plex *) dm->data; 1293 PetscInt off; 1294 PetscErrorCode ierr; 1295 1296 PetscFunctionBegin; 1297 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1298 #if defined(PETSC_USE_DEBUG) 1299 { 1300 PetscInt dof; 1301 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1302 if (dof) PetscValidPointer(coneOrientation, 3); 1303 } 1304 #endif 1305 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1306 *coneOrientation = &mesh->coneOrientations[off]; 1307 PetscFunctionReturn(0); 1308 } 1309 1310 #undef __FUNCT__ 1311 #define __FUNCT__ "DMPlexSetConeOrientation" 1312 /*@ 1313 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1314 1315 Not collective 1316 1317 Input Parameters: 1318 + mesh - The DMPlex 1319 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1320 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1321 integer giving the prescription for cone traversal. If it is negative, the cone is 1322 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1323 the index of the cone point on which to start. 1324 1325 Output Parameter: 1326 1327 Note: 1328 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1329 1330 Level: beginner 1331 1332 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1333 @*/ 1334 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1335 { 1336 DM_Plex *mesh = (DM_Plex *) dm->data; 1337 PetscInt pStart, pEnd; 1338 PetscInt dof, off, c; 1339 PetscErrorCode ierr; 1340 1341 PetscFunctionBegin; 1342 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1343 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1344 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1345 if (dof) PetscValidPointer(coneOrientation, 3); 1346 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1347 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); 1348 for (c = 0; c < dof; ++c) { 1349 PetscInt cdof, o = coneOrientation[c]; 1350 1351 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1352 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); 1353 mesh->coneOrientations[off+c] = o; 1354 } 1355 PetscFunctionReturn(0); 1356 } 1357 1358 #undef __FUNCT__ 1359 #define __FUNCT__ "DMPlexInsertCone" 1360 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1361 { 1362 DM_Plex *mesh = (DM_Plex *) dm->data; 1363 PetscInt pStart, pEnd; 1364 PetscInt dof, off; 1365 PetscErrorCode ierr; 1366 1367 PetscFunctionBegin; 1368 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1369 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1370 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1371 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1372 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); 1373 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); 1374 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); 1375 mesh->cones[off+conePos] = conePoint; 1376 PetscFunctionReturn(0); 1377 } 1378 1379 #undef __FUNCT__ 1380 #define __FUNCT__ "DMPlexGetSupportSize" 1381 /*@ 1382 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1383 1384 Not collective 1385 1386 Input Parameters: 1387 + mesh - The DMPlex 1388 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1389 1390 Output Parameter: 1391 . size - The support size for point p 1392 1393 Level: beginner 1394 1395 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1396 @*/ 1397 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1398 { 1399 DM_Plex *mesh = (DM_Plex *) dm->data; 1400 PetscErrorCode ierr; 1401 1402 PetscFunctionBegin; 1403 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1404 PetscValidPointer(size, 3); 1405 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1406 PetscFunctionReturn(0); 1407 } 1408 1409 #undef __FUNCT__ 1410 #define __FUNCT__ "DMPlexSetSupportSize" 1411 /*@ 1412 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1413 1414 Not collective 1415 1416 Input Parameters: 1417 + mesh - The DMPlex 1418 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1419 - size - The support size for point p 1420 1421 Output Parameter: 1422 1423 Note: 1424 This should be called after DMPlexSetChart(). 1425 1426 Level: beginner 1427 1428 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1429 @*/ 1430 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1431 { 1432 DM_Plex *mesh = (DM_Plex *) dm->data; 1433 PetscErrorCode ierr; 1434 1435 PetscFunctionBegin; 1436 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1437 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1438 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1439 PetscFunctionReturn(0); 1440 } 1441 1442 #undef __FUNCT__ 1443 #define __FUNCT__ "DMPlexGetSupport" 1444 /*@C 1445 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1446 1447 Not collective 1448 1449 Input Parameters: 1450 + mesh - The DMPlex 1451 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1452 1453 Output Parameter: 1454 . support - An array of points which are on the out-edges for point p 1455 1456 Level: beginner 1457 1458 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1459 @*/ 1460 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1461 { 1462 DM_Plex *mesh = (DM_Plex *) dm->data; 1463 PetscInt off; 1464 PetscErrorCode ierr; 1465 1466 PetscFunctionBegin; 1467 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1468 PetscValidPointer(support, 3); 1469 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1470 *support = &mesh->supports[off]; 1471 PetscFunctionReturn(0); 1472 } 1473 1474 #undef __FUNCT__ 1475 #define __FUNCT__ "DMPlexSetSupport" 1476 /*@ 1477 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1478 1479 Not collective 1480 1481 Input Parameters: 1482 + mesh - The DMPlex 1483 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1484 - support - An array of points which are on the in-edges for point p 1485 1486 Output Parameter: 1487 1488 Note: 1489 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1490 1491 Level: beginner 1492 1493 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1494 @*/ 1495 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1496 { 1497 DM_Plex *mesh = (DM_Plex *) dm->data; 1498 PetscInt pStart, pEnd; 1499 PetscInt dof, off, c; 1500 PetscErrorCode ierr; 1501 1502 PetscFunctionBegin; 1503 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1504 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1505 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1506 if (dof) PetscValidPointer(support, 3); 1507 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1508 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); 1509 for (c = 0; c < dof; ++c) { 1510 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); 1511 mesh->supports[off+c] = support[c]; 1512 } 1513 PetscFunctionReturn(0); 1514 } 1515 1516 #undef __FUNCT__ 1517 #define __FUNCT__ "DMPlexInsertSupport" 1518 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1519 { 1520 DM_Plex *mesh = (DM_Plex *) dm->data; 1521 PetscInt pStart, pEnd; 1522 PetscInt dof, off; 1523 PetscErrorCode ierr; 1524 1525 PetscFunctionBegin; 1526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1527 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1528 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1529 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1530 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); 1531 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); 1532 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); 1533 mesh->supports[off+supportPos] = supportPoint; 1534 PetscFunctionReturn(0); 1535 } 1536 1537 #undef __FUNCT__ 1538 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1539 /*@C 1540 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1541 1542 Not collective 1543 1544 Input Parameters: 1545 + mesh - The DMPlex 1546 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1547 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1548 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1549 1550 Output Parameters: 1551 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1552 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1553 1554 Note: 1555 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1556 1557 Level: beginner 1558 1559 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1560 @*/ 1561 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1562 { 1563 DM_Plex *mesh = (DM_Plex *) dm->data; 1564 PetscInt *closure, *fifo; 1565 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1566 PetscInt tmpSize, t; 1567 PetscInt depth = 0, maxSize; 1568 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1569 PetscErrorCode ierr; 1570 1571 PetscFunctionBegin; 1572 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1573 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1574 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1575 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1576 if (*points) { 1577 closure = *points; 1578 } else { 1579 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1580 } 1581 closure[0] = p; closure[1] = 0; 1582 /* This is only 1-level */ 1583 if (useCone) { 1584 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1585 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1586 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1587 } else { 1588 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1589 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1590 } 1591 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1592 const PetscInt cp = tmp[t]; 1593 const PetscInt co = tmpO ? tmpO[t] : 0; 1594 1595 closure[closureSize] = cp; 1596 closure[closureSize+1] = co; 1597 fifo[fifoSize] = cp; 1598 fifo[fifoSize+1] = co; 1599 } 1600 while (fifoSize - fifoStart) { 1601 const PetscInt q = fifo[fifoStart]; 1602 const PetscInt o = fifo[fifoStart+1]; 1603 const PetscInt rev = o >= 0 ? 0 : 1; 1604 const PetscInt off = rev ? -(o+1) : o; 1605 1606 if (useCone) { 1607 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1608 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1609 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1610 } else { 1611 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1612 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1613 tmpO = PETSC_NULL; 1614 } 1615 for (t = 0; t < tmpSize; ++t) { 1616 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1617 const PetscInt cp = tmp[i]; 1618 /* Must propogate orientation */ 1619 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1620 PetscInt c; 1621 1622 /* Check for duplicate */ 1623 for (c = 0; c < closureSize; c += 2) { 1624 if (closure[c] == cp) break; 1625 } 1626 if (c == closureSize) { 1627 closure[closureSize] = cp; 1628 closure[closureSize+1] = co; 1629 fifo[fifoSize] = cp; 1630 fifo[fifoSize+1] = co; 1631 closureSize += 2; 1632 fifoSize += 2; 1633 } 1634 } 1635 fifoStart += 2; 1636 } 1637 if (numPoints) *numPoints = closureSize/2; 1638 if (points) *points = closure; 1639 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1640 PetscFunctionReturn(0); 1641 } 1642 1643 #undef __FUNCT__ 1644 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1645 /*@C 1646 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1647 1648 Not collective 1649 1650 Input Parameters: 1651 + mesh - The DMPlex 1652 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1653 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1654 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1655 1656 Output Parameters: 1657 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1658 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1659 1660 Note: 1661 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1662 1663 Level: beginner 1664 1665 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1666 @*/ 1667 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1668 { 1669 PetscErrorCode ierr; 1670 1671 PetscFunctionBegin; 1672 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1673 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1674 PetscFunctionReturn(0); 1675 } 1676 1677 #undef __FUNCT__ 1678 #define __FUNCT__ "DMPlexGetFaces" 1679 /* 1680 DMPlexGetFaces - 1681 1682 Note: This will only work for cell-vertex meshes. 1683 */ 1684 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1685 { 1686 DM_Plex *mesh = (DM_Plex *) dm->data; 1687 const PetscInt *cone = PETSC_NULL; 1688 PetscInt depth = 0, dim, coneSize; 1689 PetscErrorCode ierr; 1690 1691 PetscFunctionBegin; 1692 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1693 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1694 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1695 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1696 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1697 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1698 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1699 switch (dim) { 1700 case 2: 1701 switch (coneSize) { 1702 case 3: 1703 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1704 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1705 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1706 *numFaces = 3; 1707 *faceSize = 2; 1708 *faces = mesh->facesTmp; 1709 break; 1710 case 4: 1711 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1712 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1713 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1714 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1715 *numFaces = 4; 1716 *faceSize = 2; 1717 *faces = mesh->facesTmp; 1718 break; 1719 default: 1720 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1721 } 1722 break; 1723 case 3: 1724 switch (coneSize) { 1725 case 3: 1726 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1727 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1728 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1729 *numFaces = 3; 1730 *faceSize = 2; 1731 *faces = mesh->facesTmp; 1732 break; 1733 case 4: 1734 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1735 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1736 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1737 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1738 *numFaces = 4; 1739 *faceSize = 3; 1740 *faces = mesh->facesTmp; 1741 break; 1742 default: 1743 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1744 } 1745 break; 1746 default: 1747 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1748 } 1749 PetscFunctionReturn(0); 1750 } 1751 1752 #undef __FUNCT__ 1753 #define __FUNCT__ "DMPlexGetMaxSizes" 1754 /*@ 1755 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1756 1757 Not collective 1758 1759 Input Parameter: 1760 . mesh - The DMPlex 1761 1762 Output Parameters: 1763 + maxConeSize - The maximum number of in-edges 1764 - maxSupportSize - The maximum number of out-edges 1765 1766 Level: beginner 1767 1768 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1769 @*/ 1770 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1771 { 1772 DM_Plex *mesh = (DM_Plex *) dm->data; 1773 1774 PetscFunctionBegin; 1775 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1776 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1777 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1778 PetscFunctionReturn(0); 1779 } 1780 1781 #undef __FUNCT__ 1782 #define __FUNCT__ "DMSetUp_Plex" 1783 PetscErrorCode DMSetUp_Plex(DM dm) 1784 { 1785 DM_Plex *mesh = (DM_Plex *) dm->data; 1786 PetscInt size; 1787 PetscErrorCode ierr; 1788 1789 PetscFunctionBegin; 1790 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1791 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1792 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1793 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1794 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1795 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1796 if (mesh->maxSupportSize) { 1797 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1798 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1799 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1800 } 1801 PetscFunctionReturn(0); 1802 } 1803 1804 #undef __FUNCT__ 1805 #define __FUNCT__ "DMCreateSubDM_Plex" 1806 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1807 { 1808 PetscSection section, sectionGlobal; 1809 PetscInt *subIndices; 1810 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1811 PetscErrorCode ierr; 1812 1813 PetscFunctionBegin; 1814 if (!numFields) PetscFunctionReturn(0); 1815 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1816 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1817 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1818 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1819 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1820 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); 1821 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1822 for (p = pStart; p < pEnd; ++p) { 1823 PetscInt gdof; 1824 1825 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1826 if (gdof > 0) { 1827 for (f = 0; f < numFields; ++f) { 1828 PetscInt fdof, fcdof; 1829 1830 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1831 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1832 subSize += fdof-fcdof; 1833 } 1834 } 1835 } 1836 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1837 for (p = pStart; p < pEnd; ++p) { 1838 PetscInt gdof, goff; 1839 1840 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1841 if (gdof > 0) { 1842 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1843 for (f = 0; f < numFields; ++f) { 1844 PetscInt fdof, fcdof, fc, f2, poff = 0; 1845 1846 /* Can get rid of this loop by storing field information in the global section */ 1847 for (f2 = 0; f2 < fields[f]; ++f2) { 1848 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1849 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1850 poff += fdof-fcdof; 1851 } 1852 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1853 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1854 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1855 subIndices[subOff] = goff+poff+fc; 1856 } 1857 } 1858 } 1859 } 1860 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1861 if (subdm) { 1862 PetscSection subsection; 1863 PetscBool haveNull = PETSC_FALSE; 1864 PetscInt f, nf = 0; 1865 1866 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1867 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1868 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1869 for (f = 0; f < numFields; ++f) { 1870 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1871 if ((*subdm)->nullspaceConstructors[f]) { 1872 haveNull = PETSC_TRUE; 1873 nf = f; 1874 } 1875 } 1876 if (haveNull) { 1877 MatNullSpace nullSpace; 1878 1879 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1880 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1881 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1882 } 1883 if (dm->fields) { 1884 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); 1885 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1886 for (f = 0; f < numFields; ++f) { 1887 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1888 } 1889 if (numFields == 1) { 1890 MatNullSpace space; 1891 Mat pmat; 1892 1893 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr); 1894 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1895 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr); 1896 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1897 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr); 1898 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1899 } 1900 } 1901 } 1902 PetscFunctionReturn(0); 1903 } 1904 1905 #undef __FUNCT__ 1906 #define __FUNCT__ "DMPlexSymmetrize" 1907 /*@ 1908 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1909 1910 Not collective 1911 1912 Input Parameter: 1913 . mesh - The DMPlex 1914 1915 Output Parameter: 1916 1917 Note: 1918 This should be called after all calls to DMPlexSetCone() 1919 1920 Level: beginner 1921 1922 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1923 @*/ 1924 PetscErrorCode DMPlexSymmetrize(DM dm) 1925 { 1926 DM_Plex *mesh = (DM_Plex *) dm->data; 1927 PetscInt *offsets; 1928 PetscInt supportSize; 1929 PetscInt pStart, pEnd, p; 1930 PetscErrorCode ierr; 1931 1932 PetscFunctionBegin; 1933 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1934 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1935 /* Calculate support sizes */ 1936 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1937 for (p = pStart; p < pEnd; ++p) { 1938 PetscInt dof, off, c; 1939 1940 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1941 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1942 for (c = off; c < off+dof; ++c) { 1943 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1944 } 1945 } 1946 for (p = pStart; p < pEnd; ++p) { 1947 PetscInt dof; 1948 1949 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1950 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1951 } 1952 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1953 /* Calculate supports */ 1954 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1955 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1956 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1957 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1958 for (p = pStart; p < pEnd; ++p) { 1959 PetscInt dof, off, c; 1960 1961 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1962 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1963 for (c = off; c < off+dof; ++c) { 1964 const PetscInt q = mesh->cones[c]; 1965 PetscInt offS; 1966 1967 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1968 mesh->supports[offS+offsets[q]] = p; 1969 ++offsets[q]; 1970 } 1971 } 1972 ierr = PetscFree(offsets);CHKERRQ(ierr); 1973 PetscFunctionReturn(0); 1974 } 1975 1976 #undef __FUNCT__ 1977 #define __FUNCT__ "DMPlexSetDepth_Private" 1978 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1979 { 1980 PetscInt d; 1981 PetscErrorCode ierr; 1982 1983 PetscFunctionBegin; 1984 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1985 if (d < 0) { 1986 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1987 const PetscInt *cone = PETSC_NULL; 1988 PetscInt dCone; 1989 1990 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1991 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1992 d = dCone+1; 1993 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1994 } 1995 *depth = d; 1996 PetscFunctionReturn(0); 1997 } 1998 1999 #undef __FUNCT__ 2000 #define __FUNCT__ "DMPlexStratify" 2001 /*@ 2002 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2003 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2004 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2005 the DAG. 2006 2007 Not collective 2008 2009 Input Parameter: 2010 . mesh - The DMPlex 2011 2012 Output Parameter: 2013 2014 Notes: 2015 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2016 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2017 2018 This should be called after all calls to DMPlexSymmetrize() 2019 2020 Level: beginner 2021 2022 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2023 @*/ 2024 PetscErrorCode DMPlexStratify(DM dm) 2025 { 2026 DM_Plex *mesh = (DM_Plex *) dm->data; 2027 PetscInt pStart, pEnd, p; 2028 PetscInt numRoots = 0, numLeaves = 0; 2029 PetscErrorCode ierr; 2030 2031 PetscFunctionBegin; 2032 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2033 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2034 /* Calculate depth */ 2035 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2036 /* Initialize roots and count leaves */ 2037 for (p = pStart; p < pEnd; ++p) { 2038 PetscInt coneSize, supportSize; 2039 2040 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2041 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2042 if (!coneSize && supportSize) { 2043 ++numRoots; 2044 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2045 } else if (!supportSize && coneSize) { 2046 ++numLeaves; 2047 } else if (!supportSize && !coneSize) { 2048 /* Isolated points */ 2049 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2050 } 2051 } 2052 if (numRoots + numLeaves == (pEnd - pStart)) { 2053 for (p = pStart; p < pEnd; ++p) { 2054 PetscInt coneSize, supportSize; 2055 2056 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2057 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2058 if (!supportSize && coneSize) { 2059 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2060 } 2061 } 2062 } else { 2063 /* This might be slow since lookup is not fast */ 2064 for (p = pStart; p < pEnd; ++p) { 2065 PetscInt depth; 2066 2067 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2068 } 2069 } 2070 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2071 PetscFunctionReturn(0); 2072 } 2073 2074 #undef __FUNCT__ 2075 #define __FUNCT__ "DMPlexGetJoin" 2076 /*@C 2077 DMPlexGetJoin - Get an array for the join of the set of points 2078 2079 Not Collective 2080 2081 Input Parameters: 2082 + dm - The DMPlex object 2083 . numPoints - The number of input points for the join 2084 - points - The input points 2085 2086 Output Parameters: 2087 + numCoveredPoints - The number of points in the join 2088 - coveredPoints - The points in the join 2089 2090 Level: intermediate 2091 2092 Note: Currently, this is restricted to a single level join 2093 2094 .keywords: mesh 2095 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2096 @*/ 2097 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2098 { 2099 DM_Plex *mesh = (DM_Plex *) dm->data; 2100 PetscInt *join[2]; 2101 PetscInt joinSize, i = 0; 2102 PetscInt dof, off, p, c, m; 2103 PetscErrorCode ierr; 2104 2105 PetscFunctionBegin; 2106 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2107 PetscValidPointer(points, 2); 2108 PetscValidPointer(numCoveredPoints, 3); 2109 PetscValidPointer(coveredPoints, 4); 2110 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2111 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2112 /* Copy in support of first point */ 2113 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2114 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2115 for (joinSize = 0; joinSize < dof; ++joinSize) { 2116 join[i][joinSize] = mesh->supports[off+joinSize]; 2117 } 2118 /* Check each successive support */ 2119 for (p = 1; p < numPoints; ++p) { 2120 PetscInt newJoinSize = 0; 2121 2122 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2123 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2124 for (c = 0; c < dof; ++c) { 2125 const PetscInt point = mesh->supports[off+c]; 2126 2127 for (m = 0; m < joinSize; ++m) { 2128 if (point == join[i][m]) { 2129 join[1-i][newJoinSize++] = point; 2130 break; 2131 } 2132 } 2133 } 2134 joinSize = newJoinSize; 2135 i = 1-i; 2136 } 2137 *numCoveredPoints = joinSize; 2138 *coveredPoints = join[i]; 2139 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2140 PetscFunctionReturn(0); 2141 } 2142 2143 #undef __FUNCT__ 2144 #define __FUNCT__ "DMPlexRestoreJoin" 2145 /*@C 2146 DMPlexRestoreJoin - Restore an array for the join of the set of points 2147 2148 Not Collective 2149 2150 Input Parameters: 2151 + dm - The DMPlex object 2152 . numPoints - The number of input points for the join 2153 - points - The input points 2154 2155 Output Parameters: 2156 + numCoveredPoints - The number of points in the join 2157 - coveredPoints - The points in the join 2158 2159 Level: intermediate 2160 2161 .keywords: mesh 2162 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2163 @*/ 2164 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2165 { 2166 PetscErrorCode ierr; 2167 2168 PetscFunctionBegin; 2169 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2170 PetscValidPointer(coveredPoints, 4); 2171 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2172 PetscFunctionReturn(0); 2173 } 2174 2175 #undef __FUNCT__ 2176 #define __FUNCT__ "DMPlexGetFullJoin" 2177 /*@C 2178 DMPlexGetFullJoin - Get an array for the join of the set of points 2179 2180 Not Collective 2181 2182 Input Parameters: 2183 + dm - The DMPlex object 2184 . numPoints - The number of input points for the join 2185 - points - The input points 2186 2187 Output Parameters: 2188 + numCoveredPoints - The number of points in the join 2189 - coveredPoints - The points in the join 2190 2191 Level: intermediate 2192 2193 .keywords: mesh 2194 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2195 @*/ 2196 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2197 { 2198 DM_Plex *mesh = (DM_Plex *) dm->data; 2199 PetscInt *offsets, **closures; 2200 PetscInt *join[2]; 2201 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2202 PetscInt p, d, c, m; 2203 PetscErrorCode ierr; 2204 2205 PetscFunctionBegin; 2206 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2207 PetscValidPointer(points, 2); 2208 PetscValidPointer(numCoveredPoints, 3); 2209 PetscValidPointer(coveredPoints, 4); 2210 2211 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2212 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2213 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2214 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2215 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2216 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2217 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2218 2219 for (p = 0; p < numPoints; ++p) { 2220 PetscInt closureSize; 2221 2222 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2223 offsets[p*(depth+2)+0] = 0; 2224 for (d = 0; d < depth+1; ++d) { 2225 PetscInt pStart, pEnd, i; 2226 2227 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2228 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2229 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2230 offsets[p*(depth+2)+d+1] = i; 2231 break; 2232 } 2233 } 2234 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2235 } 2236 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); 2237 } 2238 for (d = 0; d < depth+1; ++d) { 2239 PetscInt dof; 2240 2241 /* Copy in support of first point */ 2242 dof = offsets[d+1] - offsets[d]; 2243 for (joinSize = 0; joinSize < dof; ++joinSize) { 2244 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2245 } 2246 /* Check each successive cone */ 2247 for (p = 1; p < numPoints && joinSize; ++p) { 2248 PetscInt newJoinSize = 0; 2249 2250 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2251 for (c = 0; c < dof; ++c) { 2252 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2253 2254 for (m = 0; m < joinSize; ++m) { 2255 if (point == join[i][m]) { 2256 join[1-i][newJoinSize++] = point; 2257 break; 2258 } 2259 } 2260 } 2261 joinSize = newJoinSize; 2262 i = 1-i; 2263 } 2264 if (joinSize) break; 2265 } 2266 *numCoveredPoints = joinSize; 2267 *coveredPoints = join[i]; 2268 for (p = 0; p < numPoints; ++p) { 2269 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2270 } 2271 ierr = PetscFree(closures);CHKERRQ(ierr); 2272 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2273 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2274 PetscFunctionReturn(0); 2275 } 2276 2277 #undef __FUNCT__ 2278 #define __FUNCT__ "DMPlexGetMeet" 2279 /*@C 2280 DMPlexGetMeet - Get an array for the meet of the set of points 2281 2282 Not Collective 2283 2284 Input Parameters: 2285 + dm - The DMPlex object 2286 . numPoints - The number of input points for the meet 2287 - points - The input points 2288 2289 Output Parameters: 2290 + numCoveredPoints - The number of points in the meet 2291 - coveredPoints - The points in the meet 2292 2293 Level: intermediate 2294 2295 Note: Currently, this is restricted to a single level meet 2296 2297 .keywords: mesh 2298 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2299 @*/ 2300 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2301 { 2302 DM_Plex *mesh = (DM_Plex *) dm->data; 2303 PetscInt *meet[2]; 2304 PetscInt meetSize, i = 0; 2305 PetscInt dof, off, p, c, m; 2306 PetscErrorCode ierr; 2307 2308 PetscFunctionBegin; 2309 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2310 PetscValidPointer(points, 2); 2311 PetscValidPointer(numCoveringPoints, 3); 2312 PetscValidPointer(coveringPoints, 4); 2313 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2314 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2315 /* Copy in cone of first point */ 2316 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2317 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2318 for (meetSize = 0; meetSize < dof; ++meetSize) { 2319 meet[i][meetSize] = mesh->cones[off+meetSize]; 2320 } 2321 /* Check each successive cone */ 2322 for (p = 1; p < numPoints; ++p) { 2323 PetscInt newMeetSize = 0; 2324 2325 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2326 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2327 for (c = 0; c < dof; ++c) { 2328 const PetscInt point = mesh->cones[off+c]; 2329 2330 for (m = 0; m < meetSize; ++m) { 2331 if (point == meet[i][m]) { 2332 meet[1-i][newMeetSize++] = point; 2333 break; 2334 } 2335 } 2336 } 2337 meetSize = newMeetSize; 2338 i = 1-i; 2339 } 2340 *numCoveringPoints = meetSize; 2341 *coveringPoints = meet[i]; 2342 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2343 PetscFunctionReturn(0); 2344 } 2345 2346 #undef __FUNCT__ 2347 #define __FUNCT__ "DMPlexRestoreMeet" 2348 /*@C 2349 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2350 2351 Not Collective 2352 2353 Input Parameters: 2354 + dm - The DMPlex object 2355 . numPoints - The number of input points for the meet 2356 - points - The input points 2357 2358 Output Parameters: 2359 + numCoveredPoints - The number of points in the meet 2360 - coveredPoints - The points in the meet 2361 2362 Level: intermediate 2363 2364 .keywords: mesh 2365 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2366 @*/ 2367 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2368 { 2369 PetscErrorCode ierr; 2370 2371 PetscFunctionBegin; 2372 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2373 PetscValidPointer(coveredPoints, 4); 2374 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2375 PetscFunctionReturn(0); 2376 } 2377 2378 #undef __FUNCT__ 2379 #define __FUNCT__ "DMPlexGetFullMeet" 2380 /*@C 2381 DMPlexGetFullMeet - Get an array for the meet of the set of points 2382 2383 Not Collective 2384 2385 Input Parameters: 2386 + dm - The DMPlex object 2387 . numPoints - The number of input points for the meet 2388 - points - The input points 2389 2390 Output Parameters: 2391 + numCoveredPoints - The number of points in the meet 2392 - coveredPoints - The points in the meet 2393 2394 Level: intermediate 2395 2396 .keywords: mesh 2397 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2398 @*/ 2399 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2400 { 2401 DM_Plex *mesh = (DM_Plex *) dm->data; 2402 PetscInt *offsets, **closures; 2403 PetscInt *meet[2]; 2404 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2405 PetscInt p, h, c, m; 2406 PetscErrorCode ierr; 2407 2408 PetscFunctionBegin; 2409 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2410 PetscValidPointer(points, 2); 2411 PetscValidPointer(numCoveredPoints, 3); 2412 PetscValidPointer(coveredPoints, 4); 2413 2414 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2415 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2416 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2417 maxSize = PetscPowInt(mesh->maxConeSize,height); 2418 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2419 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2420 2421 for (p = 0; p < numPoints; ++p) { 2422 PetscInt closureSize; 2423 2424 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2425 offsets[p*(height+2)+0] = 0; 2426 for (h = 0; h < height+1; ++h) { 2427 PetscInt pStart, pEnd, i; 2428 2429 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2430 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2431 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2432 offsets[p*(height+2)+h+1] = i; 2433 break; 2434 } 2435 } 2436 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2437 } 2438 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); 2439 } 2440 for (h = 0; h < height+1; ++h) { 2441 PetscInt dof; 2442 2443 /* Copy in cone of first point */ 2444 dof = offsets[h+1] - offsets[h]; 2445 for (meetSize = 0; meetSize < dof; ++meetSize) { 2446 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2447 } 2448 /* Check each successive cone */ 2449 for (p = 1; p < numPoints && meetSize; ++p) { 2450 PetscInt newMeetSize = 0; 2451 2452 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2453 for (c = 0; c < dof; ++c) { 2454 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2455 2456 for (m = 0; m < meetSize; ++m) { 2457 if (point == meet[i][m]) { 2458 meet[1-i][newMeetSize++] = point; 2459 break; 2460 } 2461 } 2462 } 2463 meetSize = newMeetSize; 2464 i = 1-i; 2465 } 2466 if (meetSize) break; 2467 } 2468 *numCoveredPoints = meetSize; 2469 *coveredPoints = meet[i]; 2470 for (p = 0; p < numPoints; ++p) { 2471 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2472 } 2473 ierr = PetscFree(closures);CHKERRQ(ierr); 2474 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2475 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2476 PetscFunctionReturn(0); 2477 } 2478 2479 #undef __FUNCT__ 2480 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2481 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2482 { 2483 MPI_Comm comm = ((PetscObject) dm)->comm; 2484 PetscInt cellDim; 2485 PetscErrorCode ierr; 2486 2487 PetscFunctionBegin; 2488 PetscValidPointer(numFaceVertices,3); 2489 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2490 switch (cellDim) { 2491 case 0: 2492 *numFaceVertices = 0; 2493 break; 2494 case 1: 2495 *numFaceVertices = 1; 2496 break; 2497 case 2: 2498 switch (numCorners) { 2499 case 3: /* triangle */ 2500 *numFaceVertices = 2; /* Edge has 2 vertices */ 2501 break; 2502 case 4: /* quadrilateral */ 2503 *numFaceVertices = 2; /* Edge has 2 vertices */ 2504 break; 2505 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2506 *numFaceVertices = 3; /* Edge has 3 vertices */ 2507 break; 2508 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2509 *numFaceVertices = 3; /* Edge has 3 vertices */ 2510 break; 2511 default: 2512 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2513 } 2514 break; 2515 case 3: 2516 switch (numCorners) { 2517 case 4: /* tetradehdron */ 2518 *numFaceVertices = 3; /* Face has 3 vertices */ 2519 break; 2520 case 6: /* tet cohesive cells */ 2521 *numFaceVertices = 4; /* Face has 4 vertices */ 2522 break; 2523 case 8: /* hexahedron */ 2524 *numFaceVertices = 4; /* Face has 4 vertices */ 2525 break; 2526 case 9: /* tet cohesive Lagrange cells */ 2527 *numFaceVertices = 6; /* Face has 6 vertices */ 2528 break; 2529 case 10: /* quadratic tetrahedron */ 2530 *numFaceVertices = 6; /* Face has 6 vertices */ 2531 break; 2532 case 12: /* hex cohesive Lagrange cells */ 2533 *numFaceVertices = 6; /* Face has 6 vertices */ 2534 break; 2535 case 18: /* quadratic tet cohesive Lagrange cells */ 2536 *numFaceVertices = 6; /* Face has 6 vertices */ 2537 break; 2538 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2539 *numFaceVertices = 9; /* Face has 9 vertices */ 2540 break; 2541 default: 2542 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2543 } 2544 break; 2545 default: 2546 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2547 } 2548 PetscFunctionReturn(0); 2549 } 2550 2551 #undef __FUNCT__ 2552 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2553 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2554 { 2555 const PetscInt maxFaceCases = 30; 2556 PetscInt numFaceCases = 0; 2557 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2558 PetscInt *off, *adj; 2559 PetscInt *neighborCells, *tmpClosure; 2560 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2561 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2562 PetscErrorCode ierr; 2563 2564 PetscFunctionBegin; 2565 /* For parallel partitioning, I think you have to communicate supports */ 2566 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2567 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2568 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2569 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2570 if (cEnd - cStart == 0) { 2571 if (numVertices) *numVertices = 0; 2572 if (offsets) *offsets = PETSC_NULL; 2573 if (adjacency) *adjacency = PETSC_NULL; 2574 PetscFunctionReturn(0); 2575 } 2576 numCells = cEnd - cStart; 2577 /* Setup face recognition */ 2578 if (depth == 1) { 2579 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 */ 2580 2581 for (c = cStart; c < cEnd; ++c) { 2582 PetscInt corners; 2583 2584 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2585 if (!cornersSeen[corners]) { 2586 PetscInt nFV; 2587 2588 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2589 cornersSeen[corners] = 1; 2590 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2591 numFaceVertices[numFaceCases++] = nFV; 2592 } 2593 } 2594 } 2595 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2596 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2597 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2598 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2599 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2600 /* Count neighboring cells */ 2601 for (cell = cStart; cell < cEnd; ++cell) { 2602 PetscInt numNeighbors = maxNeighbors, n; 2603 2604 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2605 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2606 for (n = 0; n < numNeighbors; ++n) { 2607 PetscInt cellPair[2]; 2608 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2609 PetscInt meetSize = 0; 2610 const PetscInt *meet = PETSC_NULL; 2611 2612 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2613 if (cellPair[0] == cellPair[1]) continue; 2614 if (!found) { 2615 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2616 if (meetSize) { 2617 PetscInt f; 2618 2619 for (f = 0; f < numFaceCases; ++f) { 2620 if (numFaceVertices[f] == meetSize) { 2621 found = PETSC_TRUE; 2622 break; 2623 } 2624 } 2625 } 2626 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2627 } 2628 if (found) { 2629 ++off[cell-cStart+1]; 2630 } 2631 } 2632 } 2633 /* Prefix sum */ 2634 for (cell = 1; cell <= numCells; ++cell) { 2635 off[cell] += off[cell-1]; 2636 } 2637 if (adjacency) { 2638 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2639 /* Get neighboring cells */ 2640 for (cell = cStart; cell < cEnd; ++cell) { 2641 PetscInt numNeighbors = maxNeighbors, n; 2642 PetscInt cellOffset = 0; 2643 2644 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2645 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2646 for (n = 0; n < numNeighbors; ++n) { 2647 PetscInt cellPair[2]; 2648 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2649 PetscInt meetSize = 0; 2650 const PetscInt *meet = PETSC_NULL; 2651 2652 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2653 if (cellPair[0] == cellPair[1]) continue; 2654 if (!found) { 2655 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2656 if (meetSize) { 2657 PetscInt f; 2658 2659 for (f = 0; f < numFaceCases; ++f) { 2660 if (numFaceVertices[f] == meetSize) { 2661 found = PETSC_TRUE; 2662 break; 2663 } 2664 } 2665 } 2666 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2667 } 2668 if (found) { 2669 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2670 ++cellOffset; 2671 } 2672 } 2673 } 2674 } 2675 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2676 if (numVertices) *numVertices = numCells; 2677 if (offsets) *offsets = off; 2678 if (adjacency) *adjacency = adj; 2679 PetscFunctionReturn(0); 2680 } 2681 2682 #if defined(PETSC_HAVE_CHACO) 2683 #if defined(PETSC_HAVE_UNISTD_H) 2684 #include <unistd.h> 2685 #endif 2686 /* Chaco does not have an include file */ 2687 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2688 float *ewgts, float *x, float *y, float *z, char *outassignname, 2689 char *outfilename, short *assignment, int architecture, int ndims_tot, 2690 int mesh_dims[3], double *goal, int global_method, int local_method, 2691 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2692 2693 extern int FREE_GRAPH; 2694 2695 #undef __FUNCT__ 2696 #define __FUNCT__ "DMPlexPartition_Chaco" 2697 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2698 { 2699 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2700 MPI_Comm comm = ((PetscObject) dm)->comm; 2701 int nvtxs = numVertices; /* number of vertices in full graph */ 2702 int *vwgts = NULL; /* weights for all vertices */ 2703 float *ewgts = NULL; /* weights for all edges */ 2704 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2705 char *outassignname = NULL; /* name of assignment output file */ 2706 char *outfilename = NULL; /* output file name */ 2707 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2708 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2709 int mesh_dims[3]; /* dimensions of mesh of processors */ 2710 double *goal = NULL; /* desired set sizes for each set */ 2711 int global_method = 1; /* global partitioning algorithm */ 2712 int local_method = 1; /* local partitioning algorithm */ 2713 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2714 int vmax = 200; /* how many vertices to coarsen down to? */ 2715 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2716 double eigtol = 0.001; /* tolerance on eigenvectors */ 2717 long seed = 123636512; /* for random graph mutations */ 2718 short int *assignment; /* Output partition */ 2719 int fd_stdout, fd_pipe[2]; 2720 PetscInt *points; 2721 PetscMPIInt commSize; 2722 int i, v, p; 2723 PetscErrorCode ierr; 2724 2725 PetscFunctionBegin; 2726 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2727 if (!numVertices) { 2728 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2729 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2730 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2731 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2732 PetscFunctionReturn(0); 2733 } 2734 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2735 for (i = 0; i < start[numVertices]; ++i) { 2736 ++adjacency[i]; 2737 } 2738 if (global_method == INERTIAL_METHOD) { 2739 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2740 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2741 } 2742 mesh_dims[0] = commSize; 2743 mesh_dims[1] = 1; 2744 mesh_dims[2] = 1; 2745 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2746 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2747 /* TODO: check error codes for UNIX calls */ 2748 #if defined(PETSC_HAVE_UNISTD_H) 2749 { 2750 int piperet; 2751 piperet = pipe(fd_pipe); 2752 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2753 fd_stdout = dup(1); 2754 close(1); 2755 dup2(fd_pipe[1], 1); 2756 } 2757 #endif 2758 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2759 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2760 vmax, ndims, eigtol, seed); 2761 #if defined(PETSC_HAVE_UNISTD_H) 2762 { 2763 char msgLog[10000]; 2764 int count; 2765 2766 fflush(stdout); 2767 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2768 if (count < 0) count = 0; 2769 msgLog[count] = 0; 2770 close(1); 2771 dup2(fd_stdout, 1); 2772 close(fd_stdout); 2773 close(fd_pipe[0]); 2774 close(fd_pipe[1]); 2775 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2776 } 2777 #endif 2778 /* Convert to PetscSection+IS */ 2779 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2780 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2781 for (v = 0; v < nvtxs; ++v) { 2782 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2783 } 2784 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2785 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2786 for (p = 0, i = 0; p < commSize; ++p) { 2787 for (v = 0; v < nvtxs; ++v) { 2788 if (assignment[v] == p) points[i++] = v; 2789 } 2790 } 2791 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2792 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2793 if (global_method == INERTIAL_METHOD) { 2794 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2795 } 2796 ierr = PetscFree(assignment);CHKERRQ(ierr); 2797 for (i = 0; i < start[numVertices]; ++i) { 2798 --adjacency[i]; 2799 } 2800 PetscFunctionReturn(0); 2801 } 2802 #endif 2803 2804 #if defined(PETSC_HAVE_PARMETIS) 2805 #undef __FUNCT__ 2806 #define __FUNCT__ "DMPlexPartition_ParMetis" 2807 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2808 { 2809 PetscFunctionBegin; 2810 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2811 PetscFunctionReturn(0); 2812 } 2813 #endif 2814 2815 #undef __FUNCT__ 2816 #define __FUNCT__ "DMPlexEnlargePartition" 2817 /* Expand the partition by BFS on the adjacency graph */ 2818 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2819 { 2820 PetscHashI h; 2821 const PetscInt *points; 2822 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2823 PetscInt pStart, pEnd, part, q; 2824 PetscErrorCode ierr; 2825 2826 PetscFunctionBegin; 2827 PetscHashICreate(h); 2828 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2829 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2830 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2831 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2832 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2833 for (part = pStart; part < pEnd; ++part) { 2834 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2835 2836 PetscHashIClear(h); 2837 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2838 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2839 /* Add all existing points to h */ 2840 for (p = 0; p < numPoints; ++p) { 2841 const PetscInt point = points[off+p]; 2842 PetscHashIAdd(h, point, 1); 2843 } 2844 PetscHashISize(h, nP); 2845 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2846 /* Add all points in next BFS level */ 2847 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2848 for (p = 0; p < numPoints; ++p) { 2849 const PetscInt point = points[off+p]; 2850 PetscInt s = start[point], e = start[point+1], a; 2851 2852 for (a = s; a < e; ++a) { 2853 PetscHashIAdd(h, adjacency[a], 1); 2854 } 2855 } 2856 PetscHashISize(h, numNewPoints); 2857 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2858 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2859 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2860 totPoints += numNewPoints; 2861 } 2862 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2863 PetscHashIDestroy(h); 2864 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2865 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2866 for (part = pStart, q = 0; part < pEnd; ++part) { 2867 PetscInt numPoints, p; 2868 2869 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2870 for (p = 0; p < numPoints; ++p, ++q) { 2871 newPoints[q] = tmpPoints[part][p]; 2872 } 2873 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2874 } 2875 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2876 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2877 PetscFunctionReturn(0); 2878 } 2879 2880 #undef __FUNCT__ 2881 #define __FUNCT__ "DMPlexCreatePartition" 2882 /* 2883 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2884 2885 Collective on DM 2886 2887 Input Parameters: 2888 + dm - The DM 2889 . height - The height for points in the partition 2890 - enlarge - Expand each partition with neighbors 2891 2892 Output Parameters: 2893 + partSection - The PetscSection giving the division of points by partition 2894 . partition - The list of points by partition 2895 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2896 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2897 2898 Level: developer 2899 2900 .seealso DMPlexDistribute() 2901 */ 2902 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2903 { 2904 PetscMPIInt size; 2905 PetscErrorCode ierr; 2906 2907 PetscFunctionBegin; 2908 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2909 *origPartSection = PETSC_NULL; 2910 *origPartition = PETSC_NULL; 2911 if (size == 1) { 2912 PetscInt *points; 2913 PetscInt cStart, cEnd, c; 2914 2915 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2916 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2917 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2918 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2919 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2920 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2921 for (c = cStart; c < cEnd; ++c) { 2922 points[c] = c; 2923 } 2924 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2925 PetscFunctionReturn(0); 2926 } 2927 if (height == 0) { 2928 PetscInt numVertices; 2929 PetscInt *start = PETSC_NULL; 2930 PetscInt *adjacency = PETSC_NULL; 2931 2932 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2933 if (1) { 2934 #if defined(PETSC_HAVE_CHACO) 2935 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2936 #endif 2937 } else { 2938 #if defined(PETSC_HAVE_PARMETIS) 2939 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2940 #endif 2941 } 2942 if (enlarge) { 2943 *origPartSection = *partSection; 2944 *origPartition = *partition; 2945 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2946 } 2947 ierr = PetscFree(start);CHKERRQ(ierr); 2948 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2949 # if 0 2950 } else if (height == 1) { 2951 /* Build the dual graph for faces and partition the hypergraph */ 2952 PetscInt numEdges; 2953 2954 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2955 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2956 destroyCSR(numEdges, start, adjacency); 2957 #endif 2958 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2959 PetscFunctionReturn(0); 2960 } 2961 2962 #undef __FUNCT__ 2963 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2964 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2965 { 2966 /* const PetscInt height = 0; */ 2967 const PetscInt *partArray; 2968 PetscInt *allPoints, *partPoints = PETSC_NULL; 2969 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2970 PetscErrorCode ierr; 2971 2972 PetscFunctionBegin; 2973 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2974 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2975 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2976 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2977 for (rank = rStart; rank < rEnd; ++rank) { 2978 PetscInt partSize = 0; 2979 PetscInt numPoints, offset, p; 2980 2981 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2982 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2983 for (p = 0; p < numPoints; ++p) { 2984 PetscInt point = partArray[offset+p], closureSize, c; 2985 PetscInt *closure = PETSC_NULL; 2986 2987 /* TODO Include support for height > 0 case */ 2988 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2989 /* Merge into existing points */ 2990 if (partSize+closureSize > maxPartSize) { 2991 PetscInt *tmpPoints; 2992 2993 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2994 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2995 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2996 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2997 partPoints = tmpPoints; 2998 } 2999 for (c = 0; c < closureSize; ++c) { 3000 partPoints[partSize+c] = closure[c*2]; 3001 } 3002 partSize += closureSize; 3003 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3004 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3005 } 3006 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3007 } 3008 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3009 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3010 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3011 3012 for (rank = rStart; rank < rEnd; ++rank) { 3013 PetscInt partSize = 0, newOffset; 3014 PetscInt numPoints, offset, p; 3015 3016 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3017 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3018 for (p = 0; p < numPoints; ++p) { 3019 PetscInt point = partArray[offset+p], closureSize, c; 3020 PetscInt *closure = PETSC_NULL; 3021 3022 /* TODO Include support for height > 0 case */ 3023 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3024 /* Merge into existing points */ 3025 for (c = 0; c < closureSize; ++c) { 3026 partPoints[partSize+c] = closure[c*2]; 3027 } 3028 partSize += closureSize; 3029 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3030 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3031 } 3032 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3033 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3034 } 3035 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3036 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3037 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3038 PetscFunctionReturn(0); 3039 } 3040 3041 #undef __FUNCT__ 3042 #define __FUNCT__ "DMPlexDistributeField" 3043 /* 3044 Input Parameters: 3045 . originalSection 3046 , originalVec 3047 3048 Output Parameters: 3049 . newSection 3050 . newVec 3051 */ 3052 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3053 { 3054 PetscSF fieldSF; 3055 PetscInt *remoteOffsets, fieldSize; 3056 PetscScalar *originalValues, *newValues; 3057 PetscErrorCode ierr; 3058 3059 PetscFunctionBegin; 3060 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3061 3062 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3063 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3064 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3065 3066 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3067 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3068 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3069 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3070 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3071 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3072 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3073 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3074 PetscFunctionReturn(0); 3075 } 3076 3077 #undef __FUNCT__ 3078 #define __FUNCT__ "DMPlexDistribute" 3079 /*@C 3080 DMPlexDistribute - Distributes the mesh and any associated sections. 3081 3082 Not Collective 3083 3084 Input Parameter: 3085 + dm - The original DMPlex object 3086 . partitioner - The partitioning package, or NULL for the default 3087 - overlap - The overlap of partitions, 0 is the default 3088 3089 Output Parameter: 3090 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3091 3092 Note: If the mesh was not distributed, the return value is PETSC_NULL 3093 3094 Level: intermediate 3095 3096 .keywords: mesh, elements 3097 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3098 @*/ 3099 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3100 { 3101 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3102 MPI_Comm comm = ((PetscObject) dm)->comm; 3103 const PetscInt height = 0; 3104 PetscInt dim, numRemoteRanks; 3105 IS origCellPart, cellPart, part; 3106 PetscSection origCellPartSection, cellPartSection, partSection; 3107 PetscSFNode *remoteRanks; 3108 PetscSF partSF, pointSF, coneSF; 3109 ISLocalToGlobalMapping renumbering; 3110 PetscSection originalConeSection, newConeSection; 3111 PetscInt *remoteOffsets; 3112 PetscInt *cones, *newCones, newConesSize; 3113 PetscBool flg; 3114 PetscMPIInt rank, numProcs, p; 3115 PetscErrorCode ierr; 3116 3117 PetscFunctionBegin; 3118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3119 PetscValidPointer(dmParallel,4); 3120 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3121 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3122 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3123 *dmParallel = PETSC_NULL; 3124 if (numProcs == 1) PetscFunctionReturn(0); 3125 3126 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3127 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3128 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3129 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3130 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3131 if (!rank) { 3132 numRemoteRanks = numProcs; 3133 } else { 3134 numRemoteRanks = 0; 3135 } 3136 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3137 for (p = 0; p < numRemoteRanks; ++p) { 3138 remoteRanks[p].rank = p; 3139 remoteRanks[p].index = 0; 3140 } 3141 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3142 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3143 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3144 if (flg) { 3145 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3146 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3147 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3148 if (origCellPart) { 3149 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3150 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3151 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3152 } 3153 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3154 } 3155 /* Close the partition over the mesh */ 3156 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3157 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3158 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3159 /* Create new mesh */ 3160 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3161 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3162 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3163 pmesh = (DM_Plex *) (*dmParallel)->data; 3164 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3165 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3166 if (flg) { 3167 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3168 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3169 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3170 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3171 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3172 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3173 } 3174 /* Distribute cone section */ 3175 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3176 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3177 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3178 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3179 { 3180 PetscInt pStart, pEnd, p; 3181 3182 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3183 for (p = pStart; p < pEnd; ++p) { 3184 PetscInt coneSize; 3185 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3186 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3187 } 3188 } 3189 /* Communicate and renumber cones */ 3190 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3191 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3192 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3193 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3194 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3195 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3196 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3197 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3198 if (flg) { 3199 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3200 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3201 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3202 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3203 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3204 } 3205 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3206 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3207 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3208 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3209 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3210 /* Create supports and stratify sieve */ 3211 { 3212 PetscInt pStart, pEnd; 3213 3214 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3215 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3216 } 3217 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3218 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3219 /* Distribute Coordinates */ 3220 { 3221 PetscSection originalCoordSection, newCoordSection; 3222 Vec originalCoordinates, newCoordinates; 3223 const char *name; 3224 3225 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3226 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3227 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3228 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3229 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3230 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3231 3232 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3233 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3234 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3235 } 3236 /* Distribute labels */ 3237 { 3238 DMLabel next = mesh->labels, newNext = pmesh->labels; 3239 PetscInt numLabels = 0, l; 3240 3241 /* Bcast number of labels */ 3242 while (next) {++numLabels; next = next->next;} 3243 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3244 next = mesh->labels; 3245 for (l = 0; l < numLabels; ++l) { 3246 DMLabel newLabel; 3247 const PetscInt *partArray; 3248 char *name; 3249 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3250 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3251 PetscInt nameSize, s, p; 3252 PetscBool isdepth; 3253 size_t len = 0; 3254 3255 /* Bcast name (could filter for no points) */ 3256 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3257 nameSize = len; 3258 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3259 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3260 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3261 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3262 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3263 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3264 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3265 newLabel->name = name; 3266 /* Bcast numStrata (could filter for no points in stratum) */ 3267 if (!rank) {newLabel->numStrata = next->numStrata;} 3268 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3269 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3270 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3271 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3272 /* Bcast stratumValues (could filter for no points in stratum) */ 3273 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3274 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3275 /* Find size on each process and Scatter */ 3276 if (!rank) { 3277 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3278 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3279 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3280 for (s = 0; s < next->numStrata; ++s) { 3281 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3282 const PetscInt point = next->points[p]; 3283 PetscInt proc; 3284 3285 for (proc = 0; proc < numProcs; ++proc) { 3286 PetscInt dof, off, pPart; 3287 3288 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3289 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3290 for (pPart = off; pPart < off+dof; ++pPart) { 3291 if (partArray[pPart] == point) { 3292 ++stratumSizes[proc*next->numStrata+s]; 3293 break; 3294 } 3295 } 3296 } 3297 } 3298 } 3299 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3300 } 3301 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3302 /* Calculate stratumOffsets */ 3303 newLabel->stratumOffsets[0] = 0; 3304 for (s = 0; s < newLabel->numStrata; ++s) { 3305 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3306 } 3307 /* Pack points and Scatter */ 3308 if (!rank) { 3309 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3310 displs[0] = 0; 3311 for (p = 0; p < numProcs; ++p) { 3312 sendcnts[p] = 0; 3313 for (s = 0; s < next->numStrata; ++s) { 3314 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3315 } 3316 offsets[p] = displs[p]; 3317 displs[p+1] = displs[p] + sendcnts[p]; 3318 } 3319 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3320 for (s = 0; s < next->numStrata; ++s) { 3321 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3322 const PetscInt point = next->points[p]; 3323 PetscInt proc; 3324 3325 for (proc = 0; proc < numProcs; ++proc) { 3326 PetscInt dof, off, pPart; 3327 3328 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3329 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3330 for (pPart = off; pPart < off+dof; ++pPart) { 3331 if (partArray[pPart] == point) { 3332 points[offsets[proc]++] = point; 3333 break; 3334 } 3335 } 3336 } 3337 } 3338 } 3339 } 3340 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3341 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3342 ierr = PetscFree(points);CHKERRQ(ierr); 3343 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3344 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3345 /* Renumber points */ 3346 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3347 /* Sort points */ 3348 for (s = 0; s < newLabel->numStrata; ++s) { 3349 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3350 } 3351 /* Insert into list */ 3352 if (newNext) { 3353 newNext->next = newLabel; 3354 } else { 3355 pmesh->labels = newLabel; 3356 } 3357 newNext = newLabel; 3358 if (!rank) {next = next->next;} 3359 } 3360 } 3361 /* Cleanup Partition */ 3362 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3363 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3364 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3365 ierr = ISDestroy(&part);CHKERRQ(ierr); 3366 /* Create point SF for parallel mesh */ 3367 { 3368 const PetscInt *leaves; 3369 PetscSFNode *remotePoints, *rowners, *lowners; 3370 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3371 PetscInt pStart, pEnd; 3372 3373 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3374 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3375 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3376 for (p=0; p<numRoots; p++) { 3377 rowners[p].rank = -1; 3378 rowners[p].index = -1; 3379 } 3380 if (origCellPart) { 3381 /* Make sure cells in the original partition are not assigned to other procs */ 3382 const PetscInt *origCells; 3383 3384 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3385 for (p = 0; p < numProcs; ++p) { 3386 PetscInt dof, off, d; 3387 3388 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3389 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3390 for (d = off; d < off+dof; ++d) { 3391 rowners[origCells[d]].rank = p; 3392 } 3393 } 3394 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3395 } 3396 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3397 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3398 3399 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3400 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3401 for (p = 0; p < numLeaves; ++p) { 3402 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3403 lowners[p].rank = rank; 3404 lowners[p].index = leaves ? leaves[p] : p; 3405 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3406 lowners[p].rank = -2; 3407 lowners[p].index = -2; 3408 } 3409 } 3410 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3411 rowners[p].rank = -3; 3412 rowners[p].index = -3; 3413 } 3414 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3415 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3416 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3417 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3418 for (p = 0; p < numLeaves; ++p) { 3419 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3420 if (lowners[p].rank != rank) ++numGhostPoints; 3421 } 3422 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3423 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3424 for (p = 0, gp = 0; p < numLeaves; ++p) { 3425 if (lowners[p].rank != rank) { 3426 ghostPoints[gp] = leaves ? leaves[p] : p; 3427 remotePoints[gp].rank = lowners[p].rank; 3428 remotePoints[gp].index = lowners[p].index; 3429 ++gp; 3430 } 3431 } 3432 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3433 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3434 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3435 } 3436 /* Cleanup */ 3437 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3438 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3439 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3440 PetscFunctionReturn(0); 3441 } 3442 3443 #undef __FUNCT__ 3444 #define __FUNCT__ "DMPlexRenumber_Private" 3445 /* 3446 Reasons to renumber: 3447 3448 1) Permute points, e.g. bandwidth reduction (Renumber) 3449 3450 a) Must not mix strata 3451 3452 2) Shift numbers for point insertion (Shift) 3453 3454 a) Want operation brken into parts so that insertion can be interleaved 3455 3456 renumbering - An IS which provides the new numbering 3457 */ 3458 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3459 { 3460 PetscFunctionBegin; 3461 PetscFunctionReturn(0); 3462 } 3463 3464 #undef __FUNCT__ 3465 #define __FUNCT__ "DMPlexShiftPoint_Private" 3466 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3467 { 3468 if (depth < 0) return p; 3469 /* Cells */ if (p < depthEnd[depth]) return p; 3470 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3471 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3472 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3473 } 3474 3475 #undef __FUNCT__ 3476 #define __FUNCT__ "DMPlexShiftSizes_Private" 3477 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3478 { 3479 PetscInt *depthEnd; 3480 PetscInt depth = 0, d, pStart, pEnd, p; 3481 PetscErrorCode ierr; 3482 3483 PetscFunctionBegin; 3484 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3485 if (depth < 0) PetscFunctionReturn(0); 3486 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3487 /* Step 1: Expand chart */ 3488 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3489 for (d = 0; d <= depth; ++d) { 3490 pEnd += depthShift[d]; 3491 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3492 } 3493 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3494 /* Step 2: Set cone and support sizes */ 3495 for (d = 0; d <= depth; ++d) { 3496 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3497 for (p = pStart; p < pEnd; ++p) { 3498 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3499 PetscInt size; 3500 3501 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3502 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3503 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3504 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3505 } 3506 } 3507 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3508 PetscFunctionReturn(0); 3509 } 3510 3511 #undef __FUNCT__ 3512 #define __FUNCT__ "DMPlexShiftPoints_Private" 3513 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3514 { 3515 PetscInt *depthEnd, *newpoints; 3516 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3517 PetscErrorCode ierr; 3518 3519 PetscFunctionBegin; 3520 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3521 if (depth < 0) PetscFunctionReturn(0); 3522 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3523 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3524 for (d = 0; d <= depth; ++d) { 3525 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3526 } 3527 /* Step 5: Set cones and supports */ 3528 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3529 for (p = pStart; p < pEnd; ++p) { 3530 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3531 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3532 3533 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3534 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3535 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3536 for (i = 0; i < size; ++i) { 3537 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3538 } 3539 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3540 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3541 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3542 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3543 for (i = 0; i < size; ++i) { 3544 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3545 } 3546 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3547 } 3548 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3549 PetscFunctionReturn(0); 3550 } 3551 3552 #undef __FUNCT__ 3553 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3554 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3555 { 3556 PetscSection coordSection, newCoordSection; 3557 Vec coordinates, newCoordinates; 3558 PetscScalar *coords, *newCoords; 3559 PetscInt *depthEnd, coordSize; 3560 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3561 PetscErrorCode ierr; 3562 3563 PetscFunctionBegin; 3564 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3565 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3566 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3567 for (d = 0; d <= depth; ++d) { 3568 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3569 } 3570 /* Step 8: Convert coordinates */ 3571 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3572 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3573 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3574 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3575 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3576 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3577 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3578 for (v = vStartNew; v < vEndNew; ++v) { 3579 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3580 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3581 } 3582 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3583 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3584 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3585 ierr = VecCreate(((PetscObject) dm)->comm, &newCoordinates);CHKERRQ(ierr); 3586 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3587 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3588 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3589 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3590 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3591 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3592 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3593 for (v = vStart; v < vEnd; ++v) { 3594 PetscInt dof, off, noff, d; 3595 3596 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3597 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3598 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3599 for (d = 0; d < dof; ++d) { 3600 newCoords[noff+d] = coords[off+d]; 3601 } 3602 } 3603 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3604 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3605 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3606 PetscFunctionReturn(0); 3607 } 3608 3609 #undef __FUNCT__ 3610 #define __FUNCT__ "DMPlexShiftSF_Private" 3611 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3612 { 3613 PetscInt *depthEnd; 3614 PetscInt depth = 0, d; 3615 PetscSF sfPoint, sfPointNew; 3616 const PetscSFNode *remotePoints; 3617 PetscSFNode *gremotePoints; 3618 const PetscInt *localPoints; 3619 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3620 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3621 PetscMPIInt numProcs; 3622 PetscErrorCode ierr; 3623 3624 PetscFunctionBegin; 3625 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3626 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3627 for (d = 0; d <= depth; ++d) { 3628 totShift += depthShift[d]; 3629 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3630 } 3631 /* Step 9: Convert pointSF */ 3632 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3633 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3634 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3635 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3636 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3637 if (numRoots >= 0) { 3638 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3639 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3640 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3641 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3642 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3643 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3644 for (l = 0; l < numLeaves; ++l) { 3645 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3646 gremotePoints[l].rank = remotePoints[l].rank; 3647 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3648 } 3649 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3650 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3651 } 3652 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3653 PetscFunctionReturn(0); 3654 } 3655 3656 #undef __FUNCT__ 3657 #define __FUNCT__ "DMPlexShiftLabels_Private" 3658 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3659 { 3660 PetscSF sfPoint; 3661 DMLabel vtkLabel, ghostLabel; 3662 PetscInt *depthEnd; 3663 const PetscSFNode *leafRemote; 3664 const PetscInt *leafLocal; 3665 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3666 PetscMPIInt rank; 3667 PetscErrorCode ierr; 3668 3669 PetscFunctionBegin; 3670 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3671 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3672 for (d = 0; d <= depth; ++d) { 3673 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3674 } 3675 /* Step 10: Convert labels */ 3676 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3677 for (l = 0; l < numLabels; ++l) { 3678 DMLabel label, newlabel; 3679 const char *lname; 3680 PetscBool isDepth; 3681 IS valueIS; 3682 const PetscInt *values; 3683 PetscInt numValues, val; 3684 3685 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3686 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3687 if (isDepth) continue; 3688 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3689 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3690 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3691 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3692 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3693 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3694 for (val = 0; val < numValues; ++val) { 3695 IS pointIS; 3696 const PetscInt *points; 3697 PetscInt numPoints, p; 3698 3699 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3700 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3701 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3702 for (p = 0; p < numPoints; ++p) { 3703 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3704 3705 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3706 } 3707 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3708 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3709 } 3710 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3711 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3712 } 3713 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3714 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3715 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3716 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3717 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3718 ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3719 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3720 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3721 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3722 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3723 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3724 for (; c < leafLocal[l] && c < cEnd; ++c) { 3725 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3726 } 3727 if (leafLocal[l] >= cEnd) break; 3728 if (leafRemote[l].rank == rank) { 3729 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3730 } else { 3731 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3732 } 3733 } 3734 for (; c < cEnd; ++c) { 3735 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3736 } 3737 if (0) { 3738 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3739 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3740 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3741 } 3742 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3743 for (f = fStart; f < fEnd; ++f) { 3744 PetscInt numCells; 3745 3746 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3747 if (numCells < 2) { 3748 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3749 } else { 3750 const PetscInt *cells = PETSC_NULL; 3751 PetscInt vA, vB; 3752 3753 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3754 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3755 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3756 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3757 } 3758 } 3759 if (0) { 3760 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3761 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3762 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3763 } 3764 PetscFunctionReturn(0); 3765 } 3766 3767 #undef __FUNCT__ 3768 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3769 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3770 { 3771 DMLabel label; 3772 IS valueIS; 3773 const PetscInt *values; 3774 PetscInt *depthShift; 3775 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3776 PetscErrorCode ierr; 3777 3778 PetscFunctionBegin; 3779 /* Count ghost cells */ 3780 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3781 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3782 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3783 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3784 *numGhostCells = 0; 3785 for (fs = 0; fs < numFS; ++fs) { 3786 PetscInt numBdFaces; 3787 3788 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3789 *numGhostCells += numBdFaces; 3790 } 3791 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3792 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3793 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3794 if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3795 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3796 /* Step 3: Set cone/support sizes for new points */ 3797 ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3798 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3799 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3800 } 3801 for (fs = 0; fs < numFS; ++fs) { 3802 IS faceIS; 3803 const PetscInt *faces; 3804 PetscInt numFaces, f; 3805 3806 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3807 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3808 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3809 for (f = 0; f < numFaces; ++f) { 3810 PetscInt size; 3811 3812 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3813 if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3814 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3815 } 3816 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3817 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3818 } 3819 /* Step 4: Setup ghosted DM */ 3820 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3821 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3822 /* Step 6: Set cones and supports for new points */ 3823 ghostCell = cEnd; 3824 for (fs = 0; fs < numFS; ++fs) { 3825 IS faceIS; 3826 const PetscInt *faces; 3827 PetscInt numFaces, f; 3828 3829 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3830 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3831 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3832 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3833 PetscInt newFace = faces[f] + *numGhostCells; 3834 3835 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3836 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3837 } 3838 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3839 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3840 } 3841 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3842 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3843 /* Step 7: Stratify */ 3844 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3845 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3846 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3847 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3848 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3849 PetscFunctionReturn(0); 3850 } 3851 3852 #undef __FUNCT__ 3853 #define __FUNCT__ "DMPlexConstructGhostCells" 3854 /*@C 3855 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3856 3857 Collective on dm 3858 3859 Input Parameters: 3860 + dm - The original DM 3861 - labelName - The label specifying the boundary faces (this could be auto-generated) 3862 3863 Output Parameters: 3864 + numGhostCells - The number of ghost cells added to the DM 3865 - dmGhosted - The new DM 3866 3867 Level: developer 3868 3869 .seealso: DMCreate() 3870 */ 3871 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3872 { 3873 DM gdm; 3874 PetscInt dim; 3875 PetscErrorCode ierr; 3876 3877 PetscFunctionBegin; 3878 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3879 PetscValidPointer(numGhostCells, 3); 3880 PetscValidPointer(dmGhosted, 4); 3881 ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3882 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3883 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3884 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3885 switch (dim) { 3886 case 2: 3887 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3888 break; 3889 default: 3890 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3891 } 3892 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3893 *dmGhosted = gdm; 3894 PetscFunctionReturn(0); 3895 } 3896 3897 #undef __FUNCT__ 3898 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3899 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, const char labelName[], DM sdm) 3900 { 3901 MPI_Comm comm = ((PetscObject) dm)->comm; 3902 DMLabel label; 3903 IS valueIS, *pointIS; 3904 const PetscInt *values, **splitPoints; 3905 PetscSection coordSection; 3906 Vec coordinates; 3907 PetscScalar *coords; 3908 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3909 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3910 PetscErrorCode ierr; 3911 3912 PetscFunctionBegin; 3913 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3914 /* Count split points and add cohesive cells */ 3915 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 3916 if (label) { 3917 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3918 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3919 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3920 } 3921 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3922 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3923 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3924 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3925 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3926 for(d = 0; d <= depth; ++d) { 3927 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3928 numSplitPoints[d] = 0; 3929 splitPoints[d] = PETSC_NULL; 3930 pointIS[d] = PETSC_NULL; 3931 } 3932 for(sp = 0; sp < numSP; ++sp) { 3933 const PetscInt dep = values[sp]; 3934 3935 if ((dep < 0) || (dep > depth)) continue; 3936 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3937 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3938 if (pointIS[dep]) { 3939 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3940 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3941 } 3942 } 3943 if (depth >= 0) { 3944 /* Calculate number of additional points */ 3945 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3946 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3947 /* Calculate hybrid bound for each dimension */ 3948 pMaxNew[0] += depthShift[depth]; 3949 if (depth > 1) {pMaxNew[dim-1] += depthShift[depth] + depthShift[0];} 3950 if (depth > 2) {pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1];} 3951 /* Calculate point offset for each dimension */ 3952 depthOffset[depth] = 0; 3953 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3954 if (depth > 1) {depthOffset[dim-1] = depthOffset[0] + depthShift[0];} 3955 if (depth > 2) {depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1];} 3956 } 3957 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3958 /* Step 3: Set cone/support sizes for new points */ 3959 for(dep = 0; dep <= depth; ++dep) { 3960 for(p = 0; p < numSplitPoints[dep]; ++p) { 3961 const PetscInt oldp = splitPoints[dep][p]; 3962 const PetscInt newp = depthOffset[dep] + oldp; 3963 const PetscInt splitp = pMaxNew[dep] + p; 3964 const PetscInt *support; 3965 PetscInt coneSize, supportSize, q, e; 3966 3967 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3968 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3969 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3970 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3971 if (dep == depth-1) { 3972 const PetscInt ccell = pMaxNew[depth] + p; 3973 /* Add cohesive cells, they are prisms */ 3974 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3975 } else if (dep == 0) { 3976 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3977 3978 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3979 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3980 for(e = 0, q = 0; e < supportSize; ++e) { 3981 PetscInt val; 3982 3983 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3984 if ((val == 1) || (val == (shift + 1))) ++q; 3985 } 3986 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3987 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3988 for(e = 0, q = 0; e < supportSize; ++e) { 3989 PetscInt val; 3990 3991 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3992 if ((val == 1) || (val == -(shift + 1))) ++q; 3993 } 3994 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3995 /* Add cohesive edges */ 3996 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3997 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3998 } else if (dep == dim-2) { 3999 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4000 /* Split old edge: Faces in positive side cells and old split faces */ 4001 for(e = 0, q = 0; e < supportSize; ++e) { 4002 PetscInt val; 4003 4004 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4005 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4006 } 4007 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4008 /* Split new edge: Faces in negative side cells and new split faces */ 4009 for(e = 0, q = 0; e < supportSize; ++e) { 4010 PetscInt val; 4011 4012 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4013 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4014 } 4015 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4016 } 4017 } 4018 } 4019 /* Step 4: Setup split DM */ 4020 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4021 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4022 /* Step 6: Set cones and supports for new points */ 4023 for(dep = 0; dep <= depth; ++dep) { 4024 for(p = 0; p < numSplitPoints[dep]; ++p) { 4025 const PetscInt oldp = splitPoints[dep][p]; 4026 const PetscInt newp = depthOffset[dep] + oldp; 4027 const PetscInt splitp = pMaxNew[dep] + p; 4028 const PetscInt *cone, *support, *ornt; 4029 PetscInt coneSize, supportSize, q, v, e, s; 4030 4031 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4032 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4033 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4034 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4035 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4036 if (dep == depth-1) { 4037 const PetscInt ccell = pMaxNew[depth] + p; 4038 const PetscInt *supportF; 4039 4040 /* Split face: copy in old face to new face to start */ 4041 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4042 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4043 /* Split old face: old vertices/edges in cone so no change */ 4044 /* Split new face: new vertices/edges in cone */ 4045 for(q = 0; q < coneSize; ++q) { 4046 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4047 coneNew[2+q] = pMaxNew[dim-2] + v; 4048 } 4049 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4050 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4051 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4052 coneNew[0] = newp; 4053 coneNew[1] = splitp; 4054 for(q = 0; q < coneSize; ++q) { 4055 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4056 } 4057 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4058 4059 4060 for(s = 0; s < supportSize; ++s) { 4061 PetscInt val; 4062 4063 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4064 if (val < 0) { 4065 /* Split old face: Replace negative side cell with cohesive cell */ 4066 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4067 } else { 4068 /* Split new face: Replace positive side cell with cohesive cell */ 4069 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4070 } 4071 } 4072 } else if (dep == 0) { 4073 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4074 4075 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4076 for(e = 0, q = 0; e < supportSize; ++e) { 4077 PetscInt val; 4078 4079 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4080 if ((val == 1) || (val == (shift + 1))) { 4081 supportNew[q++] = depthOffset[1] + support[e]; 4082 } 4083 } 4084 supportNew[q] = cedge; 4085 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4086 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4087 for(e = 0, q = 0; e < supportSize; ++e) { 4088 PetscInt val, edge; 4089 4090 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4091 if (val == 1) { 4092 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4093 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4094 supportNew[q++] = pMaxNew[1] + edge; 4095 } else if (val == -(shift + 1)) { 4096 supportNew[q++] = depthOffset[1] + support[e]; 4097 } 4098 } 4099 supportNew[q] = cedge; 4100 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4101 /* Cohesive edge: Old and new split vertex, punting on support */ 4102 coneNew[0] = newp; 4103 coneNew[1] = splitp; 4104 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4105 } else if (dep == dim-2) { 4106 /* Split old edge: old vertices in cone so no change */ 4107 /* Split new edge: new vertices in cone */ 4108 for(q = 0; q < coneSize; ++q) { 4109 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4110 coneNew[q] = pMaxNew[dim-3] + v; 4111 } 4112 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4113 /* Split old edge: Faces in positive side cells and old split faces */ 4114 for(e = 0, q = 0; e < supportSize; ++e) { 4115 PetscInt val; 4116 4117 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4118 if ((val == dim-1) || (val == (shift + dim-1))) { 4119 supportNew[q++] = depthOffset[dim-1] + support[e]; 4120 } 4121 } 4122 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4123 /* Split new edge: Faces in negative side cells and new split faces */ 4124 for(e = 0, q = 0; e < supportSize; ++e) { 4125 PetscInt val, face; 4126 4127 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4128 if (val == dim-1) { 4129 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4130 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4131 supportNew[q++] = pMaxNew[dim-1] + face; 4132 } else if (val == -(shift + dim-1)) { 4133 supportNew[q++] = depthOffset[dim-1] + support[e]; 4134 } 4135 } 4136 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4137 } 4138 } 4139 } 4140 /* Step 6b: Replace split points in negative side cones */ 4141 for(sp = 0; sp < numSP; ++sp) { 4142 PetscInt dep = values[sp]; 4143 IS pIS; 4144 PetscInt numPoints; 4145 const PetscInt *points; 4146 4147 if (dep >= 0) continue; 4148 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4149 if (!pIS) continue; 4150 dep = -dep - shift; 4151 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4152 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4153 for(p = 0; p < numPoints; ++p) { 4154 const PetscInt oldp = points[p]; 4155 const PetscInt newp = depthOffset[dep] + oldp; 4156 const PetscInt *cone; 4157 PetscInt coneSize, c; 4158 PetscBool replaced = PETSC_FALSE; 4159 4160 /* Negative edge: replace split vertex */ 4161 /* Negative cell: replace split face */ 4162 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4163 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4164 for(c = 0; c < coneSize; ++c) { 4165 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4166 PetscInt csplitp, cp, val; 4167 4168 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4169 if (val == dep-1) { 4170 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4171 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4172 csplitp = pMaxNew[dep-1] + cp; 4173 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4174 replaced = PETSC_TRUE; 4175 } 4176 } 4177 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4178 } 4179 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4180 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4181 } 4182 /* Step 7: Stratify */ 4183 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4184 /* Step 8: Coordinates */ 4185 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4186 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4187 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4188 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4189 for(v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4190 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4191 const PetscInt splitp = pMaxNew[0] + v; 4192 PetscInt dof, off, soff, d; 4193 4194 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4195 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4196 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4197 for(d = 0; d < dof; ++d) { 4198 coords[soff+d] = coords[off+d]; 4199 } 4200 } 4201 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4202 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4203 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4204 /* Step 10: Labels */ 4205 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4206 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4207 for (dep = 0; dep <= depth; ++dep) { 4208 for (p = 0; p < numSplitPoints[dep]; ++p) { 4209 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4210 const PetscInt splitp = pMaxNew[dep] + p; 4211 PetscInt l; 4212 4213 for (l = 0; l < numLabels; ++l) { 4214 DMLabel label; 4215 const char *lname; 4216 PetscInt val; 4217 4218 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4219 ierr = DMPlexGetLabel(sdm, lname, &label);CHKERRQ(ierr); 4220 ierr = DMLabelGetValue(label, newp, &val);CHKERRQ(ierr); 4221 if (val >= 0) { 4222 ierr = DMLabelSetValue(label, splitp, val);CHKERRQ(ierr); 4223 if (dep == 0) { 4224 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4225 ierr = DMLabelSetValue(label, cedge, val);CHKERRQ(ierr); 4226 } 4227 } 4228 } 4229 } 4230 } 4231 for (sp = 0; sp < numSP; ++sp) { 4232 const PetscInt dep = values[sp]; 4233 4234 if ((dep < 0) || (dep > depth)) continue; 4235 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4236 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4237 } 4238 if (label) { 4239 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4240 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4241 } 4242 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4243 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4244 PetscFunctionReturn(0); 4245 } 4246 4247 #undef __FUNCT__ 4248 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4249 /*@C 4250 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4251 4252 Collective on dm 4253 4254 Input Parameters: 4255 + dm - The original DM 4256 - labelName - The label specifying the boundary faces (this could be auto-generated) 4257 4258 Output Parameters: 4259 - dmSplit - The new DM 4260 4261 Level: developer 4262 4263 .seealso: DMCreate() 4264 */ 4265 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, const char labelName[], DM *dmSplit) 4266 { 4267 DM sdm; 4268 PetscInt dim; 4269 PetscErrorCode ierr; 4270 4271 PetscFunctionBegin; 4272 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4273 PetscValidPointer(dmSplit, 4); 4274 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4275 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4276 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4277 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4278 switch(dim) { 4279 case 2: 4280 case 3: 4281 ierr = DMPlexConstructCohesiveCells_Private(dm, labelName, sdm);CHKERRQ(ierr); 4282 break; 4283 default: 4284 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4285 } 4286 *dmSplit = sdm; 4287 PetscFunctionReturn(0); 4288 } 4289 4290 #undef __FUNCT__ 4291 #define __FUNCT__ "DMLabelCohesiveComplete" 4292 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4293 { 4294 IS dimIS; 4295 const PetscInt *points; 4296 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4297 PetscErrorCode ierr; 4298 4299 PetscFunctionBegin; 4300 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4301 /* Cell orientation for face gives the side of the fault */ 4302 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4303 if (!dimIS) PetscFunctionReturn(0); 4304 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4305 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4306 for(p = 0; p < numPoints; ++p) { 4307 const PetscInt *support; 4308 PetscInt supportSize, s; 4309 4310 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4311 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4312 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4313 for(s = 0; s < supportSize; ++s) { 4314 const PetscInt *cone, *ornt; 4315 PetscInt coneSize, c; 4316 PetscBool pos = PETSC_TRUE; 4317 4318 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4319 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4320 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4321 for(c = 0; c < coneSize; ++c) { 4322 if (cone[c] == points[p]) { 4323 if (ornt[c] >= 0) { 4324 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4325 } else { 4326 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4327 pos = PETSC_FALSE; 4328 } 4329 break; 4330 } 4331 } 4332 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]); 4333 /* Put faces touching the fault in the label */ 4334 for(c = 0; c < coneSize; ++c) { 4335 const PetscInt point = cone[c]; 4336 4337 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4338 if (val == -1) { 4339 PetscInt *closure = PETSC_NULL; 4340 PetscInt closureSize, cl; 4341 4342 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4343 for (cl = 0; cl < closureSize*2; cl += 2) { 4344 const PetscInt clp = closure[cl]; 4345 4346 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4347 if ((val >= 0) && (val < dim-1)) { 4348 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4349 break; 4350 } 4351 } 4352 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4353 } 4354 } 4355 } 4356 } 4357 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4358 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4359 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4360 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4361 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4362 if (!dimIS) PetscFunctionReturn(0); 4363 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4364 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4365 for(p = 0; p < numPoints; ++p) { 4366 PetscInt *star = PETSC_NULL; 4367 PetscInt starSize, s; 4368 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4369 4370 /* First mark cells connected to the fault */ 4371 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4372 while (again) { 4373 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4374 again = 0; 4375 for (s = 0; s < starSize*2; s += 2) { 4376 const PetscInt point = star[s]; 4377 const PetscInt *cone; 4378 PetscInt coneSize, c; 4379 4380 if ((point < cStart) || (point >= cEnd)) continue; 4381 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4382 if (val != -1) continue; 4383 again = 2; 4384 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4385 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4386 for(c = 0; c < coneSize; ++c) { 4387 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4388 if (val != -1) { 4389 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); 4390 if (val > 0) { 4391 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4392 } else { 4393 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4394 } 4395 again = 1; 4396 break; 4397 } 4398 } 4399 } 4400 } 4401 /* Classify the rest by cell membership */ 4402 for (s = 0; s < starSize*2; s += 2) { 4403 const PetscInt point = star[s]; 4404 4405 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4406 if (val == -1) { 4407 PetscInt *sstar = PETSC_NULL; 4408 PetscInt sstarSize, ss; 4409 PetscBool marked = PETSC_FALSE; 4410 4411 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4412 for (ss = 0; ss < sstarSize*2; ss += 2) { 4413 const PetscInt spoint = sstar[ss]; 4414 4415 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4416 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4417 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4418 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4419 if (val > 0) { 4420 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4421 } else { 4422 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4423 } 4424 marked = PETSC_TRUE; 4425 break; 4426 } 4427 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4428 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4429 } 4430 } 4431 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4432 } 4433 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4434 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4435 PetscFunctionReturn(0); 4436 } 4437 4438 #undef __FUNCT__ 4439 #define __FUNCT__ "DMPlexInterpolate_2D" 4440 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4441 { 4442 DM idm; 4443 DM_Plex *mesh; 4444 PetscHashIJ edgeTable; 4445 PetscInt *off; 4446 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4447 PetscInt numEdges, firstEdge, edge, e; 4448 PetscErrorCode ierr; 4449 4450 PetscFunctionBegin; 4451 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4452 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4453 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4454 numCells = cEnd - cStart; 4455 numVertices = vEnd - vStart; 4456 firstEdge = numCells + numVertices; 4457 numEdges = 0 ; 4458 /* Count edges using algorithm from CreateNeighborCSR */ 4459 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4460 if (off) { 4461 PetscInt numCorners = 0; 4462 4463 numEdges = off[numCells]/2; 4464 #if 0 4465 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4466 numEdges += 3*numCells - off[numCells]; 4467 #else 4468 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4469 for (c = cStart; c < cEnd; ++c) { 4470 PetscInt coneSize; 4471 4472 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4473 numCorners += coneSize; 4474 } 4475 numEdges += numCorners - off[numCells]; 4476 #endif 4477 } 4478 #if 0 4479 /* Check Euler characteristic V - E + F = 1 */ 4480 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4481 #endif 4482 /* Create interpolated mesh */ 4483 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4484 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4485 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4486 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4487 for (c = 0; c < numCells; ++c) { 4488 PetscInt numCorners; 4489 4490 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4491 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4492 } 4493 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4494 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4495 } 4496 ierr = DMSetUp(idm);CHKERRQ(ierr); 4497 /* Get edge cones from subsets of cell vertices */ 4498 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4499 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4500 4501 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4502 const PetscInt *cellFaces; 4503 PetscInt numCellFaces, faceSize, cf; 4504 4505 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4506 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4507 for (cf = 0; cf < numCellFaces; ++cf) { 4508 #if 1 4509 PetscHashIJKey key; 4510 4511 key.i = PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4512 key.j = PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]); 4513 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4514 if (e < 0) { 4515 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4516 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4517 e = edge++; 4518 } 4519 #else 4520 PetscBool found = PETSC_FALSE; 4521 4522 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4523 for (e = firstEdge; e < edge; ++e) { 4524 const PetscInt *cone; 4525 4526 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4527 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4528 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4529 found = PETSC_TRUE; 4530 break; 4531 } 4532 } 4533 if (!found) { 4534 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4535 ++edge; 4536 } 4537 #endif 4538 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4539 } 4540 } 4541 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4542 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4543 ierr = PetscFree(off);CHKERRQ(ierr); 4544 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4545 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4546 mesh = (DM_Plex *) (idm)->data; 4547 /* Orient edges */ 4548 for (c = 0; c < numCells; ++c) { 4549 const PetscInt *cone = PETSC_NULL, *cellFaces; 4550 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4551 4552 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4553 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4554 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4555 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4556 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4557 for (cf = 0; cf < numCellFaces; ++cf) { 4558 const PetscInt *econe = PETSC_NULL; 4559 PetscInt esize; 4560 4561 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4562 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4563 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]); 4564 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4565 /* Correctly oriented */ 4566 mesh->coneOrientations[coff+cf] = 0; 4567 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4568 /* Start at index 1, and reverse orientation */ 4569 mesh->coneOrientations[coff+cf] = -(1+1); 4570 } 4571 } 4572 } 4573 *dmInt = idm; 4574 PetscFunctionReturn(0); 4575 } 4576 4577 #undef __FUNCT__ 4578 #define __FUNCT__ "DMPlexInterpolate_3D" 4579 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4580 { 4581 DM idm, fdm; 4582 DM_Plex *mesh; 4583 PetscInt *off; 4584 const PetscInt numCorners = 4; 4585 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4586 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4587 PetscErrorCode ierr; 4588 4589 PetscFunctionBegin; 4590 { 4591 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4592 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4593 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4594 } 4595 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4596 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4597 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4598 numCells = cEnd - cStart; 4599 numVertices = vEnd - vStart; 4600 firstFace = numCells + numVertices; 4601 numFaces = 0 ; 4602 /* Count faces using algorithm from CreateNeighborCSR */ 4603 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4604 if (off) { 4605 numFaces = off[numCells]/2; 4606 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4607 numFaces += 4*numCells - off[numCells]; 4608 } 4609 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4610 firstEdge = firstFace + numFaces; 4611 numEdges = numVertices + numFaces - numCells - 1; 4612 /* Create interpolated mesh */ 4613 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4614 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4615 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4616 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4617 for (c = 0; c < numCells; ++c) { 4618 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4619 } 4620 for (f = firstFace; f < firstFace+numFaces; ++f) { 4621 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4622 } 4623 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4624 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4625 } 4626 ierr = DMSetUp(idm);CHKERRQ(ierr); 4627 /* Get face cones from subsets of cell vertices */ 4628 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4629 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4630 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4631 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4632 for (f = firstFace; f < firstFace+numFaces; ++f) { 4633 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4634 } 4635 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4636 for (c = 0, face = firstFace; c < numCells; ++c) { 4637 const PetscInt *cellFaces; 4638 PetscInt numCellFaces, faceSize, cf; 4639 4640 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4641 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4642 for (cf = 0; cf < numCellFaces; ++cf) { 4643 PetscBool found = PETSC_FALSE; 4644 4645 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4646 for (f = firstFace; f < face; ++f) { 4647 const PetscInt *cone = PETSC_NULL; 4648 4649 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4650 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4651 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4652 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4653 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4654 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4655 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4656 found = PETSC_TRUE; 4657 break; 4658 } 4659 } 4660 if (!found) { 4661 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4662 /* Save the vertices for orientation calculation */ 4663 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4664 ++face; 4665 } 4666 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4667 } 4668 } 4669 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4670 /* Get edge cones from subsets of face vertices */ 4671 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4672 const PetscInt *cellFaces; 4673 PetscInt numCellFaces, faceSize, cf; 4674 4675 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4676 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4677 for (cf = 0; cf < numCellFaces; ++cf) { 4678 PetscBool found = PETSC_FALSE; 4679 4680 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4681 for (e = firstEdge; e < edge; ++e) { 4682 const PetscInt *cone = PETSC_NULL; 4683 4684 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4685 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4686 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4687 found = PETSC_TRUE; 4688 break; 4689 } 4690 } 4691 if (!found) { 4692 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4693 ++edge; 4694 } 4695 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4696 } 4697 } 4698 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4699 ierr = PetscFree(off);CHKERRQ(ierr); 4700 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4701 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4702 mesh = (DM_Plex *) (idm)->data; 4703 /* Orient edges */ 4704 for (f = firstFace; f < firstFace+numFaces; ++f) { 4705 const PetscInt *cone, *cellFaces; 4706 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4707 4708 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4709 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4710 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4711 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4712 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4713 for (cf = 0; cf < numCellFaces; ++cf) { 4714 const PetscInt *econe; 4715 PetscInt esize; 4716 4717 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4718 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4719 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]); 4720 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4721 /* Correctly oriented */ 4722 mesh->coneOrientations[coff+cf] = 0; 4723 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4724 /* Start at index 1, and reverse orientation */ 4725 mesh->coneOrientations[coff+cf] = -(1+1); 4726 } 4727 } 4728 } 4729 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4730 /* Orient faces */ 4731 for (c = 0; c < numCells; ++c) { 4732 const PetscInt *cone, *cellFaces; 4733 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4734 4735 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4736 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4737 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4738 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4739 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4740 for (cf = 0; cf < numCellFaces; ++cf) { 4741 PetscInt *origClosure = PETSC_NULL, *closure; 4742 PetscInt closureSize, i; 4743 4744 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4745 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4746 for (i = 4; i < 7; ++i) { 4747 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); 4748 } 4749 closure = &origClosure[4*2]; 4750 /* Remember that this is the orientation for edges, not vertices */ 4751 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4752 /* Correctly oriented */ 4753 mesh->coneOrientations[coff+cf] = 0; 4754 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4755 /* Shifted by 1 */ 4756 mesh->coneOrientations[coff+cf] = 1; 4757 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4758 /* Shifted by 2 */ 4759 mesh->coneOrientations[coff+cf] = 2; 4760 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4761 /* Start at edge 1, and reverse orientation */ 4762 mesh->coneOrientations[coff+cf] = -(1+1); 4763 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4764 /* Start at index 0, and reverse orientation */ 4765 mesh->coneOrientations[coff+cf] = -(0+1); 4766 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4767 /* Start at index 2, and reverse orientation */ 4768 mesh->coneOrientations[coff+cf] = -(2+1); 4769 } 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); 4770 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4771 } 4772 } 4773 { 4774 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4775 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4776 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4777 } 4778 *dmInt = idm; 4779 PetscFunctionReturn(0); 4780 } 4781 4782 #undef __FUNCT__ 4783 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4784 /* 4785 This takes as input the common mesh generator output, a list of the vertices for each cell 4786 */ 4787 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4788 { 4789 PetscInt *cone, c, p; 4790 PetscErrorCode ierr; 4791 4792 PetscFunctionBegin; 4793 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4794 for (c = 0; c < numCells; ++c) { 4795 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4796 } 4797 ierr = DMSetUp(dm);CHKERRQ(ierr); 4798 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4799 for (c = 0; c < numCells; ++c) { 4800 for (p = 0; p < numCorners; ++p) { 4801 cone[p] = cells[c*numCorners+p]+numCells; 4802 } 4803 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4804 } 4805 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4806 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4807 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4808 PetscFunctionReturn(0); 4809 } 4810 4811 #undef __FUNCT__ 4812 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4813 /* 4814 This takes as input the coordinates for each vertex 4815 */ 4816 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4817 { 4818 PetscSection coordSection; 4819 Vec coordinates; 4820 PetscScalar *coords; 4821 PetscInt coordSize, v, d; 4822 PetscErrorCode ierr; 4823 4824 PetscFunctionBegin; 4825 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4826 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4827 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4828 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4829 for (v = numCells; v < numCells+numVertices; ++v) { 4830 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4831 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4832 } 4833 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4834 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4835 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4836 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4837 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4838 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4839 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4840 for (v = 0; v < numVertices; ++v) { 4841 for (d = 0; d < spaceDim; ++d) { 4842 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4843 } 4844 } 4845 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4846 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4847 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4848 PetscFunctionReturn(0); 4849 } 4850 4851 #undef __FUNCT__ 4852 #define __FUNCT__ "DMPlexCreateFromCellList" 4853 /* 4854 This takes as input the common mesh generator output, a list of the vertices for each cell 4855 */ 4856 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4857 { 4858 PetscErrorCode ierr; 4859 4860 PetscFunctionBegin; 4861 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4862 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4863 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4864 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4865 if (interpolate) { 4866 DM idm; 4867 4868 switch (dim) { 4869 case 2: 4870 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4871 case 3: 4872 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4873 default: 4874 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4875 } 4876 ierr = DMDestroy(dm);CHKERRQ(ierr); 4877 *dm = idm; 4878 } 4879 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4880 PetscFunctionReturn(0); 4881 } 4882 4883 #if defined(PETSC_HAVE_TRIANGLE) 4884 #include <triangle.h> 4885 4886 #undef __FUNCT__ 4887 #define __FUNCT__ "InitInput_Triangle" 4888 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4889 { 4890 PetscFunctionBegin; 4891 inputCtx->numberofpoints = 0; 4892 inputCtx->numberofpointattributes = 0; 4893 inputCtx->pointlist = PETSC_NULL; 4894 inputCtx->pointattributelist = PETSC_NULL; 4895 inputCtx->pointmarkerlist = PETSC_NULL; 4896 inputCtx->numberofsegments = 0; 4897 inputCtx->segmentlist = PETSC_NULL; 4898 inputCtx->segmentmarkerlist = PETSC_NULL; 4899 inputCtx->numberoftriangleattributes = 0; 4900 inputCtx->trianglelist = PETSC_NULL; 4901 inputCtx->numberofholes = 0; 4902 inputCtx->holelist = PETSC_NULL; 4903 inputCtx->numberofregions = 0; 4904 inputCtx->regionlist = PETSC_NULL; 4905 PetscFunctionReturn(0); 4906 } 4907 4908 #undef __FUNCT__ 4909 #define __FUNCT__ "InitOutput_Triangle" 4910 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4911 { 4912 PetscFunctionBegin; 4913 outputCtx->numberofpoints = 0; 4914 outputCtx->pointlist = PETSC_NULL; 4915 outputCtx->pointattributelist = PETSC_NULL; 4916 outputCtx->pointmarkerlist = PETSC_NULL; 4917 outputCtx->numberoftriangles = 0; 4918 outputCtx->trianglelist = PETSC_NULL; 4919 outputCtx->triangleattributelist = PETSC_NULL; 4920 outputCtx->neighborlist = PETSC_NULL; 4921 outputCtx->segmentlist = PETSC_NULL; 4922 outputCtx->segmentmarkerlist = PETSC_NULL; 4923 outputCtx->numberofedges = 0; 4924 outputCtx->edgelist = PETSC_NULL; 4925 outputCtx->edgemarkerlist = PETSC_NULL; 4926 PetscFunctionReturn(0); 4927 } 4928 4929 #undef __FUNCT__ 4930 #define __FUNCT__ "FiniOutput_Triangle" 4931 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4932 { 4933 PetscFunctionBegin; 4934 free(outputCtx->pointmarkerlist); 4935 free(outputCtx->edgelist); 4936 free(outputCtx->edgemarkerlist); 4937 free(outputCtx->trianglelist); 4938 free(outputCtx->neighborlist); 4939 PetscFunctionReturn(0); 4940 } 4941 4942 #undef __FUNCT__ 4943 #define __FUNCT__ "DMPlexGenerate_Triangle" 4944 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4945 { 4946 MPI_Comm comm = ((PetscObject) boundary)->comm; 4947 PetscInt dim = 2; 4948 const PetscBool createConvexHull = PETSC_FALSE; 4949 const PetscBool constrained = PETSC_FALSE; 4950 struct triangulateio in; 4951 struct triangulateio out; 4952 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4953 PetscMPIInt rank; 4954 PetscErrorCode ierr; 4955 4956 PetscFunctionBegin; 4957 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4958 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4959 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4960 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4961 in.numberofpoints = vEnd - vStart; 4962 if (in.numberofpoints > 0) { 4963 PetscSection coordSection; 4964 Vec coordinates; 4965 PetscScalar *array; 4966 4967 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4968 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4969 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4970 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4971 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4972 for (v = vStart; v < vEnd; ++v) { 4973 const PetscInt idx = v - vStart; 4974 PetscInt off, d; 4975 4976 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4977 for (d = 0; d < dim; ++d) { 4978 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4979 } 4980 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4981 } 4982 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4983 } 4984 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4985 in.numberofsegments = eEnd - eStart; 4986 if (in.numberofsegments > 0) { 4987 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4988 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4989 for (e = eStart; e < eEnd; ++e) { 4990 const PetscInt idx = e - eStart; 4991 const PetscInt *cone; 4992 4993 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4994 in.segmentlist[idx*2+0] = cone[0] - vStart; 4995 in.segmentlist[idx*2+1] = cone[1] - vStart; 4996 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4997 } 4998 } 4999 #if 0 /* Do not currently support holes */ 5000 PetscReal *holeCoords; 5001 PetscInt h, d; 5002 5003 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5004 if (in.numberofholes > 0) { 5005 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5006 for (h = 0; h < in.numberofholes; ++h) { 5007 for (d = 0; d < dim; ++d) { 5008 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5009 } 5010 } 5011 } 5012 #endif 5013 if (!rank) { 5014 char args[32]; 5015 5016 /* Take away 'Q' for verbose output */ 5017 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5018 if (createConvexHull) { 5019 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 5020 } 5021 if (constrained) { 5022 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 5023 } 5024 triangulate(args, &in, &out, PETSC_NULL); 5025 } 5026 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5027 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5028 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5029 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5030 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 5031 5032 { 5033 const PetscInt numCorners = 3; 5034 const PetscInt numCells = out.numberoftriangles; 5035 const PetscInt numVertices = out.numberofpoints; 5036 const int *cells = out.trianglelist; 5037 const double *meshCoords = out.pointlist; 5038 5039 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5040 /* Set labels */ 5041 for (v = 0; v < numVertices; ++v) { 5042 if (out.pointmarkerlist[v]) { 5043 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5044 } 5045 } 5046 if (interpolate) { 5047 for (e = 0; e < out.numberofedges; e++) { 5048 if (out.edgemarkerlist[e]) { 5049 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5050 const PetscInt *edges; 5051 PetscInt numEdges; 5052 5053 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5054 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5055 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5056 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5057 } 5058 } 5059 } 5060 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5061 } 5062 #if 0 /* Do not currently support holes */ 5063 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5064 #endif 5065 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5066 PetscFunctionReturn(0); 5067 } 5068 5069 #undef __FUNCT__ 5070 #define __FUNCT__ "DMPlexRefine_Triangle" 5071 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5072 { 5073 MPI_Comm comm = ((PetscObject) dm)->comm; 5074 PetscInt dim = 2; 5075 struct triangulateio in; 5076 struct triangulateio out; 5077 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5078 PetscMPIInt rank; 5079 PetscErrorCode ierr; 5080 5081 PetscFunctionBegin; 5082 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5083 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5084 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5085 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5086 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5087 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5088 in.numberofpoints = vEnd - vStart; 5089 if (in.numberofpoints > 0) { 5090 PetscSection coordSection; 5091 Vec coordinates; 5092 PetscScalar *array; 5093 5094 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5095 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5096 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5097 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5098 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5099 for (v = vStart; v < vEnd; ++v) { 5100 const PetscInt idx = v - vStart; 5101 PetscInt off, d; 5102 5103 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5104 for (d = 0; d < dim; ++d) { 5105 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5106 } 5107 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5108 } 5109 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5110 } 5111 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5112 in.numberofcorners = 3; 5113 in.numberoftriangles = cEnd - cStart; 5114 in.trianglearealist = (double *) maxVolumes; 5115 if (in.numberoftriangles > 0) { 5116 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5117 for (c = cStart; c < cEnd; ++c) { 5118 const PetscInt idx = c - cStart; 5119 PetscInt *closure = PETSC_NULL; 5120 PetscInt closureSize; 5121 5122 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5123 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5124 for (v = 0; v < 3; ++v) { 5125 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5126 } 5127 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5128 } 5129 } 5130 /* TODO: Segment markers are missing on input */ 5131 #if 0 /* Do not currently support holes */ 5132 PetscReal *holeCoords; 5133 PetscInt h, d; 5134 5135 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5136 if (in.numberofholes > 0) { 5137 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5138 for (h = 0; h < in.numberofholes; ++h) { 5139 for (d = 0; d < dim; ++d) { 5140 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5141 } 5142 } 5143 } 5144 #endif 5145 if (!rank) { 5146 char args[32]; 5147 5148 /* Take away 'Q' for verbose output */ 5149 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5150 triangulate(args, &in, &out, PETSC_NULL); 5151 } 5152 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5153 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5154 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5155 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5156 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5157 5158 { 5159 const PetscInt numCorners = 3; 5160 const PetscInt numCells = out.numberoftriangles; 5161 const PetscInt numVertices = out.numberofpoints; 5162 const int *cells = out.trianglelist; 5163 const double *meshCoords = out.pointlist; 5164 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5165 5166 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5167 /* Set labels */ 5168 for (v = 0; v < numVertices; ++v) { 5169 if (out.pointmarkerlist[v]) { 5170 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5171 } 5172 } 5173 if (interpolate) { 5174 PetscInt e; 5175 5176 for (e = 0; e < out.numberofedges; e++) { 5177 if (out.edgemarkerlist[e]) { 5178 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5179 const PetscInt *edges; 5180 PetscInt numEdges; 5181 5182 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5183 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5184 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5185 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5186 } 5187 } 5188 } 5189 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5190 } 5191 #if 0 /* Do not currently support holes */ 5192 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5193 #endif 5194 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5195 PetscFunctionReturn(0); 5196 } 5197 #endif 5198 5199 #if defined(PETSC_HAVE_TETGEN) 5200 #include <tetgen.h> 5201 #undef __FUNCT__ 5202 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5203 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5204 { 5205 MPI_Comm comm = ((PetscObject) boundary)->comm; 5206 const PetscInt dim = 3; 5207 ::tetgenio in; 5208 ::tetgenio out; 5209 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5210 PetscMPIInt rank; 5211 PetscErrorCode ierr; 5212 5213 PetscFunctionBegin; 5214 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5215 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5216 in.numberofpoints = vEnd - vStart; 5217 if (in.numberofpoints > 0) { 5218 PetscSection coordSection; 5219 Vec coordinates; 5220 PetscScalar *array; 5221 5222 in.pointlist = new double[in.numberofpoints*dim]; 5223 in.pointmarkerlist = new int[in.numberofpoints]; 5224 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5225 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5226 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5227 for (v = vStart; v < vEnd; ++v) { 5228 const PetscInt idx = v - vStart; 5229 PetscInt off, d; 5230 5231 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5232 for (d = 0; d < dim; ++d) { 5233 in.pointlist[idx*dim + d] = array[off+d]; 5234 } 5235 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5236 } 5237 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5238 } 5239 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5240 in.numberoffacets = fEnd - fStart; 5241 if (in.numberoffacets > 0) { 5242 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5243 in.facetmarkerlist = new int[in.numberoffacets]; 5244 for (f = fStart; f < fEnd; ++f) { 5245 const PetscInt idx = f - fStart; 5246 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5247 5248 in.facetlist[idx].numberofpolygons = 1; 5249 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5250 in.facetlist[idx].numberofholes = 0; 5251 in.facetlist[idx].holelist = NULL; 5252 5253 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5254 for (p = 0; p < numPoints*2; p += 2) { 5255 const PetscInt point = points[p]; 5256 if ((point >= vStart) && (point < vEnd)) { 5257 points[numVertices++] = point; 5258 } 5259 } 5260 5261 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5262 poly->numberofvertices = numVertices; 5263 poly->vertexlist = new int[poly->numberofvertices]; 5264 for (v = 0; v < numVertices; ++v) { 5265 const PetscInt vIdx = points[v] - vStart; 5266 poly->vertexlist[v] = vIdx; 5267 } 5268 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5269 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5270 } 5271 } 5272 if (!rank) { 5273 char args[32]; 5274 5275 /* Take away 'Q' for verbose output */ 5276 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5277 ::tetrahedralize(args, &in, &out); 5278 } 5279 { 5280 const PetscInt numCorners = 4; 5281 const PetscInt numCells = out.numberoftetrahedra; 5282 const PetscInt numVertices = out.numberofpoints; 5283 const int *cells = out.tetrahedronlist; 5284 const double *meshCoords = out.pointlist; 5285 5286 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5287 /* Set labels */ 5288 for (v = 0; v < numVertices; ++v) { 5289 if (out.pointmarkerlist[v]) { 5290 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5291 } 5292 } 5293 if (interpolate) { 5294 PetscInt e; 5295 5296 for (e = 0; e < out.numberofedges; e++) { 5297 if (out.edgemarkerlist[e]) { 5298 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5299 const PetscInt *edges; 5300 PetscInt numEdges; 5301 5302 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5303 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5304 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5305 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5306 } 5307 } 5308 for (f = 0; f < out.numberoftrifaces; f++) { 5309 if (out.trifacemarkerlist[f]) { 5310 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5311 const PetscInt *faces; 5312 PetscInt numFaces; 5313 5314 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5315 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5316 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5317 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5318 } 5319 } 5320 } 5321 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5322 } 5323 PetscFunctionReturn(0); 5324 } 5325 5326 #undef __FUNCT__ 5327 #define __FUNCT__ "DMPlexRefine_Tetgen" 5328 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5329 { 5330 MPI_Comm comm = ((PetscObject) dm)->comm; 5331 const PetscInt dim = 3; 5332 ::tetgenio in; 5333 ::tetgenio out; 5334 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5335 PetscMPIInt rank; 5336 PetscErrorCode ierr; 5337 5338 PetscFunctionBegin; 5339 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5340 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5341 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5342 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5343 in.numberofpoints = vEnd - vStart; 5344 if (in.numberofpoints > 0) { 5345 PetscSection coordSection; 5346 Vec coordinates; 5347 PetscScalar *array; 5348 5349 in.pointlist = new double[in.numberofpoints*dim]; 5350 in.pointmarkerlist = new int[in.numberofpoints]; 5351 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5352 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5353 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5354 for (v = vStart; v < vEnd; ++v) { 5355 const PetscInt idx = v - vStart; 5356 PetscInt off, d; 5357 5358 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5359 for (d = 0; d < dim; ++d) { 5360 in.pointlist[idx*dim + d] = array[off+d]; 5361 } 5362 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5363 } 5364 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5365 } 5366 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5367 in.numberofcorners = 4; 5368 in.numberoftetrahedra = cEnd - cStart; 5369 in.tetrahedronvolumelist = (double *) maxVolumes; 5370 if (in.numberoftetrahedra > 0) { 5371 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5372 for (c = cStart; c < cEnd; ++c) { 5373 const PetscInt idx = c - cStart; 5374 PetscInt *closure = PETSC_NULL; 5375 PetscInt closureSize; 5376 5377 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5378 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5379 for (v = 0; v < 4; ++v) { 5380 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5381 } 5382 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5383 } 5384 } 5385 /* TODO: Put in boundary faces with markers */ 5386 if (!rank) { 5387 char args[32]; 5388 5389 /* Take away 'Q' for verbose output */ 5390 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5391 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5392 ::tetrahedralize(args, &in, &out); 5393 } 5394 in.tetrahedronvolumelist = NULL; 5395 5396 { 5397 const PetscInt numCorners = 4; 5398 const PetscInt numCells = out.numberoftetrahedra; 5399 const PetscInt numVertices = out.numberofpoints; 5400 const int *cells = out.tetrahedronlist; 5401 const double *meshCoords = out.pointlist; 5402 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5403 5404 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5405 /* Set labels */ 5406 for (v = 0; v < numVertices; ++v) { 5407 if (out.pointmarkerlist[v]) { 5408 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5409 } 5410 } 5411 if (interpolate) { 5412 PetscInt e, f; 5413 5414 for (e = 0; e < out.numberofedges; e++) { 5415 if (out.edgemarkerlist[e]) { 5416 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5417 const PetscInt *edges; 5418 PetscInt numEdges; 5419 5420 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5421 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5422 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5423 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5424 } 5425 } 5426 for (f = 0; f < out.numberoftrifaces; f++) { 5427 if (out.trifacemarkerlist[f]) { 5428 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5429 const PetscInt *faces; 5430 PetscInt numFaces; 5431 5432 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5433 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5434 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5435 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5436 } 5437 } 5438 } 5439 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5440 } 5441 PetscFunctionReturn(0); 5442 } 5443 #endif 5444 5445 #if defined(PETSC_HAVE_CTETGEN) 5446 #include "ctetgen.h" 5447 5448 #undef __FUNCT__ 5449 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5450 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5451 { 5452 MPI_Comm comm = ((PetscObject) boundary)->comm; 5453 const PetscInt dim = 3; 5454 PLC *in, *out; 5455 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5456 PetscMPIInt rank; 5457 PetscErrorCode ierr; 5458 5459 PetscFunctionBegin; 5460 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5461 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5462 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5463 ierr = PLCCreate(&in);CHKERRQ(ierr); 5464 ierr = PLCCreate(&out);CHKERRQ(ierr); 5465 in->numberofpoints = vEnd - vStart; 5466 if (in->numberofpoints > 0) { 5467 PetscSection coordSection; 5468 Vec coordinates; 5469 PetscScalar *array; 5470 5471 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5472 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5473 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5474 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5475 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5476 for (v = vStart; v < vEnd; ++v) { 5477 const PetscInt idx = v - vStart; 5478 PetscInt off, d, m; 5479 5480 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5481 for (d = 0; d < dim; ++d) { 5482 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5483 } 5484 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5485 in->pointmarkerlist[idx] = (int) m; 5486 } 5487 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5488 } 5489 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5490 in->numberoffacets = fEnd - fStart; 5491 if (in->numberoffacets > 0) { 5492 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5493 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5494 for (f = fStart; f < fEnd; ++f) { 5495 const PetscInt idx = f - fStart; 5496 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5497 polygon *poly; 5498 5499 in->facetlist[idx].numberofpolygons = 1; 5500 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5501 in->facetlist[idx].numberofholes = 0; 5502 in->facetlist[idx].holelist = PETSC_NULL; 5503 5504 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5505 for (p = 0; p < numPoints*2; p += 2) { 5506 const PetscInt point = points[p]; 5507 if ((point >= vStart) && (point < vEnd)) { 5508 points[numVertices++] = point; 5509 } 5510 } 5511 5512 poly = in->facetlist[idx].polygonlist; 5513 poly->numberofvertices = numVertices; 5514 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5515 for (v = 0; v < numVertices; ++v) { 5516 const PetscInt vIdx = points[v] - vStart; 5517 poly->vertexlist[v] = vIdx; 5518 } 5519 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5520 in->facetmarkerlist[idx] = (int) m; 5521 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5522 } 5523 } 5524 if (!rank) { 5525 TetGenOpts t; 5526 5527 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5528 t.in = boundary; /* Should go away */ 5529 t.plc = 1; 5530 t.quality = 1; 5531 t.edgesout = 1; 5532 t.zeroindex = 1; 5533 t.quiet = 1; 5534 t.verbose = verbose; 5535 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5536 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5537 } 5538 { 5539 const PetscInt numCorners = 4; 5540 const PetscInt numCells = out->numberoftetrahedra; 5541 const PetscInt numVertices = out->numberofpoints; 5542 const int *cells = out->tetrahedronlist; 5543 const double *meshCoords = out->pointlist; 5544 5545 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5546 /* Set labels */ 5547 for (v = 0; v < numVertices; ++v) { 5548 if (out->pointmarkerlist[v]) { 5549 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5550 } 5551 } 5552 if (interpolate) { 5553 PetscInt e; 5554 5555 for (e = 0; e < out->numberofedges; e++) { 5556 if (out->edgemarkerlist[e]) { 5557 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5558 const PetscInt *edges; 5559 PetscInt numEdges; 5560 5561 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5562 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5563 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5564 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5565 } 5566 } 5567 for (f = 0; f < out->numberoftrifaces; f++) { 5568 if (out->trifacemarkerlist[f]) { 5569 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5570 const PetscInt *faces; 5571 PetscInt numFaces; 5572 5573 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5574 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5575 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5576 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5577 } 5578 } 5579 } 5580 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5581 } 5582 5583 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5584 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5585 PetscFunctionReturn(0); 5586 } 5587 5588 #undef __FUNCT__ 5589 #define __FUNCT__ "DMPlexRefine_CTetgen" 5590 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5591 { 5592 MPI_Comm comm = ((PetscObject) dm)->comm; 5593 const PetscInt dim = 3; 5594 PLC *in, *out; 5595 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5596 PetscMPIInt rank; 5597 PetscErrorCode ierr; 5598 5599 PetscFunctionBegin; 5600 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5601 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5602 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5603 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5604 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5605 ierr = PLCCreate(&in);CHKERRQ(ierr); 5606 ierr = PLCCreate(&out);CHKERRQ(ierr); 5607 in->numberofpoints = vEnd - vStart; 5608 if (in->numberofpoints > 0) { 5609 PetscSection coordSection; 5610 Vec coordinates; 5611 PetscScalar *array; 5612 5613 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5614 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5615 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5616 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5617 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5618 for (v = vStart; v < vEnd; ++v) { 5619 const PetscInt idx = v - vStart; 5620 PetscInt off, d, m; 5621 5622 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5623 for (d = 0; d < dim; ++d) { 5624 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5625 } 5626 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5627 in->pointmarkerlist[idx] = (int) m; 5628 } 5629 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5630 } 5631 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5632 in->numberofcorners = 4; 5633 in->numberoftetrahedra = cEnd - cStart; 5634 in->tetrahedronvolumelist = maxVolumes; 5635 if (in->numberoftetrahedra > 0) { 5636 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5637 for (c = cStart; c < cEnd; ++c) { 5638 const PetscInt idx = c - cStart; 5639 PetscInt *closure = PETSC_NULL; 5640 PetscInt closureSize; 5641 5642 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5643 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5644 for (v = 0; v < 4; ++v) { 5645 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5646 } 5647 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5648 } 5649 } 5650 if (!rank) { 5651 TetGenOpts t; 5652 5653 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5654 t.in = dm; /* Should go away */ 5655 t.refine = 1; 5656 t.varvolume = 1; 5657 t.quality = 1; 5658 t.edgesout = 1; 5659 t.zeroindex = 1; 5660 t.quiet = 1; 5661 t.verbose = verbose; /* Change this */ 5662 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5663 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5664 } 5665 { 5666 const PetscInt numCorners = 4; 5667 const PetscInt numCells = out->numberoftetrahedra; 5668 const PetscInt numVertices = out->numberofpoints; 5669 const int *cells = out->tetrahedronlist; 5670 const double *meshCoords = out->pointlist; 5671 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5672 5673 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5674 /* Set labels */ 5675 for (v = 0; v < numVertices; ++v) { 5676 if (out->pointmarkerlist[v]) { 5677 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5678 } 5679 } 5680 if (interpolate) { 5681 PetscInt e, f; 5682 5683 for (e = 0; e < out->numberofedges; e++) { 5684 if (out->edgemarkerlist[e]) { 5685 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5686 const PetscInt *edges; 5687 PetscInt numEdges; 5688 5689 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5690 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5691 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5692 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5693 } 5694 } 5695 for (f = 0; f < out->numberoftrifaces; f++) { 5696 if (out->trifacemarkerlist[f]) { 5697 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5698 const PetscInt *faces; 5699 PetscInt numFaces; 5700 5701 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5702 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5703 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5704 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5705 } 5706 } 5707 } 5708 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5709 } 5710 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5711 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5712 PetscFunctionReturn(0); 5713 } 5714 #endif 5715 5716 #undef __FUNCT__ 5717 #define __FUNCT__ "DMPlexGenerate" 5718 /*@C 5719 DMPlexGenerate - Generates a mesh. 5720 5721 Not Collective 5722 5723 Input Parameters: 5724 + boundary - The DMPlex boundary object 5725 . name - The mesh generation package name 5726 - interpolate - Flag to create intermediate mesh elements 5727 5728 Output Parameter: 5729 . mesh - The DMPlex object 5730 5731 Level: intermediate 5732 5733 .keywords: mesh, elements 5734 .seealso: DMPlexCreate(), DMRefine() 5735 @*/ 5736 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5737 { 5738 PetscInt dim; 5739 char genname[1024]; 5740 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5741 PetscErrorCode ierr; 5742 5743 PetscFunctionBegin; 5744 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5745 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5746 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5747 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5748 if (flg) {name = genname;} 5749 if (name) { 5750 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5751 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5752 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5753 } 5754 switch (dim) { 5755 case 1: 5756 if (!name || isTriangle) { 5757 #if defined(PETSC_HAVE_TRIANGLE) 5758 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5759 #else 5760 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5761 #endif 5762 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5763 break; 5764 case 2: 5765 if (!name || isCTetgen) { 5766 #if defined(PETSC_HAVE_CTETGEN) 5767 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5768 #else 5769 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5770 #endif 5771 } else if (isTetgen) { 5772 #if defined(PETSC_HAVE_TETGEN) 5773 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5774 #else 5775 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5776 #endif 5777 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5778 break; 5779 default: 5780 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5781 } 5782 PetscFunctionReturn(0); 5783 } 5784 5785 typedef PetscInt CellRefiner; 5786 5787 #undef __FUNCT__ 5788 #define __FUNCT__ "GetDepthStart_Private" 5789 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5790 { 5791 PetscFunctionBegin; 5792 if (cStart) *cStart = 0; 5793 if (vStart) *vStart = depthSize[depth]; 5794 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5795 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5796 PetscFunctionReturn(0); 5797 } 5798 5799 #undef __FUNCT__ 5800 #define __FUNCT__ "GetDepthEnd_Private" 5801 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5802 { 5803 PetscFunctionBegin; 5804 if (cEnd) *cEnd = depthSize[depth]; 5805 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5806 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5807 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5808 PetscFunctionReturn(0); 5809 } 5810 5811 #undef __FUNCT__ 5812 #define __FUNCT__ "CellRefinerGetSizes" 5813 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5814 { 5815 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5816 PetscErrorCode ierr; 5817 5818 PetscFunctionBegin; 5819 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5820 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5821 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5822 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5823 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5824 switch (refiner) { 5825 case 1: 5826 /* Simplicial 2D */ 5827 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5828 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5829 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5830 break; 5831 case 3: 5832 /* Hybrid 2D */ 5833 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5834 cMax = PetscMin(cEnd, cMax); 5835 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5836 fMax = PetscMin(fEnd, fMax); 5837 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5838 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 */ 5839 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5840 break; 5841 case 2: 5842 /* Hex 2D */ 5843 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5844 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5845 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5846 break; 5847 default: 5848 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5849 } 5850 PetscFunctionReturn(0); 5851 } 5852 5853 #undef __FUNCT__ 5854 #define __FUNCT__ "CellRefinerSetConeSizes" 5855 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5856 { 5857 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5858 PetscErrorCode ierr; 5859 5860 PetscFunctionBegin; 5861 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5862 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5863 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5864 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5865 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5866 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5867 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5868 switch (refiner) { 5869 case 1: 5870 /* Simplicial 2D */ 5871 /* All cells have 3 faces */ 5872 for (c = cStart; c < cEnd; ++c) { 5873 for (r = 0; r < 4; ++r) { 5874 const PetscInt newp = (c - cStart)*4 + r; 5875 5876 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5877 } 5878 } 5879 /* Split faces have 2 vertices and the same cells as the parent */ 5880 for (f = fStart; f < fEnd; ++f) { 5881 for (r = 0; r < 2; ++r) { 5882 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5883 PetscInt size; 5884 5885 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5886 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5887 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5888 } 5889 } 5890 /* Interior faces have 2 vertices and 2 cells */ 5891 for (c = cStart; c < cEnd; ++c) { 5892 for (r = 0; r < 3; ++r) { 5893 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5894 5895 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5896 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5897 } 5898 } 5899 /* Old vertices have identical supports */ 5900 for (v = vStart; v < vEnd; ++v) { 5901 const PetscInt newp = vStartNew + (v - vStart); 5902 PetscInt size; 5903 5904 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5905 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5906 } 5907 /* Face vertices have 2 + cells*2 supports */ 5908 for (f = fStart; f < fEnd; ++f) { 5909 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5910 PetscInt size; 5911 5912 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5913 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5914 } 5915 break; 5916 case 2: 5917 /* Hex 2D */ 5918 /* All cells have 4 faces */ 5919 for (c = cStart; c < cEnd; ++c) { 5920 for (r = 0; r < 4; ++r) { 5921 const PetscInt newp = (c - cStart)*4 + r; 5922 5923 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5924 } 5925 } 5926 /* Split faces have 2 vertices and the same cells as the parent */ 5927 for (f = fStart; f < fEnd; ++f) { 5928 for (r = 0; r < 2; ++r) { 5929 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5930 PetscInt size; 5931 5932 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5933 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5934 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5935 } 5936 } 5937 /* Interior faces have 2 vertices and 2 cells */ 5938 for (c = cStart; c < cEnd; ++c) { 5939 for (r = 0; r < 4; ++r) { 5940 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5941 5942 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5943 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5944 } 5945 } 5946 /* Old vertices have identical supports */ 5947 for (v = vStart; v < vEnd; ++v) { 5948 const PetscInt newp = vStartNew + (v - vStart); 5949 PetscInt size; 5950 5951 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5952 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5953 } 5954 /* Face vertices have 2 + cells supports */ 5955 for (f = fStart; f < fEnd; ++f) { 5956 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5957 PetscInt size; 5958 5959 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5960 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5961 } 5962 /* Cell vertices have 4 supports */ 5963 for (c = cStart; c < cEnd; ++c) { 5964 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5965 5966 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5967 } 5968 break; 5969 case 3: 5970 /* Hybrid 2D */ 5971 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5972 cMax = PetscMin(cEnd, cMax); 5973 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5974 fMax = PetscMin(fEnd, fMax); 5975 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5976 /* Interior cells have 3 faces */ 5977 for (c = cStart; c < cMax; ++c) { 5978 for (r = 0; r < 4; ++r) { 5979 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5980 5981 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5982 } 5983 } 5984 /* Hybrid cells have 4 faces */ 5985 for (c = cMax; c < cEnd; ++c) { 5986 for (r = 0; r < 2; ++r) { 5987 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5988 5989 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5990 } 5991 } 5992 /* Interior split faces have 2 vertices and the same cells as the parent */ 5993 for (f = fStart; f < fMax; ++f) { 5994 for (r = 0; r < 2; ++r) { 5995 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5996 PetscInt size; 5997 5998 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5999 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6000 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6001 } 6002 } 6003 /* Interior cell faces have 2 vertices and 2 cells */ 6004 for (c = cStart; c < cMax; ++c) { 6005 for (r = 0; r < 3; ++r) { 6006 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6007 6008 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6009 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6010 } 6011 } 6012 /* Hybrid faces have 2 vertices and the same cells */ 6013 for (f = fMax; f < fEnd; ++f) { 6014 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6015 PetscInt size; 6016 6017 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6018 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6019 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6020 } 6021 /* Hybrid cell faces have 2 vertices and 2 cells */ 6022 for (c = cMax; c < cEnd; ++c) { 6023 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6024 6025 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 6026 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 6027 } 6028 /* Old vertices have identical supports */ 6029 for (v = vStart; v < vEnd; ++v) { 6030 const PetscInt newp = vStartNew + (v - vStart); 6031 PetscInt size; 6032 6033 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6034 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 6035 } 6036 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6037 for (f = fStart; f < fMax; ++f) { 6038 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6039 const PetscInt *support; 6040 PetscInt size, newSize = 2, s; 6041 6042 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6043 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6044 for (s = 0; s < size; ++s) { 6045 if (support[s] >= cMax) { 6046 newSize += 1; 6047 } else { 6048 newSize += 2; 6049 } 6050 } 6051 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 6052 } 6053 break; 6054 default: 6055 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6056 } 6057 PetscFunctionReturn(0); 6058 } 6059 6060 #undef __FUNCT__ 6061 #define __FUNCT__ "CellRefinerSetCones" 6062 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6063 { 6064 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; 6065 PetscInt maxSupportSize, *supportRef; 6066 PetscErrorCode ierr; 6067 6068 PetscFunctionBegin; 6069 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6070 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6071 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6072 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6073 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6074 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6075 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6076 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6077 switch (refiner) { 6078 case 1: 6079 /* Simplicial 2D */ 6080 /* 6081 2 6082 |\ 6083 | \ 6084 | \ 6085 | \ 6086 | C \ 6087 | \ 6088 | \ 6089 2---1---1 6090 |\ D / \ 6091 | 2 0 \ 6092 |A \ / B \ 6093 0---0-------1 6094 */ 6095 /* All cells have 3 faces */ 6096 for (c = cStart; c < cEnd; ++c) { 6097 const PetscInt newp = cStartNew + (c - cStart)*4; 6098 const PetscInt *cone, *ornt; 6099 PetscInt coneNew[3], orntNew[3]; 6100 6101 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6102 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6103 /* A triangle */ 6104 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6105 orntNew[0] = ornt[0]; 6106 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6107 orntNew[1] = -2; 6108 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6109 orntNew[2] = ornt[2]; 6110 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6111 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6112 #if 1 6113 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); 6114 for (p = 0; p < 3; ++p) { 6115 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); 6116 } 6117 #endif 6118 /* B triangle */ 6119 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6120 orntNew[0] = ornt[0]; 6121 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6122 orntNew[1] = ornt[1]; 6123 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6124 orntNew[2] = -2; 6125 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6126 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6127 #if 1 6128 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); 6129 for (p = 0; p < 3; ++p) { 6130 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); 6131 } 6132 #endif 6133 /* C triangle */ 6134 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6135 orntNew[0] = -2; 6136 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6137 orntNew[1] = ornt[1]; 6138 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6139 orntNew[2] = ornt[2]; 6140 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6141 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6142 #if 1 6143 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); 6144 for (p = 0; p < 3; ++p) { 6145 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); 6146 } 6147 #endif 6148 /* D triangle */ 6149 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6150 orntNew[0] = 0; 6151 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6152 orntNew[1] = 0; 6153 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6154 orntNew[2] = 0; 6155 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6156 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6157 #if 1 6158 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); 6159 for (p = 0; p < 3; ++p) { 6160 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); 6161 } 6162 #endif 6163 } 6164 /* Split faces have 2 vertices and the same cells as the parent */ 6165 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6166 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6167 for (f = fStart; f < fEnd; ++f) { 6168 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6169 6170 for (r = 0; r < 2; ++r) { 6171 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6172 const PetscInt *cone, *support; 6173 PetscInt coneNew[2], coneSize, c, supportSize, s; 6174 6175 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6176 coneNew[0] = vStartNew + (cone[0] - vStart); 6177 coneNew[1] = vStartNew + (cone[1] - vStart); 6178 coneNew[(r+1)%2] = newv; 6179 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6180 #if 1 6181 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6182 for (p = 0; p < 2; ++p) { 6183 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); 6184 } 6185 #endif 6186 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6187 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6188 for (s = 0; s < supportSize; ++s) { 6189 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6190 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6191 for (c = 0; c < coneSize; ++c) { 6192 if (cone[c] == f) { 6193 break; 6194 } 6195 } 6196 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6197 } 6198 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6199 #if 1 6200 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6201 for (p = 0; p < supportSize; ++p) { 6202 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); 6203 } 6204 #endif 6205 } 6206 } 6207 /* Interior faces have 2 vertices and 2 cells */ 6208 for (c = cStart; c < cEnd; ++c) { 6209 const PetscInt *cone; 6210 6211 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6212 for (r = 0; r < 3; ++r) { 6213 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6214 PetscInt coneNew[2]; 6215 PetscInt supportNew[2]; 6216 6217 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6218 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6219 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6220 #if 1 6221 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6222 for (p = 0; p < 2; ++p) { 6223 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); 6224 } 6225 #endif 6226 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6227 supportNew[1] = (c - cStart)*4 + 3; 6228 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6229 #if 1 6230 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6231 for (p = 0; p < 2; ++p) { 6232 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); 6233 } 6234 #endif 6235 } 6236 } 6237 /* Old vertices have identical supports */ 6238 for (v = vStart; v < vEnd; ++v) { 6239 const PetscInt newp = vStartNew + (v - vStart); 6240 const PetscInt *support, *cone; 6241 PetscInt size, s; 6242 6243 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6244 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6245 for (s = 0; s < size; ++s) { 6246 PetscInt r = 0; 6247 6248 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6249 if (cone[1] == v) r = 1; 6250 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6251 } 6252 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6253 #if 1 6254 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6255 for (p = 0; p < size; ++p) { 6256 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); 6257 } 6258 #endif 6259 } 6260 /* Face vertices have 2 + cells*2 supports */ 6261 for (f = fStart; f < fEnd; ++f) { 6262 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6263 const PetscInt *cone, *support; 6264 PetscInt size, s; 6265 6266 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6267 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6268 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6269 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6270 for (s = 0; s < size; ++s) { 6271 PetscInt r = 0; 6272 6273 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6274 if (cone[1] == f) r = 1; 6275 else if (cone[2] == f) r = 2; 6276 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6277 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6278 } 6279 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6280 #if 1 6281 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6282 for (p = 0; p < 2+size*2; ++p) { 6283 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); 6284 } 6285 #endif 6286 } 6287 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6288 break; 6289 case 2: 6290 /* Hex 2D */ 6291 /* 6292 3---------2---------2 6293 | | | 6294 | D 2 C | 6295 | | | 6296 3----3----0----1----1 6297 | | | 6298 | A 0 B | 6299 | | | 6300 0---------0---------1 6301 */ 6302 /* All cells have 4 faces */ 6303 for (c = cStart; c < cEnd; ++c) { 6304 const PetscInt newp = (c - cStart)*4; 6305 const PetscInt *cone, *ornt; 6306 PetscInt coneNew[4], orntNew[4]; 6307 6308 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6309 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6310 /* A quad */ 6311 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6312 orntNew[0] = ornt[0]; 6313 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6314 orntNew[1] = 0; 6315 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6316 orntNew[2] = -2; 6317 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6318 orntNew[3] = ornt[3]; 6319 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6320 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6321 #if 1 6322 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); 6323 for (p = 0; p < 4; ++p) { 6324 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); 6325 } 6326 #endif 6327 /* B quad */ 6328 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6329 orntNew[0] = ornt[0]; 6330 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6331 orntNew[1] = ornt[1]; 6332 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6333 orntNew[2] = 0; 6334 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6335 orntNew[3] = -2; 6336 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6337 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6338 #if 1 6339 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); 6340 for (p = 0; p < 4; ++p) { 6341 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); 6342 } 6343 #endif 6344 /* C quad */ 6345 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6346 orntNew[0] = -2; 6347 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6348 orntNew[1] = ornt[1]; 6349 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6350 orntNew[2] = ornt[2]; 6351 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6352 orntNew[3] = 0; 6353 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6354 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6355 #if 1 6356 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); 6357 for (p = 0; p < 4; ++p) { 6358 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); 6359 } 6360 #endif 6361 /* D quad */ 6362 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6363 orntNew[0] = 0; 6364 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6365 orntNew[1] = -2; 6366 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6367 orntNew[2] = ornt[2]; 6368 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6369 orntNew[3] = ornt[3]; 6370 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6371 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6372 #if 1 6373 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); 6374 for (p = 0; p < 4; ++p) { 6375 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); 6376 } 6377 #endif 6378 } 6379 /* Split faces have 2 vertices and the same cells as the parent */ 6380 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6381 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6382 for (f = fStart; f < fEnd; ++f) { 6383 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6384 6385 for (r = 0; r < 2; ++r) { 6386 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6387 const PetscInt *cone, *support; 6388 PetscInt coneNew[2], coneSize, c, supportSize, s; 6389 6390 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6391 coneNew[0] = vStartNew + (cone[0] - vStart); 6392 coneNew[1] = vStartNew + (cone[1] - vStart); 6393 coneNew[(r+1)%2] = newv; 6394 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6395 #if 1 6396 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6397 for (p = 0; p < 2; ++p) { 6398 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); 6399 } 6400 #endif 6401 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6402 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6403 for (s = 0; s < supportSize; ++s) { 6404 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6405 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6406 for (c = 0; c < coneSize; ++c) { 6407 if (cone[c] == f) { 6408 break; 6409 } 6410 } 6411 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6412 } 6413 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6414 #if 1 6415 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6416 for (p = 0; p < supportSize; ++p) { 6417 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); 6418 } 6419 #endif 6420 } 6421 } 6422 /* Interior faces have 2 vertices and 2 cells */ 6423 for (c = cStart; c < cEnd; ++c) { 6424 const PetscInt *cone; 6425 PetscInt coneNew[2], supportNew[2]; 6426 6427 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6428 for (r = 0; r < 4; ++r) { 6429 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6430 6431 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6432 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6433 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6434 #if 1 6435 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6436 for (p = 0; p < 2; ++p) { 6437 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6438 } 6439 #endif 6440 supportNew[0] = (c - cStart)*4 + r; 6441 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6442 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6443 #if 1 6444 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6445 for (p = 0; p < 2; ++p) { 6446 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6447 } 6448 #endif 6449 } 6450 } 6451 /* Old vertices have identical supports */ 6452 for (v = vStart; v < vEnd; ++v) { 6453 const PetscInt newp = vStartNew + (v - vStart); 6454 const PetscInt *support, *cone; 6455 PetscInt size, s; 6456 6457 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6458 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6459 for (s = 0; s < size; ++s) { 6460 PetscInt r = 0; 6461 6462 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6463 if (cone[1] == v) r = 1; 6464 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6465 } 6466 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6467 #if 1 6468 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6469 for (p = 0; p < size; ++p) { 6470 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); 6471 } 6472 #endif 6473 } 6474 /* Face vertices have 2 + cells supports */ 6475 for (f = fStart; f < fEnd; ++f) { 6476 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6477 const PetscInt *cone, *support; 6478 PetscInt size, s; 6479 6480 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6481 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6482 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6483 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6484 for (s = 0; s < size; ++s) { 6485 PetscInt r = 0; 6486 6487 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6488 if (cone[1] == f) r = 1; 6489 else if (cone[2] == f) r = 2; 6490 else if (cone[3] == f) r = 3; 6491 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6492 } 6493 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6494 #if 1 6495 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6496 for (p = 0; p < 2+size; ++p) { 6497 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); 6498 } 6499 #endif 6500 } 6501 /* Cell vertices have 4 supports */ 6502 for (c = cStart; c < cEnd; ++c) { 6503 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6504 PetscInt supportNew[4]; 6505 6506 for (r = 0; r < 4; ++r) { 6507 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6508 } 6509 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6510 } 6511 break; 6512 case 3: 6513 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6514 cMax = PetscMin(cEnd, cMax); 6515 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6516 fMax = PetscMin(fEnd, fMax); 6517 /* Interior cells have 3 faces */ 6518 for (c = cStart; c < cMax; ++c) { 6519 const PetscInt newp = cStartNew + (c - cStart)*4; 6520 const PetscInt *cone, *ornt; 6521 PetscInt coneNew[3], orntNew[3]; 6522 6523 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6524 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6525 /* A triangle */ 6526 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6527 orntNew[0] = ornt[0]; 6528 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6529 orntNew[1] = -2; 6530 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6531 orntNew[2] = ornt[2]; 6532 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6533 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6534 #if 1 6535 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); 6536 for (p = 0; p < 3; ++p) { 6537 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); 6538 } 6539 #endif 6540 /* B triangle */ 6541 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6542 orntNew[0] = ornt[0]; 6543 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6544 orntNew[1] = ornt[1]; 6545 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6546 orntNew[2] = -2; 6547 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6548 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6549 #if 1 6550 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); 6551 for (p = 0; p < 3; ++p) { 6552 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); 6553 } 6554 #endif 6555 /* C triangle */ 6556 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6557 orntNew[0] = -2; 6558 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6559 orntNew[1] = ornt[1]; 6560 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6561 orntNew[2] = ornt[2]; 6562 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6563 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6564 #if 1 6565 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); 6566 for (p = 0; p < 3; ++p) { 6567 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); 6568 } 6569 #endif 6570 /* D triangle */ 6571 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6572 orntNew[0] = 0; 6573 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6574 orntNew[1] = 0; 6575 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6576 orntNew[2] = 0; 6577 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6578 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6579 #if 1 6580 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); 6581 for (p = 0; p < 3; ++p) { 6582 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); 6583 } 6584 #endif 6585 } 6586 /* 6587 2----3----3 6588 | | 6589 | B | 6590 | | 6591 0----4--- 1 6592 | | 6593 | A | 6594 | | 6595 0----2----1 6596 */ 6597 /* Hybrid cells have 4 faces */ 6598 for (c = cMax; c < cEnd; ++c) { 6599 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6600 const PetscInt *cone, *ornt; 6601 PetscInt coneNew[4], orntNew[4]; 6602 6603 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6604 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6605 /* A quad */ 6606 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6607 orntNew[0] = ornt[0]; 6608 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6609 orntNew[1] = ornt[1]; 6610 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6611 orntNew[2] = 0; 6612 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6613 orntNew[3] = 0; 6614 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6615 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6616 #if 1 6617 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); 6618 for (p = 0; p < 4; ++p) { 6619 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); 6620 } 6621 #endif 6622 /* B quad */ 6623 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6624 orntNew[0] = ornt[0]; 6625 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6626 orntNew[1] = ornt[1]; 6627 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6628 orntNew[2] = 0; 6629 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6630 orntNew[3] = 0; 6631 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6632 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6633 #if 1 6634 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); 6635 for (p = 0; p < 4; ++p) { 6636 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); 6637 } 6638 #endif 6639 } 6640 /* Interior split faces have 2 vertices and the same cells as the parent */ 6641 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6642 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6643 for (f = fStart; f < fMax; ++f) { 6644 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6645 6646 for (r = 0; r < 2; ++r) { 6647 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6648 const PetscInt *cone, *support; 6649 PetscInt coneNew[2], coneSize, c, supportSize, s; 6650 6651 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6652 coneNew[0] = vStartNew + (cone[0] - vStart); 6653 coneNew[1] = vStartNew + (cone[1] - vStart); 6654 coneNew[(r+1)%2] = newv; 6655 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6656 #if 1 6657 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6658 for (p = 0; p < 2; ++p) { 6659 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); 6660 } 6661 #endif 6662 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6663 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6664 for (s = 0; s < supportSize; ++s) { 6665 if (support[s] >= cMax) { 6666 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6667 } else { 6668 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6669 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6670 for (c = 0; c < coneSize; ++c) { 6671 if (cone[c] == f) { 6672 break; 6673 } 6674 } 6675 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6676 } 6677 } 6678 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6679 #if 1 6680 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6681 for (p = 0; p < supportSize; ++p) { 6682 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); 6683 } 6684 #endif 6685 } 6686 } 6687 /* Interior cell faces have 2 vertices and 2 cells */ 6688 for (c = cStart; c < cMax; ++c) { 6689 const PetscInt *cone; 6690 6691 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6692 for (r = 0; r < 3; ++r) { 6693 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6694 PetscInt coneNew[2]; 6695 PetscInt supportNew[2]; 6696 6697 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6698 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6699 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6700 #if 1 6701 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6702 for (p = 0; p < 2; ++p) { 6703 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); 6704 } 6705 #endif 6706 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6707 supportNew[1] = (c - cStart)*4 + 3; 6708 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6709 #if 1 6710 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6711 for (p = 0; p < 2; ++p) { 6712 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); 6713 } 6714 #endif 6715 } 6716 } 6717 /* Interior hybrid faces have 2 vertices and the same cells */ 6718 for (f = fMax; f < fEnd; ++f) { 6719 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6720 const PetscInt *cone; 6721 const PetscInt *support; 6722 PetscInt coneNew[2]; 6723 PetscInt supportNew[2]; 6724 PetscInt size, s, r; 6725 6726 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6727 coneNew[0] = vStartNew + (cone[0] - vStart); 6728 coneNew[1] = vStartNew + (cone[1] - vStart); 6729 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6730 #if 1 6731 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6732 for (p = 0; p < 2; ++p) { 6733 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); 6734 } 6735 #endif 6736 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6737 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6738 for (s = 0; s < size; ++s) { 6739 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6740 for (r = 0; r < 2; ++r) { 6741 if (cone[r+2] == f) break; 6742 } 6743 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6744 } 6745 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6746 #if 1 6747 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6748 for (p = 0; p < size; ++p) { 6749 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); 6750 } 6751 #endif 6752 } 6753 /* Cell hybrid faces have 2 vertices and 2 cells */ 6754 for (c = cMax; c < cEnd; ++c) { 6755 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6756 const PetscInt *cone; 6757 PetscInt coneNew[2]; 6758 PetscInt supportNew[2]; 6759 6760 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6761 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6762 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6763 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6764 #if 1 6765 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6766 for (p = 0; p < 2; ++p) { 6767 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); 6768 } 6769 #endif 6770 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6771 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6772 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6773 #if 1 6774 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6775 for (p = 0; p < 2; ++p) { 6776 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); 6777 } 6778 #endif 6779 } 6780 /* Old vertices have identical supports */ 6781 for (v = vStart; v < vEnd; ++v) { 6782 const PetscInt newp = vStartNew + (v - vStart); 6783 const PetscInt *support, *cone; 6784 PetscInt size, s; 6785 6786 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6787 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6788 for (s = 0; s < size; ++s) { 6789 if (support[s] >= fMax) { 6790 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6791 } else { 6792 PetscInt r = 0; 6793 6794 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6795 if (cone[1] == v) r = 1; 6796 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6797 } 6798 } 6799 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6800 #if 1 6801 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6802 for (p = 0; p < size; ++p) { 6803 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); 6804 } 6805 #endif 6806 } 6807 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6808 for (f = fStart; f < fMax; ++f) { 6809 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6810 const PetscInt *cone, *support; 6811 PetscInt size, newSize = 2, s; 6812 6813 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6814 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6815 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6816 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6817 for (s = 0; s < size; ++s) { 6818 PetscInt r = 0; 6819 6820 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6821 if (support[s] >= cMax) { 6822 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6823 newSize += 1; 6824 } else { 6825 if (cone[1] == f) r = 1; 6826 else if (cone[2] == f) r = 2; 6827 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6828 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6829 newSize += 2; 6830 } 6831 } 6832 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6833 #if 1 6834 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6835 for (p = 0; p < newSize; ++p) { 6836 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); 6837 } 6838 #endif 6839 } 6840 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6841 break; 6842 default: 6843 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6844 } 6845 PetscFunctionReturn(0); 6846 } 6847 6848 #undef __FUNCT__ 6849 #define __FUNCT__ "CellRefinerSetCoordinates" 6850 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6851 { 6852 PetscSection coordSection, coordSectionNew; 6853 Vec coordinates, coordinatesNew; 6854 PetscScalar *coords, *coordsNew; 6855 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6856 PetscErrorCode ierr; 6857 6858 PetscFunctionBegin; 6859 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6860 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6861 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6862 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6863 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6864 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6865 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6866 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6867 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6868 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6869 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6870 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6871 if (fMax < 0) fMax = fEnd; 6872 switch (refiner) { 6873 case 1: 6874 case 2: 6875 case 3: 6876 /* Simplicial and Hex 2D */ 6877 /* All vertices have the dim coordinates */ 6878 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6879 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6880 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6881 } 6882 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6883 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6884 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6885 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6886 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6887 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6888 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6889 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6890 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6891 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6892 /* Old vertices have the same coordinates */ 6893 for (v = vStart; v < vEnd; ++v) { 6894 const PetscInt newv = vStartNew + (v - vStart); 6895 PetscInt off, offnew, d; 6896 6897 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6898 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6899 for (d = 0; d < dim; ++d) { 6900 coordsNew[offnew+d] = coords[off+d]; 6901 } 6902 } 6903 /* Face vertices have the average of endpoint coordinates */ 6904 for (f = fStart; f < fMax; ++f) { 6905 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6906 const PetscInt *cone; 6907 PetscInt coneSize, offA, offB, offnew, d; 6908 6909 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6910 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6911 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6912 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6913 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6914 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6915 for (d = 0; d < dim; ++d) { 6916 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6917 } 6918 } 6919 /* Just Hex 2D */ 6920 if (refiner == 2) { 6921 /* Cell vertices have the average of corner coordinates */ 6922 for (c = cStart; c < cEnd; ++c) { 6923 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6924 PetscInt *cone = PETSC_NULL; 6925 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6926 6927 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6928 for (p = 0; p < closureSize*2; p += 2) { 6929 const PetscInt point = cone[p]; 6930 if ((point >= vStart) && (point < vEnd)) { 6931 cone[coneSize++] = point; 6932 } 6933 } 6934 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6935 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6936 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6937 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6938 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6939 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6940 for (d = 0; d < dim; ++d) { 6941 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6942 } 6943 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6944 } 6945 } 6946 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6947 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6948 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6949 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6950 break; 6951 default: 6952 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6953 } 6954 PetscFunctionReturn(0); 6955 } 6956 6957 #undef __FUNCT__ 6958 #define __FUNCT__ "DMPlexCreateProcessSF" 6959 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6960 { 6961 PetscInt numRoots, numLeaves, l; 6962 const PetscInt *localPoints; 6963 const PetscSFNode *remotePoints; 6964 PetscInt *localPointsNew; 6965 PetscSFNode *remotePointsNew; 6966 PetscInt *ranks, *ranksNew; 6967 PetscErrorCode ierr; 6968 6969 PetscFunctionBegin; 6970 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6971 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6972 for (l = 0; l < numLeaves; ++l) { 6973 ranks[l] = remotePoints[l].rank; 6974 } 6975 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6976 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6977 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6978 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6979 for (l = 0; l < numLeaves; ++l) { 6980 ranksNew[l] = ranks[l]; 6981 localPointsNew[l] = l; 6982 remotePointsNew[l].index = 0; 6983 remotePointsNew[l].rank = ranksNew[l]; 6984 } 6985 ierr = PetscFree(ranks);CHKERRQ(ierr); 6986 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6987 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6988 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6989 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6990 PetscFunctionReturn(0); 6991 } 6992 6993 #undef __FUNCT__ 6994 #define __FUNCT__ "CellRefinerCreateSF" 6995 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6996 { 6997 PetscSF sf, sfNew, sfProcess; 6998 IS processRanks; 6999 MPI_Datatype depthType; 7000 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 7001 const PetscInt *localPoints, *neighbors; 7002 const PetscSFNode *remotePoints; 7003 PetscInt *localPointsNew; 7004 PetscSFNode *remotePointsNew; 7005 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 7006 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 7007 PetscErrorCode ierr; 7008 7009 PetscFunctionBegin; 7010 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 7011 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7012 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7013 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7014 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7015 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7016 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7017 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 7018 switch (refiner) { 7019 case 3: 7020 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7021 cMax = PetscMin(cEnd, cMax); 7022 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7023 fMax = PetscMin(fEnd, fMax); 7024 } 7025 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 7026 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 7027 /* Caculate size of new SF */ 7028 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 7029 if (numRoots < 0) PetscFunctionReturn(0); 7030 for (l = 0; l < numLeaves; ++l) { 7031 const PetscInt p = localPoints[l]; 7032 7033 switch (refiner) { 7034 case 1: 7035 /* Simplicial 2D */ 7036 if ((p >= vStart) && (p < vEnd)) { 7037 /* Old vertices stay the same */ 7038 ++numLeavesNew; 7039 } else if ((p >= fStart) && (p < fEnd)) { 7040 /* Old faces add new faces and vertex */ 7041 numLeavesNew += 1 + 2; 7042 } else if ((p >= cStart) && (p < cEnd)) { 7043 /* Old cells add new cells and interior faces */ 7044 numLeavesNew += 4 + 3; 7045 } 7046 break; 7047 case 2: 7048 /* Hex 2D */ 7049 if ((p >= vStart) && (p < vEnd)) { 7050 /* Old vertices stay the same */ 7051 ++numLeavesNew; 7052 } else if ((p >= fStart) && (p < fEnd)) { 7053 /* Old faces add new faces and vertex */ 7054 numLeavesNew += 1 + 2; 7055 } else if ((p >= cStart) && (p < cEnd)) { 7056 /* Old cells add new cells and interior faces */ 7057 numLeavesNew += 4 + 4; 7058 } 7059 break; 7060 default: 7061 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7062 } 7063 } 7064 /* Communicate depthSizes for each remote rank */ 7065 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7066 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7067 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7068 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); 7069 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7070 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7071 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7072 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7073 for (n = 0; n < numNeighbors; ++n) { 7074 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7075 } 7076 depthSizeOld[depth] = cMax; 7077 depthSizeOld[0] = vMax; 7078 depthSizeOld[depth-1] = fMax; 7079 depthSizeOld[1] = eMax; 7080 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7081 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7082 depthSizeOld[depth] = cEnd - cStart; 7083 depthSizeOld[0] = vEnd - vStart; 7084 depthSizeOld[depth-1] = fEnd - fStart; 7085 depthSizeOld[1] = eEnd - eStart; 7086 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7087 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7088 for (n = 0; n < numNeighbors; ++n) { 7089 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7090 } 7091 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7092 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7093 /* Calculate new point SF */ 7094 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7095 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7096 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7097 for (l = 0, m = 0; l < numLeaves; ++l) { 7098 PetscInt p = localPoints[l]; 7099 PetscInt rp = remotePoints[l].index, n; 7100 PetscMPIInt rrank = remotePoints[l].rank; 7101 7102 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7103 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7104 switch (refiner) { 7105 case 1: 7106 /* Simplicial 2D */ 7107 if ((p >= vStart) && (p < vEnd)) { 7108 /* Old vertices stay the same */ 7109 localPointsNew[m] = vStartNew + (p - vStart); 7110 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7111 remotePointsNew[m].rank = rrank; 7112 ++m; 7113 } else if ((p >= fStart) && (p < fEnd)) { 7114 /* Old faces add new faces and vertex */ 7115 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7116 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7117 remotePointsNew[m].rank = rrank; 7118 ++m; 7119 for (r = 0; r < 2; ++r, ++m) { 7120 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7121 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7122 remotePointsNew[m].rank = rrank; 7123 } 7124 } else if ((p >= cStart) && (p < cEnd)) { 7125 /* Old cells add new cells and interior faces */ 7126 for (r = 0; r < 4; ++r, ++m) { 7127 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7128 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7129 remotePointsNew[m].rank = rrank; 7130 } 7131 for (r = 0; r < 3; ++r, ++m) { 7132 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7133 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7134 remotePointsNew[m].rank = rrank; 7135 } 7136 } 7137 break; 7138 case 2: 7139 /* Hex 2D */ 7140 if ((p >= vStart) && (p < vEnd)) { 7141 /* Old vertices stay the same */ 7142 localPointsNew[m] = vStartNew + (p - vStart); 7143 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7144 remotePointsNew[m].rank = rrank; 7145 ++m; 7146 } else if ((p >= fStart) && (p < fEnd)) { 7147 /* Old faces add new faces and vertex */ 7148 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7149 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7150 remotePointsNew[m].rank = rrank; 7151 ++m; 7152 for (r = 0; r < 2; ++r, ++m) { 7153 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7154 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7155 remotePointsNew[m].rank = rrank; 7156 } 7157 } else if ((p >= cStart) && (p < cEnd)) { 7158 /* Old cells add new cells and interior faces */ 7159 for (r = 0; r < 4; ++r, ++m) { 7160 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7161 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7162 remotePointsNew[m].rank = rrank; 7163 } 7164 for (r = 0; r < 4; ++r, ++m) { 7165 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7166 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7167 remotePointsNew[m].rank = rrank; 7168 } 7169 } 7170 break; 7171 case 3: 7172 /* Hybrid simplicial 2D */ 7173 if ((p >= vStart) && (p < vEnd)) { 7174 /* Old vertices stay the same */ 7175 localPointsNew[m] = vStartNew + (p - vStart); 7176 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7177 remotePointsNew[m].rank = rrank; 7178 ++m; 7179 } else if ((p >= fStart) && (p < fMax)) { 7180 /* Old interior faces add new faces and vertex */ 7181 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7182 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7183 remotePointsNew[m].rank = rrank; 7184 ++m; 7185 for (r = 0; r < 2; ++r, ++m) { 7186 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7187 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7188 remotePointsNew[m].rank = rrank; 7189 } 7190 } else if ((p >= fMax) && (p < fEnd)) { 7191 /* Old hybrid faces stay the same */ 7192 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7193 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7194 remotePointsNew[m].rank = rrank; 7195 ++m; 7196 } else if ((p >= cStart) && (p < cMax)) { 7197 /* Old interior cells add new cells and interior faces */ 7198 for (r = 0; r < 4; ++r, ++m) { 7199 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7200 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7201 remotePointsNew[m].rank = rrank; 7202 } 7203 for (r = 0; r < 3; ++r, ++m) { 7204 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7205 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7206 remotePointsNew[m].rank = rrank; 7207 } 7208 } else if ((p >= cStart) && (p < cMax)) { 7209 /* Old hybrid cells add new cells and hybrid face */ 7210 for (r = 0; r < 2; ++r, ++m) { 7211 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7212 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7213 remotePointsNew[m].rank = rrank; 7214 } 7215 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7216 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]); 7217 remotePointsNew[m].rank = rrank; 7218 ++m; 7219 } 7220 break; 7221 default: 7222 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7223 } 7224 } 7225 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7226 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7227 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7228 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7229 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7230 PetscFunctionReturn(0); 7231 } 7232 7233 #undef __FUNCT__ 7234 #define __FUNCT__ "CellRefinerCreateLabels" 7235 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7236 { 7237 PetscInt numLabels, l; 7238 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7239 PetscErrorCode ierr; 7240 7241 PetscFunctionBegin; 7242 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7243 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7244 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7245 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7246 cStartNew = 0; 7247 vStartNew = depthSize[2]; 7248 fStartNew = depthSize[2] + depthSize[0]; 7249 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7250 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7251 switch (refiner) { 7252 case 3: 7253 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7254 cMax = PetscMin(cEnd, cMax); 7255 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7256 fMax = PetscMin(fEnd, fMax); 7257 } 7258 for (l = 0; l < numLabels; ++l) { 7259 DMLabel label, labelNew; 7260 const char *lname; 7261 PetscBool isDepth; 7262 IS valueIS; 7263 const PetscInt *values; 7264 PetscInt numValues, val; 7265 7266 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7267 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7268 if (isDepth) continue; 7269 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7270 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7271 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7272 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7273 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7274 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7275 for (val = 0; val < numValues; ++val) { 7276 IS pointIS; 7277 const PetscInt *points; 7278 PetscInt numPoints, n; 7279 7280 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7281 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7282 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7283 for (n = 0; n < numPoints; ++n) { 7284 const PetscInt p = points[n]; 7285 switch (refiner) { 7286 case 1: 7287 /* Simplicial 2D */ 7288 if ((p >= vStart) && (p < vEnd)) { 7289 /* Old vertices stay the same */ 7290 newp = vStartNew + (p - vStart); 7291 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7292 } else if ((p >= fStart) && (p < fEnd)) { 7293 /* Old faces add new faces and vertex */ 7294 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7295 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7296 for (r = 0; r < 2; ++r) { 7297 newp = fStartNew + (p - fStart)*2 + r; 7298 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7299 } 7300 } else if ((p >= cStart) && (p < cEnd)) { 7301 /* Old cells add new cells and interior faces */ 7302 for (r = 0; r < 4; ++r) { 7303 newp = cStartNew + (p - cStart)*4 + r; 7304 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7305 } 7306 for (r = 0; r < 3; ++r) { 7307 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7308 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7309 } 7310 } 7311 break; 7312 case 2: 7313 /* Hex 2D */ 7314 if ((p >= vStart) && (p < vEnd)) { 7315 /* Old vertices stay the same */ 7316 newp = vStartNew + (p - vStart); 7317 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7318 } else if ((p >= fStart) && (p < fEnd)) { 7319 /* Old faces add new faces and vertex */ 7320 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7321 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7322 for (r = 0; r < 2; ++r) { 7323 newp = fStartNew + (p - fStart)*2 + r; 7324 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7325 } 7326 } else if ((p >= cStart) && (p < cEnd)) { 7327 /* Old cells add new cells and interior faces and vertex */ 7328 for (r = 0; r < 4; ++r) { 7329 newp = cStartNew + (p - cStart)*4 + r; 7330 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7331 } 7332 for (r = 0; r < 4; ++r) { 7333 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7334 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7335 } 7336 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7337 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7338 } 7339 break; 7340 case 3: 7341 /* Hybrid simplicial 2D */ 7342 if ((p >= vStart) && (p < vEnd)) { 7343 /* Old vertices stay the same */ 7344 newp = vStartNew + (p - vStart); 7345 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7346 } else if ((p >= fStart) && (p < fMax)) { 7347 /* Old interior faces add new faces and vertex */ 7348 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7349 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7350 for (r = 0; r < 2; ++r) { 7351 newp = fStartNew + (p - fStart)*2 + r; 7352 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7353 } 7354 } else if ((p >= fMax) && (p < fEnd)) { 7355 /* Old hybrid faces stay the same */ 7356 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7357 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7358 } else if ((p >= cStart) && (p < cMax)) { 7359 /* Old interior cells add new cells and interior faces */ 7360 for (r = 0; r < 4; ++r) { 7361 newp = cStartNew + (p - cStart)*4 + r; 7362 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7363 } 7364 for (r = 0; r < 3; ++r) { 7365 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7366 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7367 } 7368 } else if ((p >= cMax) && (p < cEnd)) { 7369 /* Old hybrid cells add new cells and hybrid face */ 7370 for (r = 0; r < 2; ++r) { 7371 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7372 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7373 } 7374 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7375 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7376 } 7377 break; 7378 default: 7379 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7380 } 7381 } 7382 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7383 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7384 } 7385 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7386 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7387 if (0) { 7388 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7389 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7390 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7391 } 7392 } 7393 PetscFunctionReturn(0); 7394 } 7395 7396 #undef __FUNCT__ 7397 #define __FUNCT__ "DMPlexRefine_Uniform" 7398 /* This will only work for interpolated meshes */ 7399 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7400 { 7401 DM rdm; 7402 PetscInt *depthSize; 7403 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7404 PetscErrorCode ierr; 7405 7406 PetscFunctionBegin; 7407 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7408 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7409 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7410 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7411 /* Calculate number of new points of each depth */ 7412 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7413 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7414 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7415 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7416 /* Step 1: Set chart */ 7417 for (d = 0; d <= depth; ++d) { 7418 pEnd += depthSize[d]; 7419 } 7420 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7421 /* Step 2: Set cone/support sizes */ 7422 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7423 /* Step 3: Setup refined DM */ 7424 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7425 /* Step 4: Set cones and supports */ 7426 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7427 /* Step 5: Stratify */ 7428 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7429 /* Step 6: Set coordinates for vertices */ 7430 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7431 /* Step 7: Create pointSF */ 7432 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7433 /* Step 8: Create labels */ 7434 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7435 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7436 7437 *dmRefined = rdm; 7438 #if 0 7439 DM_Plex *mesh = (DM_Plex *) dm->data; 7440 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 7441 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 7442 7443 PetscFunctionBegin; 7444 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7445 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 7446 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7447 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7448 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 7449 7450 /* Count number of new cells which are normal and extra */ 7451 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 7452 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 7453 for (c = cStart; c < cEnd2; ++c) { 7454 PetscInt n; 7455 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7456 newNumCellsNormal += n; 7457 } 7458 for (c = cEnd2; c < cEnd; ++c) { 7459 PetscInt n; 7460 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7461 newNumCellsExtra += n; 7462 } 7463 newNumCells = newNumCellsNormal + newNumCellsExtra; 7464 /* Count number of new vertices which are normal and extra */ 7465 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 7466 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 7467 for (c = cStart; c < cEnd; ++c) { 7468 PetscInt *closure = PETSC_NULL; 7469 PetscInt closureSize, numCorners = 0, p; 7470 7471 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7472 for (p = 0; p < closureSize*2; p += 2) { 7473 const PetscInt point = closure[p]; 7474 if ((point >= vStart) && (point < vEnd)) { 7475 closure[numCorners++] = point; 7476 } 7477 } 7478 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 7479 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7480 } 7481 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 7482 for (c = cEnd2; c < cEnd; ++c) { 7483 PetscInt *closure = PETSC_NULL; 7484 PetscInt closureSize, numCorners = 0, p; 7485 7486 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7487 for (p = 0; p < closureSize*2; p += 2) { 7488 const PetscInt point = closure[p]; 7489 if ((point >= vStart) && (point < vEnd)) { 7490 closure[numCorners++] = point; 7491 } 7492 } 7493 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 7494 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7495 } /* for */ 7496 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 7497 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 7498 7499 #if 1 7500 PetscInt oldNumCellsNormal = cEnd2 - cStart; 7501 PetscInt oldNumCellsExtra = cEnd - cEnd2; 7502 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 7503 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 7504 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 7505 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 7506 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 7507 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 7508 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 7509 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 7510 ierr = PetscSynchronizedFlush(comm); 7511 #endif 7512 7513 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 7514 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 7515 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 7516 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 7517 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 7518 /* Set cone and support sizes for new normal cells */ 7519 PetscInt newCell = 0; 7520 for (c = cStart; c < cEnd2; ++c) { 7521 PetscInt coneSize, n, i; 7522 7523 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7524 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7525 for (i = 0; i < n; ++i, ++newCell) { 7526 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 7527 } 7528 7529 PetscInt *closure = PETSC_NULL; 7530 PetscInt closureSize, numCorners = 0, p; 7531 7532 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7533 for (p = 0; p < closureSize*2; p += 2) { 7534 const PetscInt point = closure[p]; 7535 if ((point >= vStart) && (point < vEnd)) { 7536 closure[numCorners++] = point; 7537 } 7538 } 7539 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); */ /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7540 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7541 } 7542 7543 /* Reset current new cell value and loop over censored cells. */ 7544 curNewCell = _orderNewMesh->cellsCensored().min(); 7545 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7546 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7547 /* Set new cone and support sizes */ 7548 cV.clear(); 7549 sieve->cone(*c_iter, cV); 7550 const point_type* cone = cV.getPoints(); 7551 const int coneSize = cV.getSize(); 7552 7553 const point_type* newCells; 7554 int numNewCells = 0; 7555 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7556 7557 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7558 newSieve->setConeSize(curNewCell, coneSize); 7559 for (int iVertex=0; iVertex < coneSize; ++iVertex) { 7560 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7561 } /* for */ 7562 } /* for */ 7563 } /* for */ 7564 newSieve->allocate(); 7565 7566 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7567 7568 /* Create refined cells in new sieve. */ 7569 curNewCell = _orderNewMesh->cellsNormal().min(); 7570 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7571 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7572 cV.clear(); 7573 sieve->cone(*c_iter, cV); 7574 const point_type *cone = cV.getPoints(); 7575 const int coneSize = cV.getSize(); 7576 7577 const point_type* newCells; 7578 int numNewCells = 0; 7579 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7580 7581 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7582 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7583 } /* for */ 7584 } /* for */ 7585 curNewCell = _orderNewMesh->cellsCensored().min(); 7586 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7587 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7588 cV.clear(); 7589 sieve->cone(*c_iter, cV); 7590 const point_type *cone = cV.getPoints(); 7591 const int coneSize = cV.getSize(); 7592 7593 const point_type* newCells; 7594 int numNewCells = 0; 7595 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7596 7597 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7598 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7599 } /* for */ 7600 } /* for */ 7601 newSieve->symmetrize(); 7602 7603 /* Set coordinates in refined mesh. */ 7604 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7605 assert(!coordinates.isNull()); 7606 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7607 assert(!newCoordinates.isNull()); 7608 7609 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7610 assert(vertices->size() > 0); 7611 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7612 assert(spaceDim > 0); 7613 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7614 7615 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7616 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7617 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7618 } /* for */ 7619 newCoordinates->allocatePoint(); 7620 7621 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7622 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7623 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7624 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7625 } /* for */ 7626 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7627 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7628 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7629 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7630 } /* for */ 7631 7632 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7633 7634 /* Create sensored depth */ 7635 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7636 assert(!censoredLabel.isNull()); 7637 7638 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7639 7640 newSieve->roots(depthVisitor); 7641 while (depthVisitor.isModified()) { 7642 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7643 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7644 7645 depthVisitor.clear(); 7646 newSieve->support(modifiedPoints, depthVisitor); 7647 } /* while */ 7648 /* Stratify refined mesh */ 7649 /* Calculate new point SF */ 7650 _calcNewOverlap(newMesh, mesh, refiner); 7651 /* Calculate new labels */ 7652 _createLabels(newMesh, mesh, refiner); 7653 #endif 7654 PetscFunctionReturn(0); 7655 } 7656 7657 #undef __FUNCT__ 7658 #define __FUNCT__ "DMPlexSetRefinementUniform" 7659 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7660 { 7661 DM_Plex *mesh = (DM_Plex *) dm->data; 7662 7663 PetscFunctionBegin; 7664 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7665 mesh->refinementUniform = refinementUniform; 7666 PetscFunctionReturn(0); 7667 } 7668 7669 #undef __FUNCT__ 7670 #define __FUNCT__ "DMPlexGetRefinementUniform" 7671 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7672 { 7673 DM_Plex *mesh = (DM_Plex *) dm->data; 7674 7675 PetscFunctionBegin; 7676 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7677 PetscValidPointer(refinementUniform, 2); 7678 *refinementUniform = mesh->refinementUniform; 7679 PetscFunctionReturn(0); 7680 } 7681 7682 #undef __FUNCT__ 7683 #define __FUNCT__ "DMPlexSetRefinementLimit" 7684 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7685 { 7686 DM_Plex *mesh = (DM_Plex *) dm->data; 7687 7688 PetscFunctionBegin; 7689 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7690 mesh->refinementLimit = refinementLimit; 7691 PetscFunctionReturn(0); 7692 } 7693 7694 #undef __FUNCT__ 7695 #define __FUNCT__ "DMPlexGetRefinementLimit" 7696 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7697 { 7698 DM_Plex *mesh = (DM_Plex *) dm->data; 7699 7700 PetscFunctionBegin; 7701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7702 PetscValidPointer(refinementLimit, 2); 7703 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7704 *refinementLimit = mesh->refinementLimit; 7705 PetscFunctionReturn(0); 7706 } 7707 7708 #undef __FUNCT__ 7709 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7710 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7711 { 7712 PetscInt dim, cStart, coneSize, cMax; 7713 PetscErrorCode ierr; 7714 7715 PetscFunctionBegin; 7716 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7717 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7718 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7719 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7720 switch (dim) { 7721 case 2: 7722 switch (coneSize) { 7723 case 3: 7724 if (cMax >= 0) { 7725 *cellRefiner = 3; /* Hybrid */ 7726 } else { 7727 *cellRefiner = 1; /* Triangular */ 7728 } 7729 break; 7730 case 4: 7731 if (cMax >= 0) { 7732 *cellRefiner = 4; /* Hybrid */ 7733 } else { 7734 *cellRefiner = 2; /* Quadrilateral */ 7735 } 7736 break; 7737 default: 7738 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7739 } 7740 break; 7741 default: 7742 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7743 } 7744 PetscFunctionReturn(0); 7745 } 7746 7747 #undef __FUNCT__ 7748 #define __FUNCT__ "DMRefine_Plex" 7749 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7750 { 7751 PetscReal refinementLimit; 7752 PetscInt dim, cStart, cEnd; 7753 char genname[1024], *name = PETSC_NULL; 7754 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7755 PetscErrorCode ierr; 7756 7757 PetscFunctionBegin; 7758 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7759 if (isUniform) { 7760 CellRefiner cellRefiner; 7761 7762 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7763 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7764 PetscFunctionReturn(0); 7765 } 7766 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7767 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7768 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7769 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7770 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7771 if (flg) {name = genname;} 7772 if (name) { 7773 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7774 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7775 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7776 } 7777 switch (dim) { 7778 case 2: 7779 if (!name || isTriangle) { 7780 #if defined(PETSC_HAVE_TRIANGLE) 7781 double *maxVolumes; 7782 PetscInt c; 7783 7784 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7785 for (c = 0; c < cEnd-cStart; ++c) { 7786 maxVolumes[c] = refinementLimit; 7787 } 7788 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7789 #else 7790 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7791 #endif 7792 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7793 break; 7794 case 3: 7795 if (!name || isCTetgen) { 7796 #if defined(PETSC_HAVE_CTETGEN) 7797 PetscReal *maxVolumes; 7798 PetscInt c; 7799 7800 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7801 for (c = 0; c < cEnd-cStart; ++c) { 7802 maxVolumes[c] = refinementLimit; 7803 } 7804 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7805 #else 7806 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7807 #endif 7808 } else if (isTetgen) { 7809 #if defined(PETSC_HAVE_TETGEN) 7810 double *maxVolumes; 7811 PetscInt c; 7812 7813 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7814 for (c = 0; c < cEnd-cStart; ++c) { 7815 maxVolumes[c] = refinementLimit; 7816 } 7817 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7818 #else 7819 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7820 #endif 7821 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7822 break; 7823 default: 7824 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7825 } 7826 PetscFunctionReturn(0); 7827 } 7828 7829 #undef __FUNCT__ 7830 #define __FUNCT__ "DMPlexGetDepth" 7831 /*@ 7832 DMPlexGetDepth - get the number of strata 7833 7834 Not Collective 7835 7836 Input Parameters: 7837 . dm - The DMPlex object 7838 7839 Output Parameters: 7840 . depth - number of strata 7841 7842 Level: developer 7843 7844 Notes: 7845 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7846 7847 .keywords: mesh, points 7848 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7849 @*/ 7850 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7851 { 7852 PetscInt d; 7853 PetscErrorCode ierr; 7854 7855 PetscFunctionBegin; 7856 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7857 PetscValidPointer(depth, 2); 7858 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7859 *depth = d-1; 7860 PetscFunctionReturn(0); 7861 } 7862 7863 #undef __FUNCT__ 7864 #define __FUNCT__ "DMPlexGetDepthStratum" 7865 /*@ 7866 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7867 7868 Not Collective 7869 7870 Input Parameters: 7871 + dm - The DMPlex object 7872 - stratumValue - The requested depth 7873 7874 Output Parameters: 7875 + start - The first point at this depth 7876 - end - One beyond the last point at this depth 7877 7878 Level: developer 7879 7880 .keywords: mesh, points 7881 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7882 @*/ 7883 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7884 { 7885 DM_Plex *mesh = (DM_Plex *) dm->data; 7886 DMLabel next = mesh->labels; 7887 PetscBool flg = PETSC_FALSE; 7888 PetscInt depth; 7889 PetscErrorCode ierr; 7890 7891 PetscFunctionBegin; 7892 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7893 if (stratumValue < 0) { 7894 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7895 PetscFunctionReturn(0); 7896 } else { 7897 PetscInt pStart, pEnd; 7898 7899 if (start) {*start = 0;} 7900 if (end) {*end = 0;} 7901 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7902 if (pStart == pEnd) {PetscFunctionReturn(0);} 7903 } 7904 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7905 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7906 /* We should have a generic GetLabel() and a Label class */ 7907 while (next) { 7908 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7909 if (flg) break; 7910 next = next->next; 7911 } 7912 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7913 depth = stratumValue; 7914 if ((depth < 0) || (depth >= next->numStrata)) { 7915 if (start) {*start = 0;} 7916 if (end) {*end = 0;} 7917 } else { 7918 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7919 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7920 } 7921 PetscFunctionReturn(0); 7922 } 7923 7924 #undef __FUNCT__ 7925 #define __FUNCT__ "DMPlexGetHeightStratum" 7926 /*@ 7927 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7928 7929 Not Collective 7930 7931 Input Parameters: 7932 + dm - The DMPlex object 7933 - stratumValue - The requested height 7934 7935 Output Parameters: 7936 + start - The first point at this height 7937 - end - One beyond the last point at this height 7938 7939 Level: developer 7940 7941 .keywords: mesh, points 7942 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7943 @*/ 7944 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7945 { 7946 DM_Plex *mesh = (DM_Plex *) dm->data; 7947 DMLabel next = mesh->labels; 7948 PetscBool flg = PETSC_FALSE; 7949 PetscInt depth; 7950 PetscErrorCode ierr; 7951 7952 PetscFunctionBegin; 7953 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7954 if (stratumValue < 0) { 7955 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7956 } else { 7957 PetscInt pStart, pEnd; 7958 7959 if (start) {*start = 0;} 7960 if (end) {*end = 0;} 7961 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7962 if (pStart == pEnd) {PetscFunctionReturn(0);} 7963 } 7964 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7965 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7966 /* We should have a generic GetLabel() and a Label class */ 7967 while (next) { 7968 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7969 if (flg) break; 7970 next = next->next; 7971 } 7972 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7973 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7974 if ((depth < 0) || (depth >= next->numStrata)) { 7975 if (start) {*start = 0;} 7976 if (end) {*end = 0;} 7977 } else { 7978 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7979 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7980 } 7981 PetscFunctionReturn(0); 7982 } 7983 7984 #undef __FUNCT__ 7985 #define __FUNCT__ "DMPlexCreateSectionInitial" 7986 /* Set the number of dof on each point and separate by fields */ 7987 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7988 { 7989 PetscInt *numDofTot; 7990 PetscInt pStart = 0, pEnd = 0; 7991 PetscInt p, d, f; 7992 PetscErrorCode ierr; 7993 7994 PetscFunctionBegin; 7995 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7996 for (d = 0; d <= dim; ++d) { 7997 numDofTot[d] = 0; 7998 for (f = 0; f < numFields; ++f) { 7999 numDofTot[d] += numDof[f*(dim+1)+d]; 8000 } 8001 } 8002 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 8003 if (numFields > 0) { 8004 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 8005 if (numComp) { 8006 for (f = 0; f < numFields; ++f) { 8007 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 8008 } 8009 } 8010 } 8011 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8012 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 8013 for (d = 0; d <= dim; ++d) { 8014 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 8015 for (p = pStart; p < pEnd; ++p) { 8016 for (f = 0; f < numFields; ++f) { 8017 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 8018 } 8019 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 8020 } 8021 } 8022 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 8023 PetscFunctionReturn(0); 8024 } 8025 8026 #undef __FUNCT__ 8027 #define __FUNCT__ "DMPlexCreateSectionBCDof" 8028 /* Set the number of dof on each point and separate by fields 8029 If constDof is PETSC_DETERMINE, constrain every dof on the point 8030 */ 8031 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 8032 { 8033 PetscInt numFields; 8034 PetscInt bc; 8035 PetscErrorCode ierr; 8036 8037 PetscFunctionBegin; 8038 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8039 for (bc = 0; bc < numBC; ++bc) { 8040 PetscInt field = 0; 8041 const PetscInt *idx; 8042 PetscInt n, i; 8043 8044 if (numFields) {field = bcField[bc];} 8045 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 8046 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8047 for (i = 0; i < n; ++i) { 8048 const PetscInt p = idx[i]; 8049 PetscInt numConst = constDof; 8050 8051 /* Constrain every dof on the point */ 8052 if (numConst < 0) { 8053 if (numFields) { 8054 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 8055 } else { 8056 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 8057 } 8058 } 8059 if (numFields) { 8060 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 8061 } 8062 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 8063 } 8064 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8065 } 8066 PetscFunctionReturn(0); 8067 } 8068 8069 #undef __FUNCT__ 8070 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 8071 /* Set the constrained indices on each point and separate by fields */ 8072 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 8073 { 8074 PetscInt *maxConstraints; 8075 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 8076 PetscErrorCode ierr; 8077 8078 PetscFunctionBegin; 8079 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8080 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8081 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 8082 for (f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 8083 for (p = pStart; p < pEnd; ++p) { 8084 PetscInt cdof; 8085 8086 if (numFields) { 8087 for (f = 0; f < numFields; ++f) { 8088 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 8089 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 8090 } 8091 } else { 8092 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8093 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 8094 } 8095 } 8096 for (f = 0; f < numFields; ++f) { 8097 maxConstraints[numFields] += maxConstraints[f]; 8098 } 8099 if (maxConstraints[numFields]) { 8100 PetscInt *indices; 8101 8102 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8103 for (p = pStart; p < pEnd; ++p) { 8104 PetscInt cdof, d; 8105 8106 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8107 if (cdof) { 8108 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 8109 if (numFields) { 8110 PetscInt numConst = 0, foff = 0; 8111 8112 for (f = 0; f < numFields; ++f) { 8113 PetscInt cfdof, fdof; 8114 8115 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8116 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 8117 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 8118 for (d = 0; d < cfdof; ++d) { 8119 indices[numConst+d] = d; 8120 } 8121 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 8122 for (d = 0; d < cfdof; ++d) { 8123 indices[numConst+d] += foff; 8124 } 8125 numConst += cfdof; 8126 foff += fdof; 8127 } 8128 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8129 } else { 8130 for (d = 0; d < cdof; ++d) { 8131 indices[d] = d; 8132 } 8133 } 8134 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8135 } 8136 } 8137 ierr = PetscFree(indices);CHKERRQ(ierr); 8138 } 8139 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 8140 PetscFunctionReturn(0); 8141 } 8142 8143 #undef __FUNCT__ 8144 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 8145 /* Set the constrained field indices on each point */ 8146 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 8147 { 8148 const PetscInt *points, *indices; 8149 PetscInt numFields, maxDof, numPoints, p, numConstraints; 8150 PetscErrorCode ierr; 8151 8152 PetscFunctionBegin; 8153 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8154 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 8155 8156 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 8157 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 8158 if (!constraintIndices) { 8159 PetscInt *idx, i; 8160 8161 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8162 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 8163 for (i = 0; i < maxDof; ++i) {idx[i] = i;} 8164 for (p = 0; p < numPoints; ++p) { 8165 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 8166 } 8167 ierr = PetscFree(idx);CHKERRQ(ierr); 8168 } else { 8169 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 8170 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 8171 for (p = 0; p < numPoints; ++p) { 8172 PetscInt fcdof; 8173 8174 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 8175 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); 8176 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 8177 } 8178 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 8179 } 8180 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 8181 PetscFunctionReturn(0); 8182 } 8183 8184 #undef __FUNCT__ 8185 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 8186 /* Set the constrained indices on each point and separate by fields */ 8187 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 8188 { 8189 PetscInt *indices; 8190 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 8191 PetscErrorCode ierr; 8192 8193 PetscFunctionBegin; 8194 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8195 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8196 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8197 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 8198 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8199 for (p = pStart; p < pEnd; ++p) { 8200 PetscInt cdof, d; 8201 8202 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8203 if (cdof) { 8204 PetscInt numConst = 0, foff = 0; 8205 8206 for (f = 0; f < numFields; ++f) { 8207 const PetscInt *fcind; 8208 PetscInt fdof, fcdof; 8209 8210 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8211 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8212 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 8213 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8214 for (d = 0; d < fcdof; ++d) { 8215 indices[numConst+d] = fcind[d]+foff; 8216 } 8217 foff += fdof; 8218 numConst += fcdof; 8219 } 8220 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8221 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8222 } 8223 } 8224 ierr = PetscFree(indices);CHKERRQ(ierr); 8225 PetscFunctionReturn(0); 8226 } 8227 8228 #undef __FUNCT__ 8229 #define __FUNCT__ "DMPlexCreateSection" 8230 /*@C 8231 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8232 8233 Not Collective 8234 8235 Input Parameters: 8236 + dm - The DMPlex object 8237 . dim - The spatial dimension of the problem 8238 . numFields - The number of fields in the problem 8239 . numComp - An array of size numFields that holds the number of components for each field 8240 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8241 . numBC - The number of boundary conditions 8242 . bcField - An array of size numBC giving the field number for each boundry condition 8243 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8244 8245 Output Parameter: 8246 . section - The PetscSection object 8247 8248 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 8249 nubmer of dof for field 0 on each edge. 8250 8251 Level: developer 8252 8253 .keywords: mesh, elements 8254 .seealso: DMPlexCreate(), PetscSectionCreate() 8255 @*/ 8256 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8257 { 8258 PetscErrorCode ierr; 8259 8260 PetscFunctionBegin; 8261 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8262 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8263 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8264 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8265 { 8266 PetscBool view = PETSC_FALSE; 8267 8268 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8269 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8270 } 8271 PetscFunctionReturn(0); 8272 } 8273 8274 #undef __FUNCT__ 8275 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8276 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8277 { 8278 PetscSection section; 8279 PetscErrorCode ierr; 8280 8281 PetscFunctionBegin; 8282 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8283 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8284 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8285 PetscFunctionReturn(0); 8286 } 8287 8288 #undef __FUNCT__ 8289 #define __FUNCT__ "DMPlexGetCoordinateSection" 8290 /*@ 8291 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8292 8293 Not Collective 8294 8295 Input Parameter: 8296 . dm - The DMPlex object 8297 8298 Output Parameter: 8299 . section - The PetscSection object 8300 8301 Level: intermediate 8302 8303 .keywords: mesh, coordinates 8304 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8305 @*/ 8306 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8307 { 8308 DM cdm; 8309 PetscErrorCode ierr; 8310 8311 PetscFunctionBegin; 8312 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8313 PetscValidPointer(section, 2); 8314 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8315 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8316 PetscFunctionReturn(0); 8317 } 8318 8319 #undef __FUNCT__ 8320 #define __FUNCT__ "DMPlexSetCoordinateSection" 8321 /*@ 8322 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8323 8324 Not Collective 8325 8326 Input Parameters: 8327 + dm - The DMPlex object 8328 - section - The PetscSection object 8329 8330 Level: intermediate 8331 8332 .keywords: mesh, coordinates 8333 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8334 @*/ 8335 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8336 { 8337 DM cdm; 8338 PetscErrorCode ierr; 8339 8340 PetscFunctionBegin; 8341 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8342 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8343 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8344 PetscFunctionReturn(0); 8345 } 8346 8347 #undef __FUNCT__ 8348 #define __FUNCT__ "DMPlexGetConeSection" 8349 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8350 { 8351 DM_Plex *mesh = (DM_Plex *) dm->data; 8352 8353 PetscFunctionBegin; 8354 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8355 if (section) *section = mesh->coneSection; 8356 PetscFunctionReturn(0); 8357 } 8358 8359 #undef __FUNCT__ 8360 #define __FUNCT__ "DMPlexGetCones" 8361 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8362 { 8363 DM_Plex *mesh = (DM_Plex *) dm->data; 8364 8365 PetscFunctionBegin; 8366 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8367 if (cones) *cones = mesh->cones; 8368 PetscFunctionReturn(0); 8369 } 8370 8371 #undef __FUNCT__ 8372 #define __FUNCT__ "DMPlexGetConeOrientations" 8373 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8374 { 8375 DM_Plex *mesh = (DM_Plex *) dm->data; 8376 8377 PetscFunctionBegin; 8378 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8379 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8380 PetscFunctionReturn(0); 8381 } 8382 8383 #undef __FUNCT__ 8384 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8385 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8386 { 8387 const PetscInt embedDim = 2; 8388 PetscReal x = PetscRealPart(point[0]); 8389 PetscReal y = PetscRealPart(point[1]); 8390 PetscReal v0[2], J[4], invJ[4], detJ; 8391 PetscReal xi, eta; 8392 PetscErrorCode ierr; 8393 8394 PetscFunctionBegin; 8395 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8396 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8397 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8398 8399 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 8400 *cell = c; 8401 } else { 8402 *cell = -1; 8403 } 8404 PetscFunctionReturn(0); 8405 } 8406 8407 #undef __FUNCT__ 8408 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8409 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8410 { 8411 PetscSection coordSection; 8412 Vec coordsLocal; 8413 const PetscScalar *coords; 8414 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8415 PetscReal x = PetscRealPart(point[0]); 8416 PetscReal y = PetscRealPart(point[1]); 8417 PetscInt crossings = 0, f; 8418 PetscErrorCode ierr; 8419 8420 PetscFunctionBegin; 8421 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8422 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8423 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8424 for (f = 0; f < 4; ++f) { 8425 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8426 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8427 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8428 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8429 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8430 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8431 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8432 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8433 if ((cond1 || cond2) && above) ++crossings; 8434 } 8435 if (crossings % 2) { 8436 *cell = c; 8437 } else { 8438 *cell = -1; 8439 } 8440 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8441 PetscFunctionReturn(0); 8442 } 8443 8444 #undef __FUNCT__ 8445 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8446 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8447 { 8448 const PetscInt embedDim = 3; 8449 PetscReal v0[3], J[9], invJ[9], detJ; 8450 PetscReal x = PetscRealPart(point[0]); 8451 PetscReal y = PetscRealPart(point[1]); 8452 PetscReal z = PetscRealPart(point[2]); 8453 PetscReal xi, eta, zeta; 8454 PetscErrorCode ierr; 8455 8456 PetscFunctionBegin; 8457 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8458 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8459 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8460 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8461 8462 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 8463 *cell = c; 8464 } else { 8465 *cell = -1; 8466 } 8467 PetscFunctionReturn(0); 8468 } 8469 8470 #undef __FUNCT__ 8471 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8472 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8473 { 8474 PetscSection coordSection; 8475 Vec coordsLocal; 8476 const PetscScalar *coords; 8477 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8478 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8479 PetscBool found = PETSC_TRUE; 8480 PetscInt f; 8481 PetscErrorCode ierr; 8482 8483 PetscFunctionBegin; 8484 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8485 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8486 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8487 for (f = 0; f < 6; ++f) { 8488 /* Check the point is under plane */ 8489 /* Get face normal */ 8490 PetscReal v_i[3]; 8491 PetscReal v_j[3]; 8492 PetscReal normal[3]; 8493 PetscReal pp[3]; 8494 PetscReal dot; 8495 8496 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 8497 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 8498 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 8499 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 8500 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 8501 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 8502 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 8503 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 8504 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 8505 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 8506 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 8507 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 8508 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8509 8510 /* Check that projected point is in face (2D location problem) */ 8511 if (dot < 0.0) { 8512 found = PETSC_FALSE; 8513 break; 8514 } 8515 } 8516 if (found) { 8517 *cell = c; 8518 } else { 8519 *cell = -1; 8520 } 8521 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8522 PetscFunctionReturn(0); 8523 } 8524 8525 #undef __FUNCT__ 8526 #define __FUNCT__ "DMLocatePoints_Plex" 8527 /* 8528 Need to implement using the guess 8529 */ 8530 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8531 { 8532 PetscInt cell = -1/*, guess = -1*/; 8533 PetscInt bs, numPoints, p; 8534 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8535 PetscInt *cells; 8536 PetscScalar *a; 8537 PetscErrorCode ierr; 8538 8539 PetscFunctionBegin; 8540 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8541 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8542 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8543 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 8544 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8545 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8546 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8547 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); 8548 numPoints /= bs; 8549 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8550 for (p = 0; p < numPoints; ++p) { 8551 const PetscScalar *point = &a[p*bs]; 8552 8553 switch (dim) { 8554 case 2: 8555 for (c = cStart; c < cEnd; ++c) { 8556 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8557 switch (coneSize) { 8558 case 3: 8559 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8560 break; 8561 case 4: 8562 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8563 break; 8564 default: 8565 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8566 } 8567 if (cell >= 0) break; 8568 } 8569 break; 8570 case 3: 8571 for (c = cStart; c < cEnd; ++c) { 8572 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8573 switch (coneSize) { 8574 case 4: 8575 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8576 break; 8577 case 8: 8578 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8579 break; 8580 default: 8581 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8582 } 8583 if (cell >= 0) break; 8584 } 8585 break; 8586 default: 8587 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8588 } 8589 cells[p] = cell; 8590 } 8591 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8592 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8593 PetscFunctionReturn(0); 8594 } 8595 8596 /******************************** FEM Support **********************************/ 8597 8598 #undef __FUNCT__ 8599 #define __FUNCT__ "DMPlexVecGetClosure" 8600 /*@C 8601 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8602 8603 Not collective 8604 8605 Input Parameters: 8606 + dm - The DM 8607 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8608 . v - The local vector 8609 - point - The sieve point in the DM 8610 8611 Output Parameters: 8612 + csize - The number of values in the closure, or PETSC_NULL 8613 - values - The array of values, which is a borrowed array and should not be freed 8614 8615 Level: intermediate 8616 8617 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8618 @*/ 8619 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8620 { 8621 PetscScalar *array, *vArray; 8622 PetscInt *points = PETSC_NULL; 8623 PetscInt offsets[32]; 8624 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8625 PetscErrorCode ierr; 8626 8627 PetscFunctionBegin; 8628 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8629 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8630 if (!section) { 8631 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8632 } 8633 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8634 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8635 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8636 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8637 /* Compress out points not in the section */ 8638 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8639 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8640 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8641 points[q*2] = points[p]; 8642 points[q*2+1] = points[p+1]; 8643 ++q; 8644 } 8645 } 8646 numPoints = q; 8647 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8648 PetscInt dof, fdof; 8649 8650 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8651 for (f = 0; f < numFields; ++f) { 8652 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8653 offsets[f+1] += fdof; 8654 } 8655 size += dof; 8656 } 8657 for (f = 1; f < numFields; ++f) { 8658 offsets[f+1] += offsets[f]; 8659 } 8660 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8661 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8662 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8663 for (p = 0; p < numPoints*2; p += 2) { 8664 PetscInt o = points[p+1]; 8665 PetscInt dof, off, d; 8666 PetscScalar *varr; 8667 8668 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8669 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8670 varr = &vArray[off]; 8671 if (numFields) { 8672 PetscInt fdof, foff, fcomp, f, c; 8673 8674 for (f = 0, foff = 0; f < numFields; ++f) { 8675 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8676 if (o >= 0) { 8677 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8678 array[offsets[f]] = varr[foff+d]; 8679 } 8680 } else { 8681 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8682 for (d = fdof/fcomp-1; d >= 0; --d) { 8683 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8684 array[offsets[f]] = varr[foff+d*fcomp+c]; 8685 } 8686 } 8687 } 8688 foff += fdof; 8689 } 8690 } else { 8691 if (o >= 0) { 8692 for (d = 0; d < dof; ++d, ++offsets[0]) { 8693 array[offsets[0]] = varr[d]; 8694 } 8695 } else { 8696 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8697 array[offsets[0]] = varr[d]; 8698 } 8699 } 8700 } 8701 } 8702 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8703 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8704 if (csize) *csize = size; 8705 *values = array; 8706 PetscFunctionReturn(0); 8707 } 8708 8709 #undef __FUNCT__ 8710 #define __FUNCT__ "DMPlexVecRestoreClosure" 8711 /*@C 8712 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8713 8714 Not collective 8715 8716 Input Parameters: 8717 + dm - The DM 8718 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8719 . v - The local vector 8720 . point - The sieve point in the DM 8721 . csize - The number of values in the closure, or PETSC_NULL 8722 - values - The array of values, which is a borrowed array and should not be freed 8723 8724 Level: intermediate 8725 8726 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8727 @*/ 8728 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8729 { 8730 PetscInt size = 0; 8731 PetscErrorCode ierr; 8732 8733 PetscFunctionBegin; 8734 /* Should work without recalculating size */ 8735 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 8736 PetscFunctionReturn(0); 8737 } 8738 8739 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8740 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8741 8742 #undef __FUNCT__ 8743 #define __FUNCT__ "updatePoint_private" 8744 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8745 { 8746 PetscInt cdof; /* The number of constraints on this point */ 8747 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8748 PetscScalar *a; 8749 PetscInt off, cind = 0, k; 8750 PetscErrorCode ierr; 8751 8752 PetscFunctionBegin; 8753 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8754 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8755 a = &array[off]; 8756 if (!cdof || setBC) { 8757 if (orientation >= 0) { 8758 for (k = 0; k < dof; ++k) { 8759 fuse(&a[k], values[k]); 8760 } 8761 } else { 8762 for (k = 0; k < dof; ++k) { 8763 fuse(&a[k], values[dof-k-1]); 8764 } 8765 } 8766 } else { 8767 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8768 if (orientation >= 0) { 8769 for (k = 0; k < dof; ++k) { 8770 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8771 fuse(&a[k], values[k]); 8772 } 8773 } else { 8774 for (k = 0; k < dof; ++k) { 8775 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8776 fuse(&a[k], values[dof-k-1]); 8777 } 8778 } 8779 } 8780 PetscFunctionReturn(0); 8781 } 8782 8783 #undef __FUNCT__ 8784 #define __FUNCT__ "updatePointFields_private" 8785 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8786 { 8787 PetscScalar *a; 8788 PetscInt numFields, off, foff, f; 8789 PetscErrorCode ierr; 8790 8791 PetscFunctionBegin; 8792 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8793 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8794 a = &array[off]; 8795 for (f = 0, foff = 0; f < numFields; ++f) { 8796 PetscInt fdof, fcomp, fcdof; 8797 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8798 PetscInt cind = 0, k, c; 8799 8800 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8801 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8802 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8803 if (!fcdof || setBC) { 8804 if (orientation >= 0) { 8805 for (k = 0; k < fdof; ++k) { 8806 fuse(&a[foff+k], values[foffs[f]+k]); 8807 } 8808 } else { 8809 for (k = fdof/fcomp-1; k >= 0; --k) { 8810 for (c = 0; c < fcomp; ++c) { 8811 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8812 } 8813 } 8814 } 8815 } else { 8816 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8817 if (orientation >= 0) { 8818 for (k = 0; k < fdof; ++k) { 8819 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8820 fuse(&a[foff+k], values[foffs[f]+k]); 8821 } 8822 } else { 8823 for (k = fdof/fcomp-1; k >= 0; --k) { 8824 for (c = 0; c < fcomp; ++c) { 8825 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8826 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8827 } 8828 } 8829 } 8830 } 8831 foff += fdof; 8832 foffs[f] += fdof; 8833 } 8834 PetscFunctionReturn(0); 8835 } 8836 8837 #undef __FUNCT__ 8838 #define __FUNCT__ "DMPlexVecSetClosure" 8839 /*@C 8840 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8841 8842 Not collective 8843 8844 Input Parameters: 8845 + dm - The DM 8846 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8847 . v - The local vector 8848 . point - The sieve point in the DM 8849 . values - The array of values, which is a borrowed array and should not be freed 8850 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8851 8852 Level: intermediate 8853 8854 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8855 @*/ 8856 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8857 { 8858 PetscScalar *array; 8859 PetscInt *points = PETSC_NULL; 8860 PetscInt offsets[32]; 8861 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8862 PetscErrorCode ierr; 8863 8864 PetscFunctionBegin; 8865 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8866 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8867 if (!section) { 8868 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8869 } 8870 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8871 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8872 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8873 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8874 /* Compress out points not in the section */ 8875 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8876 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8877 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8878 points[q*2] = points[p]; 8879 points[q*2+1] = points[p+1]; 8880 ++q; 8881 } 8882 } 8883 numPoints = q; 8884 for (p = 0; p < numPoints*2; p += 2) { 8885 PetscInt fdof; 8886 8887 for (f = 0; f < numFields; ++f) { 8888 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8889 offsets[f+1] += fdof; 8890 } 8891 } 8892 for (f = 1; f < numFields; ++f) { 8893 offsets[f+1] += offsets[f]; 8894 } 8895 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8896 if (numFields) { 8897 switch (mode) { 8898 case INSERT_VALUES: 8899 for (p = 0; p < numPoints*2; p += 2) { 8900 PetscInt o = points[p+1]; 8901 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8902 } break; 8903 case INSERT_ALL_VALUES: 8904 for (p = 0; p < numPoints*2; p += 2) { 8905 PetscInt o = points[p+1]; 8906 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8907 } break; 8908 case ADD_VALUES: 8909 for (p = 0; p < numPoints*2; p += 2) { 8910 PetscInt o = points[p+1]; 8911 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8912 } break; 8913 case ADD_ALL_VALUES: 8914 for (p = 0; p < numPoints*2; p += 2) { 8915 PetscInt o = points[p+1]; 8916 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8917 } break; 8918 default: 8919 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8920 } 8921 } else { 8922 switch (mode) { 8923 case INSERT_VALUES: 8924 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8925 PetscInt o = points[p+1]; 8926 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8927 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8928 } break; 8929 case INSERT_ALL_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_TRUE, o, &values[off], array); 8934 } break; 8935 case ADD_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, add, PETSC_FALSE, o, &values[off], array); 8940 } break; 8941 case ADD_ALL_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_TRUE, o, &values[off], array); 8946 } break; 8947 default: 8948 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8949 } 8950 } 8951 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8952 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8953 PetscFunctionReturn(0); 8954 } 8955 8956 #undef __FUNCT__ 8957 #define __FUNCT__ "DMPlexPrintMatSetValues" 8958 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8959 { 8960 PetscMPIInt rank; 8961 PetscInt i, j; 8962 PetscErrorCode ierr; 8963 8964 PetscFunctionBegin; 8965 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8966 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8967 for (i = 0; i < numIndices; i++) { 8968 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8969 } 8970 for (i = 0; i < numIndices; i++) { 8971 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8972 for (j = 0; j < numIndices; j++) { 8973 #if defined(PETSC_USE_COMPLEX) 8974 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8975 #else 8976 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8977 #endif 8978 } 8979 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8980 } 8981 PetscFunctionReturn(0); 8982 } 8983 8984 #undef __FUNCT__ 8985 #define __FUNCT__ "indicesPoint_private" 8986 /* . off - The global offset of this point */ 8987 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8988 { 8989 PetscInt cdof; /* The number of constraints on this point */ 8990 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8991 PetscInt cind = 0, k; 8992 PetscErrorCode ierr; 8993 8994 PetscFunctionBegin; 8995 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8996 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8997 if (!cdof || setBC) { 8998 if (orientation >= 0) { 8999 for (k = 0; k < dof; ++k) { 9000 indices[k] = off+k; 9001 } 9002 } else { 9003 for (k = 0; k < dof; ++k) { 9004 indices[dof-k-1] = off+k; 9005 } 9006 } 9007 } else { 9008 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 9009 if (orientation >= 0) { 9010 for (k = 0; k < dof; ++k) { 9011 if ((cind < cdof) && (k == cdofs[cind])) { 9012 /* Insert check for returning constrained indices */ 9013 indices[k] = -(off+k+1); 9014 ++cind; 9015 } else { 9016 indices[k] = off+k-cind; 9017 } 9018 } 9019 } else { 9020 for (k = 0; k < dof; ++k) { 9021 if ((cind < cdof) && (k == cdofs[cind])) { 9022 /* Insert check for returning constrained indices */ 9023 indices[dof-k-1] = -(off+k+1); 9024 ++cind; 9025 } else { 9026 indices[dof-k-1] = off+k-cind; 9027 } 9028 } 9029 } 9030 } 9031 PetscFunctionReturn(0); 9032 } 9033 9034 #undef __FUNCT__ 9035 #define __FUNCT__ "indicesPointFields_private" 9036 /* . off - The global offset of this point */ 9037 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 9038 { 9039 PetscInt numFields, foff, f; 9040 PetscErrorCode ierr; 9041 9042 PetscFunctionBegin; 9043 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9044 for (f = 0, foff = 0; f < numFields; ++f) { 9045 PetscInt fdof, fcomp, cfdof; 9046 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 9047 PetscInt cind = 0, k, c; 9048 9049 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 9050 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 9051 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 9052 if (!cfdof || setBC) { 9053 if (orientation >= 0) { 9054 for (k = 0; k < fdof; ++k) { 9055 indices[foffs[f]+k] = off+foff+k; 9056 } 9057 } else { 9058 for (k = fdof/fcomp-1; k >= 0; --k) { 9059 for (c = 0; c < fcomp; ++c) { 9060 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 9061 } 9062 } 9063 } 9064 } else { 9065 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 9066 if (orientation >= 0) { 9067 for (k = 0; k < fdof; ++k) { 9068 if ((cind < cfdof) && (k == fcdofs[cind])) { 9069 indices[foffs[f]+k] = -(off+foff+k+1); 9070 ++cind; 9071 } else { 9072 indices[foffs[f]+k] = off+foff+k-cind; 9073 } 9074 } 9075 } else { 9076 for (k = fdof/fcomp-1; k >= 0; --k) { 9077 for (c = 0; c < fcomp; ++c) { 9078 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 9079 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 9080 ++cind; 9081 } else { 9082 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 9083 } 9084 } 9085 } 9086 } 9087 } 9088 foff += fdof - cfdof; 9089 foffs[f] += fdof; 9090 } 9091 PetscFunctionReturn(0); 9092 } 9093 9094 #undef __FUNCT__ 9095 #define __FUNCT__ "DMPlexMatSetClosure" 9096 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 9097 { 9098 DM_Plex *mesh = (DM_Plex *) dm->data; 9099 PetscInt *points = PETSC_NULL; 9100 PetscInt *indices; 9101 PetscInt offsets[32]; 9102 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 9103 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 9104 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 9105 PetscErrorCode ierr; 9106 9107 PetscFunctionBegin; 9108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9109 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 9110 if (useDefault) { 9111 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9112 } 9113 if (useGlobalDefault) { 9114 if (useDefault) { 9115 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 9116 } else { 9117 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9118 } 9119 } 9120 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9121 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 9122 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 9123 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9124 /* Compress out points not in the section */ 9125 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 9126 for (p = 0, q = 0; p < numPoints*2; p += 2) { 9127 if ((points[p] >= pStart) && (points[p] < pEnd)) { 9128 points[q*2] = points[p]; 9129 points[q*2+1] = points[p+1]; 9130 ++q; 9131 } 9132 } 9133 numPoints = q; 9134 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 9135 PetscInt fdof; 9136 9137 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 9138 for (f = 0; f < numFields; ++f) { 9139 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 9140 offsets[f+1] += fdof; 9141 } 9142 numIndices += dof; 9143 } 9144 for (f = 1; f < numFields; ++f) { 9145 offsets[f+1] += offsets[f]; 9146 } 9147 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 9148 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9149 if (numFields) { 9150 for (p = 0; p < numPoints*2; p += 2) { 9151 PetscInt o = points[p+1]; 9152 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9153 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 9154 } 9155 } else { 9156 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 9157 PetscInt o = points[p+1]; 9158 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9159 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 9160 } 9161 } 9162 if (useGlobalDefault && !useDefault) { 9163 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9164 } 9165 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 9166 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 9167 if (ierr) { 9168 PetscMPIInt rank; 9169 PetscErrorCode ierr2; 9170 9171 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 9172 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 9173 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 9174 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 9175 CHKERRQ(ierr); 9176 } 9177 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9178 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9179 PetscFunctionReturn(0); 9180 } 9181 9182 #undef __FUNCT__ 9183 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 9184 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9185 { 9186 PetscSection coordSection; 9187 Vec coordinates; 9188 const PetscScalar *coords; 9189 const PetscInt dim = 2; 9190 PetscInt d, f; 9191 PetscErrorCode ierr; 9192 9193 PetscFunctionBegin; 9194 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9195 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9196 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9197 if (v0) { 9198 for (d = 0; d < dim; d++) { 9199 v0[d] = PetscRealPart(coords[d]); 9200 } 9201 } 9202 if (J) { 9203 for (d = 0; d < dim; d++) { 9204 for (f = 0; f < dim; f++) { 9205 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9206 } 9207 } 9208 *detJ = J[0]*J[3] - J[1]*J[2]; 9209 #if 0 9210 if (detJ < 0.0) { 9211 const PetscReal xLength = mesh->periodicity[0]; 9212 9213 if (xLength != 0.0) { 9214 PetscReal v0x = coords[0*dim+0]; 9215 9216 if (v0x == 0.0) { 9217 v0x = v0[0] = xLength; 9218 } 9219 for (f = 0; f < dim; f++) { 9220 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 9221 9222 J[0*dim+f] = 0.5*(px - v0x); 9223 } 9224 } 9225 detJ = J[0]*J[3] - J[1]*J[2]; 9226 } 9227 #endif 9228 PetscLogFlops(8.0 + 3.0); 9229 } 9230 if (invJ) { 9231 const PetscReal invDet = 1.0/(*detJ); 9232 9233 invJ[0] = invDet*J[3]; 9234 invJ[1] = -invDet*J[1]; 9235 invJ[2] = -invDet*J[2]; 9236 invJ[3] = invDet*J[0]; 9237 PetscLogFlops(5.0); 9238 } 9239 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9240 PetscFunctionReturn(0); 9241 } 9242 9243 #undef __FUNCT__ 9244 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9245 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9246 { 9247 PetscSection coordSection; 9248 Vec coordinates; 9249 const PetscScalar *coords; 9250 const PetscInt dim = 2; 9251 PetscInt d, f; 9252 PetscErrorCode ierr; 9253 9254 PetscFunctionBegin; 9255 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9256 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9257 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9258 if (v0) { 9259 for (d = 0; d < dim; d++) { 9260 v0[d] = PetscRealPart(coords[d]); 9261 } 9262 } 9263 if (J) { 9264 for (d = 0; d < dim; d++) { 9265 for (f = 0; f < dim; f++) { 9266 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9267 } 9268 } 9269 *detJ = J[0]*J[3] - J[1]*J[2]; 9270 PetscLogFlops(8.0 + 3.0); 9271 } 9272 if (invJ) { 9273 const PetscReal invDet = 1.0/(*detJ); 9274 9275 invJ[0] = invDet*J[3]; 9276 invJ[1] = -invDet*J[1]; 9277 invJ[2] = -invDet*J[2]; 9278 invJ[3] = invDet*J[0]; 9279 PetscLogFlops(5.0); 9280 } 9281 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9282 PetscFunctionReturn(0); 9283 } 9284 9285 #undef __FUNCT__ 9286 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9287 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9288 { 9289 PetscSection coordSection; 9290 Vec coordinates; 9291 const PetscScalar *coords; 9292 const PetscInt dim = 3; 9293 PetscInt d, f; 9294 PetscErrorCode ierr; 9295 9296 PetscFunctionBegin; 9297 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9298 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9299 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9300 if (v0) { 9301 for (d = 0; d < dim; d++) { 9302 v0[d] = PetscRealPart(coords[d]); 9303 } 9304 } 9305 if (J) { 9306 for (d = 0; d < dim; d++) { 9307 for (f = 0; f < dim; f++) { 9308 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9309 } 9310 } 9311 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9312 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9313 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9314 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9315 PetscLogFlops(18.0 + 12.0); 9316 } 9317 if (invJ) { 9318 const PetscReal invDet = 1.0/(*detJ); 9319 9320 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9321 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9322 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9323 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9324 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9325 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9326 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9327 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9328 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9329 PetscLogFlops(37.0); 9330 } 9331 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9332 PetscFunctionReturn(0); 9333 } 9334 9335 #undef __FUNCT__ 9336 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9337 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9338 { 9339 PetscSection coordSection; 9340 Vec coordinates; 9341 const PetscScalar *coords; 9342 const PetscInt dim = 3; 9343 PetscInt d; 9344 PetscErrorCode ierr; 9345 9346 PetscFunctionBegin; 9347 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9348 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9349 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9350 if (v0) { 9351 for (d = 0; d < dim; d++) { 9352 v0[d] = PetscRealPart(coords[d]); 9353 } 9354 } 9355 if (J) { 9356 for (d = 0; d < dim; d++) { 9357 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9358 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9359 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9360 } 9361 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9362 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9363 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9364 PetscLogFlops(18.0 + 12.0); 9365 } 9366 if (invJ) { 9367 const PetscReal invDet = -1.0/(*detJ); 9368 9369 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9370 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9371 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9372 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9373 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9374 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9375 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9376 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9377 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9378 PetscLogFlops(37.0); 9379 } 9380 *detJ *= 8.0; 9381 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9382 PetscFunctionReturn(0); 9383 } 9384 9385 #undef __FUNCT__ 9386 #define __FUNCT__ "DMPlexComputeCellGeometry" 9387 /*@C 9388 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9389 9390 Collective on DM 9391 9392 Input Arguments: 9393 + dm - the DM 9394 - cell - the cell 9395 9396 Output Arguments: 9397 + v0 - the translation part of this affine transform 9398 . J - the Jacobian of the transform to the reference element 9399 . invJ - the inverse of the Jacobian 9400 - detJ - the Jacobian determinant 9401 9402 Level: advanced 9403 9404 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9405 @*/ 9406 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9407 { 9408 PetscInt dim, coneSize; 9409 PetscErrorCode ierr; 9410 9411 PetscFunctionBegin; 9412 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9413 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9414 switch (dim) { 9415 case 2: 9416 switch (coneSize) { 9417 case 3: 9418 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9419 break; 9420 case 4: 9421 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9422 break; 9423 default: 9424 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9425 } 9426 break; 9427 case 3: 9428 switch (coneSize) { 9429 case 4: 9430 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9431 break; 9432 case 8: 9433 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9434 break; 9435 default: 9436 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9437 } 9438 break; 9439 default: 9440 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9441 } 9442 PetscFunctionReturn(0); 9443 } 9444 9445 #undef __FUNCT__ 9446 #define __FUNCT__ "DMPlexGetFaceOrientation" 9447 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9448 { 9449 MPI_Comm comm = ((PetscObject) dm)->comm; 9450 PetscBool posOrient = PETSC_FALSE; 9451 const PetscInt debug = 0; 9452 PetscInt cellDim, faceSize, f; 9453 PetscErrorCode ierr; 9454 9455 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9456 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9457 9458 if (cellDim == numCorners-1) { 9459 /* Simplices */ 9460 faceSize = numCorners-1; 9461 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9462 } else if (cellDim == 1 && numCorners == 3) { 9463 /* Quadratic line */ 9464 faceSize = 1; 9465 posOrient = PETSC_TRUE; 9466 } else if (cellDim == 2 && numCorners == 4) { 9467 /* Quads */ 9468 faceSize = 2; 9469 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9470 posOrient = PETSC_TRUE; 9471 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9472 posOrient = PETSC_TRUE; 9473 } else { 9474 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9475 posOrient = PETSC_FALSE; 9476 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9477 } 9478 } else if (cellDim == 2 && numCorners == 6) { 9479 /* Quadratic triangle (I hate this) */ 9480 /* Edges are determined by the first 2 vertices (corners of edges) */ 9481 const PetscInt faceSizeTri = 3; 9482 PetscInt sortedIndices[3], i, iFace; 9483 PetscBool found = PETSC_FALSE; 9484 PetscInt faceVerticesTriSorted[9] = { 9485 0, 3, 4, /* bottom */ 9486 1, 4, 5, /* right */ 9487 2, 3, 5, /* left */ 9488 }; 9489 PetscInt faceVerticesTri[9] = { 9490 0, 3, 4, /* bottom */ 9491 1, 4, 5, /* right */ 9492 2, 5, 3, /* left */ 9493 }; 9494 9495 faceSize = faceSizeTri; 9496 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9497 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9498 for (iFace = 0; iFace < 3; ++iFace) { 9499 const PetscInt ii = iFace*faceSizeTri; 9500 PetscInt fVertex, cVertex; 9501 9502 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9503 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9504 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9505 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9506 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9507 faceVertices[fVertex] = origVertices[cVertex]; 9508 break; 9509 } 9510 } 9511 } 9512 found = PETSC_TRUE; 9513 break; 9514 } 9515 } 9516 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9517 if (posOriented) {*posOriented = PETSC_TRUE;} 9518 PetscFunctionReturn(0); 9519 } else if (cellDim == 2 && numCorners == 9) { 9520 /* Quadratic quad (I hate this) */ 9521 /* Edges are determined by the first 2 vertices (corners of edges) */ 9522 const PetscInt faceSizeQuad = 3; 9523 PetscInt sortedIndices[3], i, iFace; 9524 PetscBool found = PETSC_FALSE; 9525 PetscInt faceVerticesQuadSorted[12] = { 9526 0, 1, 4, /* bottom */ 9527 1, 2, 5, /* right */ 9528 2, 3, 6, /* top */ 9529 0, 3, 7, /* left */ 9530 }; 9531 PetscInt faceVerticesQuad[12] = { 9532 0, 1, 4, /* bottom */ 9533 1, 2, 5, /* right */ 9534 2, 3, 6, /* top */ 9535 3, 0, 7, /* left */ 9536 }; 9537 9538 faceSize = faceSizeQuad; 9539 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9540 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9541 for (iFace = 0; iFace < 4; ++iFace) { 9542 const PetscInt ii = iFace*faceSizeQuad; 9543 PetscInt fVertex, cVertex; 9544 9545 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9546 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9547 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9548 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9549 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9550 faceVertices[fVertex] = origVertices[cVertex]; 9551 break; 9552 } 9553 } 9554 } 9555 found = PETSC_TRUE; 9556 break; 9557 } 9558 } 9559 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9560 if (posOriented) {*posOriented = PETSC_TRUE;} 9561 PetscFunctionReturn(0); 9562 } else if (cellDim == 3 && numCorners == 8) { 9563 /* Hexes 9564 A hex is two oriented quads with the normal of the first 9565 pointing up at the second. 9566 9567 7---6 9568 /| /| 9569 4---5 | 9570 | 3-|-2 9571 |/ |/ 9572 0---1 9573 9574 Faces are determined by the first 4 vertices (corners of faces) */ 9575 const PetscInt faceSizeHex = 4; 9576 PetscInt sortedIndices[4], i, iFace; 9577 PetscBool found = PETSC_FALSE; 9578 PetscInt faceVerticesHexSorted[24] = { 9579 0, 1, 2, 3, /* bottom */ 9580 4, 5, 6, 7, /* top */ 9581 0, 1, 4, 5, /* front */ 9582 1, 2, 5, 6, /* right */ 9583 2, 3, 6, 7, /* back */ 9584 0, 3, 4, 7, /* left */ 9585 }; 9586 PetscInt faceVerticesHex[24] = { 9587 3, 2, 1, 0, /* bottom */ 9588 4, 5, 6, 7, /* top */ 9589 0, 1, 5, 4, /* front */ 9590 1, 2, 6, 5, /* right */ 9591 2, 3, 7, 6, /* back */ 9592 3, 0, 4, 7, /* left */ 9593 }; 9594 9595 faceSize = faceSizeHex; 9596 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9597 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9598 for (iFace = 0; iFace < 6; ++iFace) { 9599 const PetscInt ii = iFace*faceSizeHex; 9600 PetscInt fVertex, cVertex; 9601 9602 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9603 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9604 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9605 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9606 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9607 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9608 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9609 faceVertices[fVertex] = origVertices[cVertex]; 9610 break; 9611 } 9612 } 9613 } 9614 found = PETSC_TRUE; 9615 break; 9616 } 9617 } 9618 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9619 if (posOriented) {*posOriented = PETSC_TRUE;} 9620 PetscFunctionReturn(0); 9621 } else if (cellDim == 3 && numCorners == 10) { 9622 /* Quadratic tet */ 9623 /* Faces are determined by the first 3 vertices (corners of faces) */ 9624 const PetscInt faceSizeTet = 6; 9625 PetscInt sortedIndices[6], i, iFace; 9626 PetscBool found = PETSC_FALSE; 9627 PetscInt faceVerticesTetSorted[24] = { 9628 0, 1, 2, 6, 7, 8, /* bottom */ 9629 0, 3, 4, 6, 7, 9, /* front */ 9630 1, 4, 5, 7, 8, 9, /* right */ 9631 2, 3, 5, 6, 8, 9, /* left */ 9632 }; 9633 PetscInt faceVerticesTet[24] = { 9634 0, 1, 2, 6, 7, 8, /* bottom */ 9635 0, 4, 3, 6, 7, 9, /* front */ 9636 1, 5, 4, 7, 8, 9, /* right */ 9637 2, 3, 5, 8, 6, 9, /* left */ 9638 }; 9639 9640 faceSize = faceSizeTet; 9641 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9642 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9643 for (iFace=0; iFace < 4; ++iFace) { 9644 const PetscInt ii = iFace*faceSizeTet; 9645 PetscInt fVertex, cVertex; 9646 9647 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9648 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9649 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9650 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9651 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9652 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9653 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9654 faceVertices[fVertex] = origVertices[cVertex]; 9655 break; 9656 } 9657 } 9658 } 9659 found = PETSC_TRUE; 9660 break; 9661 } 9662 } 9663 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9664 if (posOriented) {*posOriented = PETSC_TRUE;} 9665 PetscFunctionReturn(0); 9666 } else if (cellDim == 3 && numCorners == 27) { 9667 /* Quadratic hexes (I hate this) 9668 A hex is two oriented quads with the normal of the first 9669 pointing up at the second. 9670 9671 7---6 9672 /| /| 9673 4---5 | 9674 | 3-|-2 9675 |/ |/ 9676 0---1 9677 9678 Faces are determined by the first 4 vertices (corners of faces) */ 9679 const PetscInt faceSizeQuadHex = 9; 9680 PetscInt sortedIndices[9], i, iFace; 9681 PetscBool found = PETSC_FALSE; 9682 PetscInt faceVerticesQuadHexSorted[54] = { 9683 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9684 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9685 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9686 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9687 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9688 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9689 }; 9690 PetscInt faceVerticesQuadHex[54] = { 9691 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9692 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9693 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9694 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9695 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9696 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9697 }; 9698 9699 faceSize = faceSizeQuadHex; 9700 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9701 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9702 for (iFace = 0; iFace < 6; ++iFace) { 9703 const PetscInt ii = iFace*faceSizeQuadHex; 9704 PetscInt fVertex, cVertex; 9705 9706 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9707 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9708 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9709 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9710 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9711 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9712 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9713 faceVertices[fVertex] = origVertices[cVertex]; 9714 break; 9715 } 9716 } 9717 } 9718 found = PETSC_TRUE; 9719 break; 9720 } 9721 } 9722 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9723 if (posOriented) {*posOriented = PETSC_TRUE;} 9724 PetscFunctionReturn(0); 9725 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9726 if (!posOrient) { 9727 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9728 for (f = 0; f < faceSize; ++f) { 9729 faceVertices[f] = origVertices[faceSize-1 - f]; 9730 } 9731 } else { 9732 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9733 for (f = 0; f < faceSize; ++f) { 9734 faceVertices[f] = origVertices[f]; 9735 } 9736 } 9737 if (posOriented) {*posOriented = posOrient;} 9738 PetscFunctionReturn(0); 9739 } 9740 9741 #undef __FUNCT__ 9742 #define __FUNCT__ "DMPlexGetOrientedFace" 9743 /* 9744 Given a cell and a face, as a set of vertices, 9745 return the oriented face, as a set of vertices, in faceVertices 9746 The orientation is such that the face normal points out of the cell 9747 */ 9748 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9749 { 9750 const PetscInt *cone = PETSC_NULL; 9751 PetscInt coneSize, v, f, v2; 9752 PetscInt oppositeVertex = -1; 9753 PetscErrorCode ierr; 9754 9755 PetscFunctionBegin; 9756 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9757 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9758 for (v = 0, v2 = 0; v < coneSize; ++v) { 9759 PetscBool found = PETSC_FALSE; 9760 9761 for (f = 0; f < faceSize; ++f) { 9762 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 9763 } 9764 if (found) { 9765 indices[v2] = v; 9766 origVertices[v2] = cone[v]; 9767 ++v2; 9768 } else { 9769 oppositeVertex = v; 9770 } 9771 } 9772 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9773 PetscFunctionReturn(0); 9774 } 9775 9776 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9777 { 9778 switch (i) { 9779 case 0: 9780 switch (j) { 9781 case 0: return 0; 9782 case 1: 9783 switch (k) { 9784 case 0: return 0; 9785 case 1: return 0; 9786 case 2: return 1; 9787 } 9788 case 2: 9789 switch (k) { 9790 case 0: return 0; 9791 case 1: return -1; 9792 case 2: return 0; 9793 } 9794 } 9795 case 1: 9796 switch (j) { 9797 case 0: 9798 switch (k) { 9799 case 0: return 0; 9800 case 1: return 0; 9801 case 2: return -1; 9802 } 9803 case 1: return 0; 9804 case 2: 9805 switch (k) { 9806 case 0: return 1; 9807 case 1: return 0; 9808 case 2: return 0; 9809 } 9810 } 9811 case 2: 9812 switch (j) { 9813 case 0: 9814 switch (k) { 9815 case 0: return 0; 9816 case 1: return 1; 9817 case 2: return 0; 9818 } 9819 case 1: 9820 switch (k) { 9821 case 0: return -1; 9822 case 1: return 0; 9823 case 2: return 0; 9824 } 9825 case 2: return 0; 9826 } 9827 } 9828 return 0; 9829 } 9830 9831 #undef __FUNCT__ 9832 #define __FUNCT__ "DMPlexCreateRigidBody" 9833 /*@C 9834 DMPlexCreateRigidBody - create rigid body modes from coordinates 9835 9836 Collective on DM 9837 9838 Input Arguments: 9839 + dm - the DM 9840 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9841 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9842 9843 Output Argument: 9844 . sp - the null space 9845 9846 Note: This is necessary to take account of Dirichlet conditions on the displacements 9847 9848 Level: advanced 9849 9850 .seealso: MatNullSpaceCreate() 9851 @*/ 9852 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9853 { 9854 MPI_Comm comm = ((PetscObject) dm)->comm; 9855 Vec coordinates, localMode, mode[6]; 9856 PetscSection coordSection; 9857 PetscScalar *coords; 9858 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9859 PetscErrorCode ierr; 9860 9861 PetscFunctionBegin; 9862 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9863 if (dim == 1) { 9864 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9865 PetscFunctionReturn(0); 9866 } 9867 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9868 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9869 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9870 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9871 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9872 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9873 m = (dim*(dim+1))/2; 9874 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9875 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9876 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9877 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9878 /* Assume P1 */ 9879 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9880 for (d = 0; d < dim; ++d) { 9881 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9882 9883 values[d] = 1.0; 9884 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9885 for (v = vStart; v < vEnd; ++v) { 9886 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9887 } 9888 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9889 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9890 } 9891 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9892 for (d = dim; d < dim*(dim+1)/2; ++d) { 9893 PetscInt i, j, k = dim > 2 ? d - dim : d; 9894 9895 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9896 for (v = vStart; v < vEnd; ++v) { 9897 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9898 PetscInt off; 9899 9900 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9901 for (i = 0; i < dim; ++i) { 9902 for (j = 0; j < dim; ++j) { 9903 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9904 } 9905 } 9906 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9907 } 9908 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9909 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9910 } 9911 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9912 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9913 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9914 /* Orthonormalize system */ 9915 for (i = dim; i < m; ++i) { 9916 PetscScalar dots[6]; 9917 9918 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9919 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9920 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9921 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9922 } 9923 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9924 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9925 PetscFunctionReturn(0); 9926 } 9927 9928 #undef __FUNCT__ 9929 #define __FUNCT__ "DMPlexGetHybridBounds" 9930 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9931 { 9932 DM_Plex *mesh = (DM_Plex *) dm->data; 9933 PetscInt dim; 9934 PetscErrorCode ierr; 9935 9936 PetscFunctionBegin; 9937 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9938 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9939 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9940 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9941 if (eMax) *eMax = mesh->hybridPointMax[1]; 9942 if (vMax) *vMax = mesh->hybridPointMax[0]; 9943 PetscFunctionReturn(0); 9944 } 9945 9946 #undef __FUNCT__ 9947 #define __FUNCT__ "DMPlexSetHybridBounds" 9948 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9949 { 9950 DM_Plex *mesh = (DM_Plex *) dm->data; 9951 PetscInt dim; 9952 PetscErrorCode ierr; 9953 9954 PetscFunctionBegin; 9955 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9956 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9957 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9958 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9959 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9960 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9961 PetscFunctionReturn(0); 9962 } 9963 9964 #undef __FUNCT__ 9965 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9966 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9967 { 9968 DM_Plex *mesh = (DM_Plex *) dm->data; 9969 9970 PetscFunctionBegin; 9971 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9972 PetscValidPointer(cellHeight, 2); 9973 *cellHeight = mesh->vtkCellHeight; 9974 PetscFunctionReturn(0); 9975 } 9976 9977 #undef __FUNCT__ 9978 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9979 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9980 { 9981 DM_Plex *mesh = (DM_Plex *) dm->data; 9982 9983 PetscFunctionBegin; 9984 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9985 mesh->vtkCellHeight = cellHeight; 9986 PetscFunctionReturn(0); 9987 } 9988 9989 #undef __FUNCT__ 9990 #define __FUNCT__ "DMPlexInsertFace_Private" 9991 /* 9992 DMPlexInsertFace_Private - Puts a face into the mesh 9993 9994 Not collective 9995 9996 Input Parameters: 9997 + dm - The DMPlex 9998 . numFaceVertex - The number of vertices in the face 9999 . faceVertices - The vertices in the face for dm 10000 . subfaceVertices - The vertices in the face for subdm 10001 . numCorners - The number of vertices in the cell 10002 . cell - A cell in dm containing the face 10003 . subcell - A cell in subdm containing the face 10004 . firstFace - First face in the mesh 10005 - newFacePoint - Next face in the mesh 10006 10007 Output Parameters: 10008 . newFacePoint - Contains next face point number on input, updated on output 10009 10010 Level: developer 10011 */ 10012 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) 10013 { 10014 MPI_Comm comm = ((PetscObject) dm)->comm; 10015 DM_Plex *submesh = (DM_Plex *) subdm->data; 10016 const PetscInt *faces; 10017 PetscInt numFaces, coneSize; 10018 PetscErrorCode ierr; 10019 10020 PetscFunctionBegin; 10021 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 10022 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 10023 #if 0 10024 /* Cannot use this because support() has not been constructed yet */ 10025 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 10026 #else 10027 { 10028 PetscInt f; 10029 10030 numFaces = 0; 10031 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 10032 for (f = firstFace; f < *newFacePoint; ++f) { 10033 PetscInt dof, off, d; 10034 10035 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 10036 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 10037 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 10038 for (d = 0; d < dof; ++d) { 10039 const PetscInt p = submesh->cones[off+d]; 10040 PetscInt v; 10041 10042 for (v = 0; v < numFaceVertices; ++v) { 10043 if (subfaceVertices[v] == p) break; 10044 } 10045 if (v == numFaceVertices) break; 10046 } 10047 if (d == dof) { 10048 numFaces = 1; 10049 ((PetscInt *) faces)[0] = f; 10050 } 10051 } 10052 } 10053 #endif 10054 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 10055 else if (numFaces == 1) { 10056 /* Add the other cell neighbor for this face */ 10057 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 10058 } else { 10059 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 10060 PetscBool posOriented; 10061 10062 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10063 origVertices = &orientedVertices[numFaceVertices]; 10064 indices = &orientedVertices[numFaceVertices*2]; 10065 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 10066 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 10067 /* TODO: I know that routine should return a permutation, not the indices */ 10068 for (v = 0; v < numFaceVertices; ++v) { 10069 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 10070 for (ov = 0; ov < numFaceVertices; ++ov) { 10071 if (orientedVertices[ov] == vertex) { 10072 orientedSubVertices[ov] = subvertex; 10073 break; 10074 } 10075 } 10076 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 10077 } 10078 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 10079 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 10080 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10081 ++(*newFacePoint); 10082 } 10083 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 10084 PetscFunctionReturn(0); 10085 } 10086 10087 #undef __FUNCT__ 10088 #define __FUNCT__ "DMPlexCreateSubmesh" 10089 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 10090 { 10091 MPI_Comm comm = ((PetscObject) dm)->comm; 10092 DM_Plex *submesh; 10093 PetscBool boundaryFaces = PETSC_FALSE; 10094 PetscSection coordSection, subCoordSection; 10095 Vec coordinates, subCoordinates; 10096 PetscScalar *coords, *subCoords; 10097 IS labelIS; 10098 const PetscInt *subVertices; 10099 PetscInt *subVerticesActive, *tmpPoints; 10100 PetscInt *subCells = PETSC_NULL; 10101 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 10102 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 10103 PetscInt dim; /* Right now, do not specify dimension */ 10104 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 10105 PetscErrorCode ierr; 10106 10107 PetscFunctionBegin; 10108 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10109 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10110 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10111 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 10112 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10113 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 10114 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 10115 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10116 subface = &face[maxConeSize]; 10117 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 10118 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 10119 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 10120 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 10121 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 10122 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 10123 maxSubCells = numSubVertices; 10124 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 10125 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 10126 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 10127 for (v = 0; v < numSubVertices; ++v) { 10128 const PetscInt vertex = subVertices[v]; 10129 PetscInt *star = PETSC_NULL; 10130 PetscInt starSize, numCells = 0; 10131 10132 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10133 for (p = 0; p < starSize*2; p += 2) { 10134 const PetscInt point = star[p]; 10135 if ((point >= cStart) && (point < cEnd)) { 10136 star[numCells++] = point; 10137 } 10138 } 10139 numOldSubCells = numSubCells; 10140 for (c = 0; c < numCells; ++c) { 10141 const PetscInt cell = star[c]; 10142 PetscInt *closure = PETSC_NULL; 10143 PetscInt closureSize, numCorners = 0, faceSize = 0; 10144 PetscInt cellLoc; 10145 10146 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 10147 if (cellLoc >= 0) continue; 10148 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10149 for (p = 0; p < closureSize*2; p += 2) { 10150 const PetscInt point = closure[p]; 10151 if ((point >= vStart) && (point < vEnd)) { 10152 closure[numCorners++] = point; 10153 } 10154 } 10155 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 10156 for (corner = 0; corner < numCorners; ++corner) { 10157 const PetscInt cellVertex = closure[corner]; 10158 PetscInt subVertex; 10159 10160 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 10161 if (subVertex >= 0) { /* contains submesh vertex */ 10162 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 10163 if (i == faceSize) { 10164 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 10165 face[faceSize] = cellVertex; 10166 subface[faceSize] = subVertex; 10167 ++faceSize; 10168 } 10169 } 10170 } 10171 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10172 if (faceSize >= nFV) { 10173 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10174 if (numSubCells >= maxSubCells) { 10175 PetscInt *tmpCells; 10176 maxSubCells *= 2; 10177 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 10178 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 10179 ierr = PetscFree(subCells);CHKERRQ(ierr); 10180 subCells = tmpCells; 10181 } 10182 /* TOOD: Maybe overestimate then squeeze out empty faces */ 10183 if (faceSize > nFV) { 10184 /* TODO: This is tricky. Maybe just add all faces */ 10185 numSubFaces++; 10186 } else { 10187 numSubFaces++; 10188 } 10189 for (f = 0; f < faceSize; ++f) { 10190 subVerticesActive[subface[f]] = 1; 10191 } 10192 subCells[numSubCells++] = cell; 10193 } 10194 } 10195 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10196 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 10197 } 10198 /* Pick out active subvertices */ 10199 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 10200 if (subVerticesActive[v]) { 10201 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 10202 } 10203 } 10204 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 10205 /* Set cone sizes */ 10206 firstSubVertex = numSubCells; 10207 firstSubFace = numSubCells+numSubVerticesActive; 10208 newFacePoint = firstSubFace; 10209 for (c = 0; c < numSubCells; ++c) { 10210 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 10211 } 10212 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 10213 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 10214 } 10215 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 10216 /* Create face cones */ 10217 for (c = 0; c < numSubCells; ++c) { 10218 const PetscInt cell = subCells[c]; 10219 PetscInt *closure = PETSC_NULL; 10220 PetscInt closureSize, numCorners = 0, faceSize = 0; 10221 10222 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10223 for (p = 0; p < closureSize*2; p += 2) { 10224 const PetscInt point = closure[p]; 10225 if ((point >= vStart) && (point < vEnd)) { 10226 closure[numCorners++] = point; 10227 } 10228 } 10229 for (corner = 0; corner < numCorners; ++corner) { 10230 const PetscInt cellVertex = closure[corner]; 10231 PetscInt subVertex; 10232 10233 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 10234 if (subVertex >= 0) { /* contains submesh vertex */ 10235 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 10236 if (i == faceSize) { 10237 face[faceSize] = cellVertex; 10238 subface[faceSize] = numSubCells+subVertex; 10239 ++faceSize; 10240 } 10241 } 10242 } 10243 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10244 if (faceSize >= nFV) { 10245 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10246 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 10247 /* We have to take all the faces, and discard those in the interior */ 10248 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 10249 #if 0 10250 /* This object just calls insert on each face that comes from subsets() */ 10251 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 10252 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 10253 PointArray faceVec(face->begin(), face->end()); 10254 10255 subsets(faceVec, nFV, inserter); 10256 #endif 10257 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 10258 } 10259 } 10260 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 10261 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 10262 /* Build coordinates */ 10263 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10264 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10265 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 10266 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 10267 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 10268 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 10269 } 10270 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10271 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10272 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 10273 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10274 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10275 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10276 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10277 for (v = 0; v < numSubVerticesActive; ++v) { 10278 const PetscInt vertex = subVerticesActive[v]; 10279 const PetscInt subVertex = firstSubVertex+v; 10280 PetscInt dof, off, sdof, soff; 10281 10282 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10283 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10284 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10285 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10286 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10287 for (d = 0; d < dof; ++d) { 10288 subCoords[soff+d] = coords[off+d]; 10289 } 10290 } 10291 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10292 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10293 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 10294 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10295 10296 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 10297 /* Create map from submesh points to original mesh points */ 10298 submesh = (DM_Plex *) (*subdm)->data; 10299 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 10300 for (c = 0; c < numSubCells; ++c) { 10301 tmpPoints[c] = subCells[c]; 10302 } 10303 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 10304 tmpPoints[v] = subVerticesActive[v-numSubCells]; 10305 } 10306 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 10307 10308 ierr = PetscFree(subCells);CHKERRQ(ierr); 10309 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10310 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10311 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10312 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10313 PetscFunctionReturn(0); 10314 } 10315 10316 #undef __FUNCT__ 10317 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10318 /* We can easily have a form that takes an IS instead */ 10319 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10320 { 10321 PetscSection section, globalSection; 10322 PetscInt *numbers, p; 10323 PetscErrorCode ierr; 10324 10325 PetscFunctionBegin; 10326 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10327 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10328 for (p = pStart; p < pEnd; ++p) { 10329 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10330 } 10331 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10332 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10333 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10334 for (p = pStart; p < pEnd; ++p) { 10335 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10336 } 10337 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10338 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10339 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10340 PetscFunctionReturn(0); 10341 } 10342 10343 #undef __FUNCT__ 10344 #define __FUNCT__ "DMPlexGetCellNumbering" 10345 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10346 { 10347 DM_Plex *mesh = (DM_Plex *) dm->data; 10348 PetscInt cellHeight, cStart, cEnd, cMax; 10349 PetscErrorCode ierr; 10350 10351 PetscFunctionBegin; 10352 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10353 if (!mesh->globalCellNumbers) { 10354 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10355 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10356 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10357 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 10358 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10359 } 10360 *globalCellNumbers = mesh->globalCellNumbers; 10361 PetscFunctionReturn(0); 10362 } 10363 10364 #undef __FUNCT__ 10365 #define __FUNCT__ "DMPlexGetVertexNumbering" 10366 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10367 { 10368 DM_Plex *mesh = (DM_Plex *) dm->data; 10369 PetscInt vStart, vEnd, vMax; 10370 PetscErrorCode ierr; 10371 10372 PetscFunctionBegin; 10373 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10374 if (!mesh->globalVertexNumbers) { 10375 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10376 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10377 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 10378 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10379 } 10380 *globalVertexNumbers = mesh->globalVertexNumbers; 10381 PetscFunctionReturn(0); 10382 } 10383 10384 #undef __FUNCT__ 10385 #define __FUNCT__ "DMPlexGetSubpointMap" 10386 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 10387 { 10388 DM_Plex *mesh = (DM_Plex *) dm->data; 10389 10390 PetscFunctionBegin; 10391 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10392 PetscValidPointer(subpointMap, 2); 10393 *subpointMap = mesh->subpointMap; 10394 PetscFunctionReturn(0); 10395 } 10396 10397 #undef __FUNCT__ 10398 #define __FUNCT__ "DMPlexSetSubpointMap" 10399 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10400 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 10401 { 10402 DM_Plex *mesh = (DM_Plex *) dm->data; 10403 10404 PetscFunctionBegin; 10405 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10406 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 10407 mesh->subpointMap = subpointMap; 10408 PetscFunctionReturn(0); 10409 } 10410 10411 #undef __FUNCT__ 10412 #define __FUNCT__ "DMPlexGetScale" 10413 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10414 { 10415 DM_Plex *mesh = (DM_Plex *) dm->data; 10416 10417 PetscFunctionBegin; 10418 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10419 PetscValidPointer(scale, 3); 10420 *scale = mesh->scale[unit]; 10421 PetscFunctionReturn(0); 10422 } 10423 10424 #undef __FUNCT__ 10425 #define __FUNCT__ "DMPlexSetScale" 10426 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10427 { 10428 DM_Plex *mesh = (DM_Plex *) dm->data; 10429 10430 PetscFunctionBegin; 10431 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10432 mesh->scale[unit] = scale; 10433 PetscFunctionReturn(0); 10434 } 10435 10436 10437 /******************************************************************************* 10438 This should be in a separate Discretization object, but I am not sure how to lay 10439 it out yet, so I am stuffing things here while I experiment. 10440 *******************************************************************************/ 10441 #undef __FUNCT__ 10442 #define __FUNCT__ "DMPlexSetFEMIntegration" 10443 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10444 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10445 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10446 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10447 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10448 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10449 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10450 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10451 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10452 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10453 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10454 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], 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 { 10461 DM_Plex *mesh = (DM_Plex *) dm->data; 10462 10463 PetscFunctionBegin; 10464 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10465 mesh->integrateResidualFEM = integrateResidualFEM; 10466 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10467 mesh->integrateJacobianFEM = integrateJacobianFEM; 10468 PetscFunctionReturn(0); 10469 } 10470 10471 #undef __FUNCT__ 10472 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10473 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10474 { 10475 Vec coordinates; 10476 PetscSection section, cSection; 10477 PetscInt dim, vStart, vEnd, v, c, d; 10478 PetscScalar *values, *cArray; 10479 PetscReal *coords; 10480 PetscErrorCode ierr; 10481 10482 PetscFunctionBegin; 10483 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10484 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10485 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10486 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10487 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10488 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10489 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10490 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10491 for (v = vStart; v < vEnd; ++v) { 10492 PetscInt dof, off; 10493 10494 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10495 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10496 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10497 for (d = 0; d < dof; ++d) { 10498 coords[d] = PetscRealPart(cArray[off+d]); 10499 } 10500 for (c = 0; c < numComp; ++c) { 10501 values[c] = (*funcs[c])(coords); 10502 } 10503 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10504 } 10505 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10506 /* Temporary, must be replaced by a projection on the finite element basis */ 10507 { 10508 PetscInt eStart = 0, eEnd = 0, e, depth; 10509 10510 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10511 --depth; 10512 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10513 for (e = eStart; e < eEnd; ++e) { 10514 const PetscInt *cone = PETSC_NULL; 10515 PetscInt coneSize, d; 10516 PetscScalar *coordsA, *coordsB; 10517 10518 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10519 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10520 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10521 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10522 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10523 for (d = 0; d < dim; ++d) { 10524 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10525 } 10526 for (c = 0; c < numComp; ++c) { 10527 values[c] = (*funcs[c])(coords); 10528 } 10529 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10530 } 10531 } 10532 10533 ierr = PetscFree(coords);CHKERRQ(ierr); 10534 ierr = PetscFree(values);CHKERRQ(ierr); 10535 #if 0 10536 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10537 PetscReal detJ; 10538 10539 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10540 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10541 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10542 10543 for (PetscInt c = cStart; c < cEnd; ++c) { 10544 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10545 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10546 const int oSize = pV.getSize(); 10547 int v = 0; 10548 10549 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10550 for (PetscInt cl = 0; cl < oSize; ++cl) { 10551 const PetscInt fDim; 10552 10553 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10554 if (pointDim) { 10555 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10556 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10557 } 10558 } 10559 } 10560 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10561 pV.clear(); 10562 } 10563 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10564 ierr = PetscFree(values);CHKERRQ(ierr); 10565 #endif 10566 PetscFunctionReturn(0); 10567 } 10568 10569 #undef __FUNCT__ 10570 #define __FUNCT__ "DMPlexProjectFunction" 10571 /*@C 10572 DMPlexProjectFunction - This projects the given function into the function space provided. 10573 10574 Input Parameters: 10575 + dm - The DM 10576 . numComp - The number of components (functions) 10577 . funcs - The coordinate functions to evaluate 10578 - mode - The insertion mode for values 10579 10580 Output Parameter: 10581 . X - vector 10582 10583 Level: developer 10584 10585 Note: 10586 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10587 We will eventually fix it. 10588 10589 ,seealso: DMPlexComputeL2Diff() 10590 */ 10591 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10592 { 10593 Vec localX; 10594 PetscErrorCode ierr; 10595 10596 PetscFunctionBegin; 10597 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10598 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10599 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10600 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10601 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10602 PetscFunctionReturn(0); 10603 } 10604 10605 #undef __FUNCT__ 10606 #define __FUNCT__ "DMPlexComputeL2Diff" 10607 /*@C 10608 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10609 10610 Input Parameters: 10611 + dm - The DM 10612 . quad - The PetscQuadrature object for each field 10613 . funcs - The functions to evaluate for each field component 10614 - X - The coefficient vector u_h 10615 10616 Output Parameter: 10617 . diff - The diff ||u - u_h||_2 10618 10619 Level: developer 10620 10621 .seealso: DMPlexProjectFunction() 10622 */ 10623 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10624 { 10625 const PetscInt debug = 0; 10626 PetscSection section; 10627 Vec localX; 10628 PetscReal *coords, *v0, *J, *invJ, detJ; 10629 PetscReal localDiff = 0.0; 10630 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10631 PetscErrorCode ierr; 10632 10633 PetscFunctionBegin; 10634 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10635 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10636 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10637 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10638 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10639 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10640 for (field = 0; field < numFields; ++field) { 10641 numComponents += quad[field].numComponents; 10642 } 10643 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10644 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10645 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10646 for (c = cStart; c < cEnd; ++c) { 10647 const PetscScalar *x; 10648 PetscReal elemDiff = 0.0; 10649 10650 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10651 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10652 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10653 10654 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10655 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10656 const PetscReal *quadPoints = quad[field].quadPoints; 10657 const PetscReal *quadWeights = quad[field].quadWeights; 10658 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10659 const PetscInt numBasisComps = quad[field].numComponents; 10660 const PetscReal *basis = quad[field].basis; 10661 PetscInt q, d, e, fc, f; 10662 10663 if (debug) { 10664 char title[1024]; 10665 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10666 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10667 } 10668 for (q = 0; q < numQuadPoints; ++q) { 10669 for (d = 0; d < dim; d++) { 10670 coords[d] = v0[d]; 10671 for (e = 0; e < dim; e++) { 10672 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10673 } 10674 } 10675 for (fc = 0; fc < numBasisComps; ++fc) { 10676 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10677 PetscReal interpolant = 0.0; 10678 for (f = 0; f < numBasisFuncs; ++f) { 10679 const PetscInt fidx = f*numBasisComps+fc; 10680 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10681 } 10682 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10683 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10684 } 10685 } 10686 comp += numBasisComps; 10687 fieldOffset += numBasisFuncs*numBasisComps; 10688 } 10689 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10690 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10691 localDiff += elemDiff; 10692 } 10693 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10694 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10695 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10696 *diff = PetscSqrtReal(*diff); 10697 PetscFunctionReturn(0); 10698 } 10699 10700 #undef __FUNCT__ 10701 #define __FUNCT__ "DMPlexComputeResidualFEM" 10702 /*@ 10703 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10704 10705 Input Parameters: 10706 + dm - The mesh 10707 . X - Local input vector 10708 - user - The user context 10709 10710 Output Parameter: 10711 . F - Local output vector 10712 10713 Note: 10714 The second member of the user context must be an FEMContext. 10715 10716 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10717 like a GPU, or vectorize on a multicore machine. 10718 10719 .seealso: DMPlexComputeJacobianActionFEM() 10720 */ 10721 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10722 { 10723 DM_Plex *mesh = (DM_Plex *) dm->data; 10724 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10725 PetscQuadrature *quad = fem->quad; 10726 PetscSection section; 10727 PetscReal *v0, *J, *invJ, *detJ; 10728 PetscScalar *elemVec, *u; 10729 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10730 PetscInt cellDof = 0, numComponents = 0; 10731 PetscErrorCode ierr; 10732 10733 PetscFunctionBegin; 10734 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10735 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10736 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10737 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10738 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10739 numCells = cEnd - cStart; 10740 for (field = 0; field < numFields; ++field) { 10741 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10742 numComponents += quad[field].numComponents; 10743 } 10744 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10745 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10746 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); 10747 for (c = cStart; c < cEnd; ++c) { 10748 const PetscScalar *x; 10749 PetscInt i; 10750 10751 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10752 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10753 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10754 10755 for (i = 0; i < cellDof; ++i) { 10756 u[c*cellDof+i] = x[i]; 10757 } 10758 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10759 } 10760 for (field = 0; field < numFields; ++field) { 10761 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10762 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10763 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10764 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10765 /* Conforming batches */ 10766 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10767 PetscInt numBlocks = 1; 10768 PetscInt batchSize = numBlocks * blockSize; 10769 PetscInt numBatches = numBatchesTmp; 10770 PetscInt numChunks = numCells / (numBatches*batchSize); 10771 /* Remainder */ 10772 PetscInt numRemainder = numCells % (numBatches * batchSize); 10773 PetscInt offset = numCells - numRemainder; 10774 10775 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10776 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10777 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10778 } 10779 for (c = cStart; c < cEnd; ++c) { 10780 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10781 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10782 } 10783 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10784 if (mesh->printFEM) { 10785 PetscMPIInt rank, numProcs; 10786 PetscInt p; 10787 10788 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10789 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10790 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10791 for (p = 0; p < numProcs; ++p) { 10792 if (p == rank) { 10793 Vec f; 10794 10795 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10796 ierr = VecCopy(F, f);CHKERRQ(ierr); 10797 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10798 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10799 ierr = VecDestroy(&f);CHKERRQ(ierr); 10800 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10801 } 10802 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10803 } 10804 } 10805 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10806 PetscFunctionReturn(0); 10807 } 10808 10809 #undef __FUNCT__ 10810 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10811 /*@C 10812 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10813 10814 Input Parameters: 10815 + dm - The mesh 10816 . J - The Jacobian shell matrix 10817 . X - Local input vector 10818 - user - The user context 10819 10820 Output Parameter: 10821 . F - Local output vector 10822 10823 Note: 10824 The second member of the user context must be an FEMContext. 10825 10826 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10827 like a GPU, or vectorize on a multicore machine. 10828 10829 .seealso: DMPlexComputeResidualFEM() 10830 */ 10831 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10832 { 10833 DM_Plex *mesh = (DM_Plex *) dm->data; 10834 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10835 PetscQuadrature *quad = fem->quad; 10836 PetscSection section; 10837 JacActionCtx *jctx; 10838 PetscReal *v0, *J, *invJ, *detJ; 10839 PetscScalar *elemVec, *u, *a; 10840 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10841 PetscInt cellDof = 0; 10842 PetscErrorCode ierr; 10843 10844 PetscFunctionBegin; 10845 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10846 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10847 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10848 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10849 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10850 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10851 numCells = cEnd - cStart; 10852 for (field = 0; field < numFields; ++field) { 10853 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10854 } 10855 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10856 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); 10857 for (c = cStart; c < cEnd; ++c) { 10858 const PetscScalar *x; 10859 PetscInt i; 10860 10861 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10862 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10863 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10864 for (i = 0; i < cellDof; ++i) { 10865 u[c*cellDof+i] = x[i]; 10866 } 10867 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10868 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10869 for (i = 0; i < cellDof; ++i) { 10870 a[c*cellDof+i] = x[i]; 10871 } 10872 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10873 } 10874 for (field = 0; field < numFields; ++field) { 10875 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10876 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10877 /* Conforming batches */ 10878 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10879 PetscInt numBlocks = 1; 10880 PetscInt batchSize = numBlocks * blockSize; 10881 PetscInt numBatches = numBatchesTmp; 10882 PetscInt numChunks = numCells / (numBatches*batchSize); 10883 /* Remainder */ 10884 PetscInt numRemainder = numCells % (numBatches * batchSize); 10885 PetscInt offset = numCells - numRemainder; 10886 10887 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); 10888 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], 10889 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10890 } 10891 for (c = cStart; c < cEnd; ++c) { 10892 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10893 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10894 } 10895 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10896 if (mesh->printFEM) { 10897 PetscMPIInt rank, numProcs; 10898 PetscInt p; 10899 10900 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10901 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10902 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10903 for (p = 0; p < numProcs; ++p) { 10904 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10905 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10906 } 10907 } 10908 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10909 PetscFunctionReturn(0); 10910 } 10911 10912 #undef __FUNCT__ 10913 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10914 /*@ 10915 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10916 10917 Input Parameters: 10918 + dm - The mesh 10919 . X - Local input vector 10920 - user - The user context 10921 10922 Output Parameter: 10923 . Jac - Jacobian matrix 10924 10925 Note: 10926 The second member of the user context must be an FEMContext. 10927 10928 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10929 like a GPU, or vectorize on a multicore machine. 10930 10931 .seealso: FormFunctionLocal() 10932 */ 10933 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10934 { 10935 DM_Plex *mesh = (DM_Plex *) dm->data; 10936 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10937 PetscQuadrature *quad = fem->quad; 10938 PetscSection section; 10939 PetscReal *v0, *J, *invJ, *detJ; 10940 PetscScalar *elemMat, *u; 10941 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10942 PetscInt cellDof = 0, numComponents = 0; 10943 PetscBool isShell; 10944 PetscErrorCode ierr; 10945 10946 PetscFunctionBegin; 10947 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10948 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10949 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10950 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10951 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10952 numCells = cEnd - cStart; 10953 for (field = 0; field < numFields; ++field) { 10954 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10955 numComponents += quad[field].numComponents; 10956 } 10957 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10958 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10959 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); 10960 for (c = cStart; c < cEnd; ++c) { 10961 const PetscScalar *x; 10962 PetscInt i; 10963 10964 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10965 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10966 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10967 10968 for (i = 0; i < cellDof; ++i) { 10969 u[c*cellDof+i] = x[i]; 10970 } 10971 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10972 } 10973 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10974 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10975 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10976 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10977 PetscInt fieldJ; 10978 10979 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10980 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10981 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10982 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10983 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10984 /* Conforming batches */ 10985 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10986 PetscInt numBlocks = 1; 10987 PetscInt batchSize = numBlocks * blockSize; 10988 PetscInt numBatches = numBatchesTmp; 10989 PetscInt numChunks = numCells / (numBatches*batchSize); 10990 /* Remainder */ 10991 PetscInt numRemainder = numCells % (numBatches * batchSize); 10992 PetscInt offset = numCells - numRemainder; 10993 10994 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10995 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10996 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10997 } 10998 } 10999 for (c = cStart; c < cEnd; ++c) { 11000 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 11001 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 11002 } 11003 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 11004 11005 /* Assemble matrix, using the 2-step process: 11006 MatAssemblyBegin(), MatAssemblyEnd(). */ 11007 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11008 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11009 11010 if (mesh->printFEM) { 11011 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 11012 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 11013 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 11014 } 11015 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 11016 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 11017 if (isShell) { 11018 JacActionCtx *jctx; 11019 11020 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 11021 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 11022 } 11023 *str = SAME_NONZERO_PATTERN; 11024 PetscFunctionReturn(0); 11025 } 11026 11027 11028 #undef __FUNCT__ 11029 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 11030 /*@C 11031 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 11032 the local section and an SF describing the section point overlap. 11033 11034 Input Parameters: 11035 + s - The PetscSection for the local field layout 11036 . sf - The SF describing parallel layout of the section points 11037 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 11038 . label - The label specifying the points 11039 - labelValue - The label stratum specifying the points 11040 11041 Output Parameter: 11042 . gsection - The PetscSection for the global field layout 11043 11044 Note: This gives negative sizes and offsets to points not owned by this process 11045 11046 Level: developer 11047 11048 .seealso: PetscSectionCreate() 11049 @*/ 11050 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 11051 { 11052 PetscInt *neg; 11053 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 11054 PetscErrorCode ierr; 11055 11056 PetscFunctionBegin; 11057 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 11058 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 11059 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 11060 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 11061 /* Mark ghost points with negative dof */ 11062 for (p = pStart; p < pEnd; ++p) { 11063 PetscInt value; 11064 11065 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 11066 if (value != labelValue) continue; 11067 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 11068 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 11069 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 11070 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 11071 neg[p-pStart] = -(dof+1); 11072 } 11073 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 11074 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 11075 if (nroots >= 0) { 11076 if (nroots > pEnd - pStart) { 11077 PetscInt *tmpDof; 11078 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11079 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 11080 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11081 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11082 for (p = pStart; p < pEnd; ++p) { 11083 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 11084 } 11085 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 11086 } else { 11087 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11088 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11089 } 11090 } 11091 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 11092 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11093 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 11094 (*gsection)->atlasOff[p] = off; 11095 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 11096 } 11097 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 11098 globalOff -= off; 11099 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11100 (*gsection)->atlasOff[p] += globalOff; 11101 neg[p] = -((*gsection)->atlasOff[p]+1); 11102 } 11103 /* Put in negative offsets for ghost points */ 11104 if (nroots >= 0) { 11105 if (nroots > pEnd - pStart) { 11106 PetscInt *tmpOff; 11107 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11108 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 11109 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11110 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11111 for (p = pStart; p < pEnd; ++p) { 11112 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 11113 } 11114 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 11115 } else { 11116 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11117 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11118 } 11119 } 11120 ierr = PetscFree(neg);CHKERRQ(ierr); 11121 PetscFunctionReturn(0); 11122 } 11123