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