1 #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 4 /* Logging support */ 5 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6 7 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "VecView_Plex_Local" 12 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13 { 14 DM dm; 15 PetscBool isvtk; 16 PetscErrorCode ierr; 17 18 PetscFunctionBegin; 19 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22 if (isvtk) { 23 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24 PetscSection section; 25 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26 27 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39 } else if (cdof && vdof) { 40 SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41 } else if (cdof) { 42 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43 * vector or just happens to have the same number of dofs as the dimension. */ 44 if (cdof == dim) { 45 ft = PETSC_VTK_CELL_VECTOR_FIELD; 46 } else { 47 ft = PETSC_VTK_CELL_FIELD; 48 } 49 } else if (vdof) { 50 if (vdof == dim) { 51 ft = PETSC_VTK_POINT_VECTOR_FIELD; 52 } else { 53 ft = PETSC_VTK_POINT_FIELD; 54 } 55 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56 57 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60 } else { 61 PetscBool isseq; 62 63 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64 if (isseq) { 65 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66 } else { 67 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68 } 69 } 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "VecView_Plex" 75 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76 { 77 DM dm; 78 PetscBool isvtk; 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83 if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85 if (isvtk) { 86 Vec locv; 87 const char *name; 88 89 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96 } else { 97 PetscBool isseq; 98 99 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100 if (isseq) { 101 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102 } else { 103 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104 } 105 } 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexView_Ascii" 111 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112 { 113 DM_Plex *mesh = (DM_Plex *) dm->data; 114 DM cdm; 115 DMLabel markers; 116 PetscSection coordSection; 117 Vec coordinates; 118 PetscViewerFormat format; 119 PetscErrorCode ierr; 120 121 PetscFunctionBegin; 122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127 const char *name; 128 PetscInt maxConeSize, maxSupportSize; 129 PetscInt pStart, pEnd, p; 130 PetscMPIInt rank, size; 131 132 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142 for (p = pStart; p < pEnd; ++p) { 143 PetscInt dof, off, s; 144 145 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147 for (s = off; s < off+dof; ++s) { 148 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149 } 150 } 151 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153 for (p = pStart; p < pEnd; ++p) { 154 PetscInt dof, off, c; 155 156 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158 for (c = off; c < off+dof; ++c) { 159 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160 } 161 } 162 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163 ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166 if (markers) { 167 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 168 } 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for (c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = PETSC_NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm = ((PetscObject) dm)->comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 284 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 285 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 286 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 287 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 288 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 289 if (depth == 1) { 290 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 291 pEnd = pEnd - pStart; 292 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 293 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 294 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 295 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 296 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 297 pEnd = pEnd - pStart; 298 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 299 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 300 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 301 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 302 } else { 303 for (d = 0; d <= dim; d++) { 304 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 305 pEnd = pEnd - pStart; 306 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 307 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 308 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 309 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 310 } 311 } 312 ierr = PetscFree(sizes);CHKERRQ(ierr); 313 } 314 PetscFunctionReturn(0); 315 } 316 317 #undef __FUNCT__ 318 #define __FUNCT__ "DMView_Plex" 319 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 320 { 321 PetscBool iascii, isbinary; 322 PetscErrorCode ierr; 323 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 326 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 327 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 329 if (iascii) { 330 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 331 #if 0 332 } else if (isbinary) { 333 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 334 #endif 335 } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name); 336 PetscFunctionReturn(0); 337 } 338 339 #undef __FUNCT__ 340 #define __FUNCT__ "DMDestroy_Plex" 341 PetscErrorCode DMDestroy_Plex(DM dm) 342 { 343 DM_Plex *mesh = (DM_Plex *) dm->data; 344 DMLabel next = mesh->labels; 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 if (--mesh->refct > 0) {PetscFunctionReturn(0);} 349 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 350 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 352 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 353 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 355 while (next) { 356 DMLabel tmp = next->next; 357 358 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 359 next = tmp; 360 } 361 ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 362 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 364 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 365 ierr = PetscFree(mesh);CHKERRQ(ierr); 366 PetscFunctionReturn(0); 367 } 368 369 #undef __FUNCT__ 370 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 371 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 372 { 373 const PetscInt *support = PETSC_NULL; 374 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 if (useClosure) { 379 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 380 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 381 for (s = 0; s < supportSize; ++s) { 382 const PetscInt *cone = PETSC_NULL; 383 PetscInt coneSize, c, q; 384 385 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 386 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 387 for (c = 0; c < coneSize; ++c) { 388 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 389 if (cone[c] == adj[q]) break; 390 } 391 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 392 } 393 } 394 } else { 395 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 396 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 397 for (s = 0; s < supportSize; ++s) { 398 const PetscInt *cone = PETSC_NULL; 399 PetscInt coneSize, c, q; 400 401 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 402 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 403 for (c = 0; c < coneSize; ++c) { 404 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 405 if (cone[c] == adj[q]) break; 406 } 407 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 408 } 409 } 410 } 411 *adjSize = numAdj; 412 PetscFunctionReturn(0); 413 } 414 415 #undef __FUNCT__ 416 #define __FUNCT__ "DMPlexGetAdjacency_Private" 417 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 418 { 419 const PetscInt *star = tmpClosure; 420 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 421 PetscErrorCode ierr; 422 423 PetscFunctionBegin; 424 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 425 for (s = 2; s < starSize*2; s += 2) { 426 const PetscInt *closure = PETSC_NULL; 427 PetscInt closureSize, c, q; 428 429 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 430 for (c = 0; c < closureSize*2; c += 2) { 431 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 432 if (closure[c] == adj[q]) break; 433 } 434 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 435 } 436 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 437 } 438 *adjSize = numAdj; 439 PetscFunctionReturn(0); 440 } 441 442 #undef __FUNCT__ 443 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 444 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 445 { 446 DM_Plex *mesh = (DM_Plex *) dm->data; 447 448 PetscFunctionBegin; 449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 450 mesh->preallocCenterDim = preallocCenterDim; 451 PetscFunctionReturn(0); 452 } 453 454 #undef __FUNCT__ 455 #define __FUNCT__ "DMPlexPreallocateOperator" 456 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 457 { 458 DM_Plex *mesh = (DM_Plex *) dm->data; 459 MPI_Comm comm = ((PetscObject) dm)->comm; 460 PetscSF sf, sfDof, sfAdj; 461 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 462 PetscInt nleaves, l, p; 463 const PetscInt *leaves; 464 const PetscSFNode *remotes; 465 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 466 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 467 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 468 PetscLayout rLayout; 469 PetscInt locRows, rStart, rEnd, r; 470 PetscMPIInt size; 471 PetscBool useClosure, debug = PETSC_FALSE; 472 PetscErrorCode ierr; 473 474 PetscFunctionBegin; 475 ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 476 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 477 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 478 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 479 /* Create dof SF based on point SF */ 480 if (debug) { 481 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 482 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 483 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 487 } 488 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 489 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 490 if (debug) { 491 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 492 ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 493 } 494 /* Create section for dof adjacency (dof ==> # adj dof) */ 495 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 496 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 497 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 498 if (mesh->preallocCenterDim == dim) { 499 useClosure = PETSC_FALSE; 500 } else if (mesh->preallocCenterDim == 0) { 501 useClosure = PETSC_TRUE; 502 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 503 504 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 505 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 506 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 507 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 510 /* Fill in the ghost dofs on the interface */ 511 ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 512 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 513 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 514 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 515 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 516 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 517 518 /* 519 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 520 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 521 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 522 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 523 Create sfAdj connecting rootSectionAdj and leafSectionAdj 524 3. Visit unowned points on interface, write adjacencies to adj 525 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 526 4. Visit owned points on interface, write adjacencies to rootAdj 527 Remove redundancy in rootAdj 528 ** The last two traversals use transitive closure 529 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 530 Allocate memory addressed by sectionAdj (cols) 531 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 532 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 533 */ 534 535 for (l = 0; l < nleaves; ++l) { 536 PetscInt dof, off, d, q; 537 PetscInt p = leaves[l], numAdj = maxAdjSize; 538 539 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 540 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 541 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 542 for (q = 0; q < numAdj; ++q) { 543 PetscInt ndof, ncdof; 544 545 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 546 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 547 for (d = off; d < off+dof; ++d) { 548 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 549 } 550 } 551 } 552 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 553 if (debug) { 554 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 555 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 556 } 557 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 558 if (size > 1) { 559 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 560 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 561 } 562 if (debug) { 563 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 564 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 565 } 566 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 567 for (p = pStart; p < pEnd; ++p) { 568 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 569 570 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 571 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 572 if (!dof) continue; 573 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 574 if (adof <= 0) continue; 575 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 576 for (q = 0; q < numAdj; ++q) { 577 PetscInt ndof, ncdof; 578 579 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 580 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 581 for (d = off; d < off+dof; ++d) { 582 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 583 } 584 } 585 } 586 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 587 if (debug) { 588 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 589 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 590 } 591 /* Create adj SF based on dof SF */ 592 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 593 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 594 if (debug) { 595 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 596 ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 597 } 598 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 599 /* Create leaf adjacency */ 600 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 601 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 602 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 603 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 604 for (l = 0; l < nleaves; ++l) { 605 PetscInt dof, off, d, q; 606 PetscInt p = leaves[l], numAdj = maxAdjSize; 607 608 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 609 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 610 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 611 for (d = off; d < off+dof; ++d) { 612 PetscInt aoff, i = 0; 613 614 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 615 for (q = 0; q < numAdj; ++q) { 616 PetscInt ndof, ncdof, ngoff, nd; 617 618 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 619 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 620 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 621 for (nd = 0; nd < ndof-ncdof; ++nd) { 622 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 623 ++i; 624 } 625 } 626 } 627 } 628 /* Debugging */ 629 if (debug) { 630 IS tmp; 631 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 632 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 633 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 634 } 635 /* Gather adjacenct indices to root */ 636 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 637 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 638 for (r = 0; r < adjSize; ++r) { 639 rootAdj[r] = -1; 640 } 641 if (size > 1) { 642 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 643 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 644 } 645 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 646 ierr = PetscFree(adj);CHKERRQ(ierr); 647 /* Debugging */ 648 if (debug) { 649 IS tmp; 650 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 651 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 652 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 653 } 654 /* Add in local adjacency indices for owned dofs on interface (roots) */ 655 for (p = pStart; p < pEnd; ++p) { 656 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 657 658 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 659 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 660 if (!dof) continue; 661 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 662 if (adof <= 0) continue; 663 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 664 for (d = off; d < off+dof; ++d) { 665 PetscInt adof, aoff, i; 666 667 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 668 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 669 i = adof-1; 670 for (q = 0; q < numAdj; ++q) { 671 PetscInt ndof, ncdof, ngoff, nd; 672 673 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 674 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 675 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 676 for (nd = 0; nd < ndof-ncdof; ++nd) { 677 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 678 --i; 679 } 680 } 681 } 682 } 683 /* Debugging */ 684 if (debug) { 685 IS tmp; 686 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 687 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 688 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 689 } 690 /* Compress indices */ 691 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 692 for (p = pStart; p < pEnd; ++p) { 693 PetscInt dof, cdof, off, d; 694 PetscInt adof, aoff; 695 696 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 697 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 698 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 699 if (!dof) continue; 700 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 701 if (adof <= 0) continue; 702 for (d = off; d < off+dof-cdof; ++d) { 703 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 704 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 705 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 706 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 707 } 708 } 709 /* Debugging */ 710 if (debug) { 711 IS tmp; 712 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 713 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 714 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 715 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 716 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 717 } 718 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 719 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 720 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 721 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 722 for (p = pStart; p < pEnd; ++p) { 723 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 724 PetscBool found = PETSC_TRUE; 725 726 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 727 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 728 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 729 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 730 for (d = 0; d < dof-cdof; ++d) { 731 PetscInt ldof, rdof; 732 733 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 734 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 735 if (ldof > 0) { 736 /* We do not own this point */ 737 } else if (rdof > 0) { 738 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 739 } else { 740 found = PETSC_FALSE; 741 } 742 } 743 if (found) continue; 744 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 745 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 746 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 747 for (q = 0; q < numAdj; ++q) { 748 PetscInt ndof, ncdof, noff; 749 750 /* Adjacent points may not be in the section chart */ 751 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 752 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 753 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 754 ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 755 for (d = goff; d < goff+dof-cdof; ++d) { 756 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 757 } 758 } 759 } 760 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 761 if (debug) { 762 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 763 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 764 } 765 /* Get adjacent indices */ 766 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 767 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 768 for (p = pStart; p < pEnd; ++p) { 769 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 770 PetscBool found = PETSC_TRUE; 771 772 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 773 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 774 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 775 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 776 for (d = 0; d < dof-cdof; ++d) { 777 PetscInt ldof, rdof; 778 779 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 780 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 781 if (ldof > 0) { 782 /* We do not own this point */ 783 } else if (rdof > 0) { 784 PetscInt aoff, roff; 785 786 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 787 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 788 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 789 } else { 790 found = PETSC_FALSE; 791 } 792 } 793 if (found) continue; 794 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 795 for (d = goff; d < goff+dof-cdof; ++d) { 796 PetscInt adof, aoff, i = 0; 797 798 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 799 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 800 for (q = 0; q < numAdj; ++q) { 801 PetscInt ndof, ncdof, ngoff, nd; 802 const PetscInt *ncind; 803 804 /* Adjacent points may not be in the section chart */ 805 if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 806 ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 807 ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 808 ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 809 ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 810 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 811 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 812 } 813 } 814 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 815 } 816 } 817 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 818 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 819 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 820 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 821 /* Debugging */ 822 if (debug) { 823 IS tmp; 824 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 825 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 826 ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 827 } 828 /* Create allocation vectors from adjacency graph */ 829 ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 830 ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 831 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 832 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 833 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 834 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 835 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 836 /* Only loop over blocks of rows */ 837 if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 838 for (r = rStart/bs; r < rEnd/bs; ++r) { 839 const PetscInt row = r*bs; 840 PetscInt numCols, cStart, c; 841 842 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 843 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 844 for (c = cStart; c < cStart+numCols; ++c) { 845 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 846 ++dnz[r-rStart]; 847 if (cols[c] >= row) {++dnzu[r-rStart];} 848 } else { 849 ++onz[r-rStart]; 850 if (cols[c] >= row) {++onzu[r-rStart];} 851 } 852 } 853 } 854 if (bs > 1) { 855 for (r = 0; r < locRows/bs; ++r) { 856 dnz[r] /= bs; 857 onz[r] /= bs; 858 dnzu[r] /= bs; 859 onzu[r] /= bs; 860 } 861 } 862 /* Set matrix pattern */ 863 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 864 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 865 /* Fill matrix with zeros */ 866 if (fillMatrix) { 867 PetscScalar *values; 868 PetscInt maxRowLen = 0; 869 870 for (r = rStart; r < rEnd; ++r) { 871 PetscInt len; 872 873 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 874 maxRowLen = PetscMax(maxRowLen, len); 875 } 876 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 877 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 878 for (r = rStart; r < rEnd; ++r) { 879 PetscInt numCols, cStart; 880 881 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 882 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 883 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 884 } 885 ierr = PetscFree(values);CHKERRQ(ierr); 886 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 887 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 888 } 889 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 890 ierr = PetscFree(cols);CHKERRQ(ierr); 891 PetscFunctionReturn(0); 892 } 893 894 #if 0 895 #undef __FUNCT__ 896 #define __FUNCT__ "DMPlexPreallocateOperator_2" 897 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 898 { 899 PetscErrorCode ierr; 900 PetscInt c,cStart,cEnd,pStart,pEnd; 901 PetscInt *tmpClosure,*tmpAdj,*visits; 902 903 PetscFunctionBegin; 904 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 905 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 906 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 907 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 908 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 909 npoints = pEnd - pStart; 910 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 911 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 912 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 913 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 914 for (c=cStart; c<cEnd; c++) { 915 PetscInt *support = tmpClosure; 916 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 917 for (p=0; p<supportSize; p++) { 918 lvisits[support[p]]++; 919 } 920 } 921 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 922 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 923 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 924 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 925 926 ierr = PetscSFGetRanks();CHKERRQ(ierr); 927 928 929 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 930 for (c=cStart; c<cEnd; c++) { 931 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 932 /* 933 Depth-first walk of transitive closure. 934 At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 935 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 936 */ 937 } 938 939 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 940 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 941 PetscFunctionReturn(0); 942 } 943 #endif 944 945 #undef __FUNCT__ 946 #define __FUNCT__ "DMCreateMatrix_Plex" 947 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 948 { 949 PetscSection section, sectionGlobal; 950 PetscInt bs = -1; 951 PetscInt localSize; 952 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 953 PetscErrorCode ierr; 954 955 PetscFunctionBegin; 956 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 957 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 958 #endif 959 if (!mtype) mtype = MATAIJ; 960 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 961 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 962 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 963 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 964 ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 965 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 966 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 967 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 968 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 969 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 970 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 971 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 972 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 973 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 974 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 975 /* Check for symmetric storage */ 976 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 977 if (isSymmetric) { 978 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 979 } 980 if (!isShell) { 981 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 982 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal; 983 984 if (bs < 0) { 985 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 986 PetscInt pStart, pEnd, p, dof; 987 988 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 989 for (p = pStart; p < pEnd; ++p) { 990 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 991 if (dof) { 992 bs = dof; 993 break; 994 } 995 } 996 } else { 997 bs = 1; 998 } 999 /* Must have same blocksize on all procs (some might have no points) */ 1000 bsLocal = bs; 1001 ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1002 } 1003 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1004 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1005 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1006 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1007 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1008 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1009 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1010 } 1011 PetscFunctionReturn(0); 1012 } 1013 1014 #undef __FUNCT__ 1015 #define __FUNCT__ "DMPlexGetDimension" 1016 /*@ 1017 DMPlexGetDimension - Return the topological mesh dimension 1018 1019 Not collective 1020 1021 Input Parameter: 1022 . mesh - The DMPlex 1023 1024 Output Parameter: 1025 . dim - The topological mesh dimension 1026 1027 Level: beginner 1028 1029 .seealso: DMPlexCreate() 1030 @*/ 1031 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1032 { 1033 DM_Plex *mesh = (DM_Plex *) dm->data; 1034 1035 PetscFunctionBegin; 1036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1037 PetscValidPointer(dim, 2); 1038 *dim = mesh->dim; 1039 PetscFunctionReturn(0); 1040 } 1041 1042 #undef __FUNCT__ 1043 #define __FUNCT__ "DMPlexSetDimension" 1044 /*@ 1045 DMPlexSetDimension - Set the topological mesh dimension 1046 1047 Collective on mesh 1048 1049 Input Parameters: 1050 + mesh - The DMPlex 1051 - dim - The topological mesh dimension 1052 1053 Level: beginner 1054 1055 .seealso: DMPlexCreate() 1056 @*/ 1057 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1058 { 1059 DM_Plex *mesh = (DM_Plex *) dm->data; 1060 1061 PetscFunctionBegin; 1062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1063 PetscValidLogicalCollectiveInt(dm, dim, 2); 1064 mesh->dim = dim; 1065 mesh->preallocCenterDim = dim; 1066 PetscFunctionReturn(0); 1067 } 1068 1069 #undef __FUNCT__ 1070 #define __FUNCT__ "DMPlexGetChart" 1071 /*@ 1072 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1073 1074 Not collective 1075 1076 Input Parameter: 1077 . mesh - The DMPlex 1078 1079 Output Parameters: 1080 + pStart - The first mesh point 1081 - pEnd - The upper bound for mesh points 1082 1083 Level: beginner 1084 1085 .seealso: DMPlexCreate(), DMPlexSetChart() 1086 @*/ 1087 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1088 { 1089 DM_Plex *mesh = (DM_Plex *) dm->data; 1090 PetscErrorCode ierr; 1091 1092 PetscFunctionBegin; 1093 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1094 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1095 PetscFunctionReturn(0); 1096 } 1097 1098 #undef __FUNCT__ 1099 #define __FUNCT__ "DMPlexSetChart" 1100 /*@ 1101 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1102 1103 Not collective 1104 1105 Input Parameters: 1106 + mesh - The DMPlex 1107 . pStart - The first mesh point 1108 - pEnd - The upper bound for mesh points 1109 1110 Output Parameters: 1111 1112 Level: beginner 1113 1114 .seealso: DMPlexCreate(), DMPlexGetChart() 1115 @*/ 1116 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1117 { 1118 DM_Plex *mesh = (DM_Plex *) dm->data; 1119 PetscErrorCode ierr; 1120 1121 PetscFunctionBegin; 1122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1123 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1124 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1125 PetscFunctionReturn(0); 1126 } 1127 1128 #undef __FUNCT__ 1129 #define __FUNCT__ "DMPlexGetConeSize" 1130 /*@ 1131 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1132 1133 Not collective 1134 1135 Input Parameters: 1136 + mesh - The DMPlex 1137 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1138 1139 Output Parameter: 1140 . size - The cone size for point p 1141 1142 Level: beginner 1143 1144 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1145 @*/ 1146 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1147 { 1148 DM_Plex *mesh = (DM_Plex *) dm->data; 1149 PetscErrorCode ierr; 1150 1151 PetscFunctionBegin; 1152 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1153 PetscValidPointer(size, 3); 1154 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1155 PetscFunctionReturn(0); 1156 } 1157 1158 #undef __FUNCT__ 1159 #define __FUNCT__ "DMPlexSetConeSize" 1160 /*@ 1161 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1162 1163 Not collective 1164 1165 Input Parameters: 1166 + mesh - The DMPlex 1167 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1168 - size - The cone size for point p 1169 1170 Output Parameter: 1171 1172 Note: 1173 This should be called after DMPlexSetChart(). 1174 1175 Level: beginner 1176 1177 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1178 @*/ 1179 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1180 { 1181 DM_Plex *mesh = (DM_Plex *) dm->data; 1182 PetscErrorCode ierr; 1183 1184 PetscFunctionBegin; 1185 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1186 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1187 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1188 PetscFunctionReturn(0); 1189 } 1190 1191 #undef __FUNCT__ 1192 #define __FUNCT__ "DMPlexGetCone" 1193 /*@C 1194 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1195 1196 Not collective 1197 1198 Input Parameters: 1199 + mesh - The DMPlex 1200 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1201 1202 Output Parameter: 1203 . cone - An array of points which are on the in-edges for point p 1204 1205 Level: beginner 1206 1207 Note: 1208 This routine is not available in Fortran. 1209 1210 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1211 @*/ 1212 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1213 { 1214 DM_Plex *mesh = (DM_Plex *) dm->data; 1215 PetscInt off; 1216 PetscErrorCode ierr; 1217 1218 PetscFunctionBegin; 1219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1220 PetscValidPointer(cone, 3); 1221 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1222 *cone = &mesh->cones[off]; 1223 PetscFunctionReturn(0); 1224 } 1225 1226 #undef __FUNCT__ 1227 #define __FUNCT__ "DMPlexSetCone" 1228 /*@ 1229 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1230 1231 Not collective 1232 1233 Input Parameters: 1234 + mesh - The DMPlex 1235 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1236 - cone - An array of points which are on the in-edges for point p 1237 1238 Output Parameter: 1239 1240 Note: 1241 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1242 1243 Level: beginner 1244 1245 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1246 @*/ 1247 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1248 { 1249 DM_Plex *mesh = (DM_Plex *) dm->data; 1250 PetscInt pStart, pEnd; 1251 PetscInt dof, off, c; 1252 PetscErrorCode ierr; 1253 1254 PetscFunctionBegin; 1255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1256 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1257 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1258 if (dof) PetscValidPointer(cone, 3); 1259 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1260 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1261 for (c = 0; c < dof; ++c) { 1262 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1263 mesh->cones[off+c] = cone[c]; 1264 } 1265 PetscFunctionReturn(0); 1266 } 1267 1268 #undef __FUNCT__ 1269 #define __FUNCT__ "DMPlexGetConeOrientation" 1270 /*@C 1271 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1272 1273 Not collective 1274 1275 Input Parameters: 1276 + mesh - The DMPlex 1277 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1278 1279 Output Parameter: 1280 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1281 integer giving the prescription for cone traversal. If it is negative, the cone is 1282 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1283 the index of the cone point on which to start. 1284 1285 Level: beginner 1286 1287 Note: 1288 This routine is not available in Fortran. 1289 1290 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1291 @*/ 1292 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1293 { 1294 DM_Plex *mesh = (DM_Plex *) dm->data; 1295 PetscInt off; 1296 PetscErrorCode ierr; 1297 1298 PetscFunctionBegin; 1299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1300 #if defined(PETSC_USE_DEBUG) 1301 { 1302 PetscInt dof; 1303 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1304 if (dof) PetscValidPointer(coneOrientation, 3); 1305 } 1306 #endif 1307 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1308 *coneOrientation = &mesh->coneOrientations[off]; 1309 PetscFunctionReturn(0); 1310 } 1311 1312 #undef __FUNCT__ 1313 #define __FUNCT__ "DMPlexSetConeOrientation" 1314 /*@ 1315 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1316 1317 Not collective 1318 1319 Input Parameters: 1320 + mesh - The DMPlex 1321 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1322 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1323 integer giving the prescription for cone traversal. If it is negative, the cone is 1324 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1325 the index of the cone point on which to start. 1326 1327 Output Parameter: 1328 1329 Note: 1330 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1331 1332 Level: beginner 1333 1334 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1335 @*/ 1336 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1337 { 1338 DM_Plex *mesh = (DM_Plex *) dm->data; 1339 PetscInt pStart, pEnd; 1340 PetscInt dof, off, c; 1341 PetscErrorCode ierr; 1342 1343 PetscFunctionBegin; 1344 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1345 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1346 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1347 if (dof) PetscValidPointer(coneOrientation, 3); 1348 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1349 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1350 for (c = 0; c < dof; ++c) { 1351 PetscInt cdof, o = coneOrientation[c]; 1352 1353 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1354 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1355 mesh->coneOrientations[off+c] = o; 1356 } 1357 PetscFunctionReturn(0); 1358 } 1359 1360 #undef __FUNCT__ 1361 #define __FUNCT__ "DMPlexInsertCone" 1362 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1363 { 1364 DM_Plex *mesh = (DM_Plex *) dm->data; 1365 PetscInt pStart, pEnd; 1366 PetscInt dof, off; 1367 PetscErrorCode ierr; 1368 1369 PetscFunctionBegin; 1370 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1371 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1372 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1373 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1374 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1375 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1376 if (conePos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1377 mesh->cones[off+conePos] = conePoint; 1378 PetscFunctionReturn(0); 1379 } 1380 1381 #undef __FUNCT__ 1382 #define __FUNCT__ "DMPlexGetSupportSize" 1383 /*@ 1384 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1385 1386 Not collective 1387 1388 Input Parameters: 1389 + mesh - The DMPlex 1390 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1391 1392 Output Parameter: 1393 . size - The support size for point p 1394 1395 Level: beginner 1396 1397 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1398 @*/ 1399 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1400 { 1401 DM_Plex *mesh = (DM_Plex *) dm->data; 1402 PetscErrorCode ierr; 1403 1404 PetscFunctionBegin; 1405 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1406 PetscValidPointer(size, 3); 1407 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1408 PetscFunctionReturn(0); 1409 } 1410 1411 #undef __FUNCT__ 1412 #define __FUNCT__ "DMPlexSetSupportSize" 1413 /*@ 1414 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1415 1416 Not collective 1417 1418 Input Parameters: 1419 + mesh - The DMPlex 1420 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1421 - size - The support size for point p 1422 1423 Output Parameter: 1424 1425 Note: 1426 This should be called after DMPlexSetChart(). 1427 1428 Level: beginner 1429 1430 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1431 @*/ 1432 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1433 { 1434 DM_Plex *mesh = (DM_Plex *) dm->data; 1435 PetscErrorCode ierr; 1436 1437 PetscFunctionBegin; 1438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1439 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1440 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1441 PetscFunctionReturn(0); 1442 } 1443 1444 #undef __FUNCT__ 1445 #define __FUNCT__ "DMPlexGetSupport" 1446 /*@C 1447 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1448 1449 Not collective 1450 1451 Input Parameters: 1452 + mesh - The DMPlex 1453 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1454 1455 Output Parameter: 1456 . support - An array of points which are on the out-edges for point p 1457 1458 Level: beginner 1459 1460 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1461 @*/ 1462 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1463 { 1464 DM_Plex *mesh = (DM_Plex *) dm->data; 1465 PetscInt off; 1466 PetscErrorCode ierr; 1467 1468 PetscFunctionBegin; 1469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1470 PetscValidPointer(support, 3); 1471 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1472 *support = &mesh->supports[off]; 1473 PetscFunctionReturn(0); 1474 } 1475 1476 #undef __FUNCT__ 1477 #define __FUNCT__ "DMPlexSetSupport" 1478 /*@ 1479 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1480 1481 Not collective 1482 1483 Input Parameters: 1484 + mesh - The DMPlex 1485 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1486 - support - An array of points which are on the in-edges for point p 1487 1488 Output Parameter: 1489 1490 Note: 1491 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1492 1493 Level: beginner 1494 1495 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1496 @*/ 1497 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1498 { 1499 DM_Plex *mesh = (DM_Plex *) dm->data; 1500 PetscInt pStart, pEnd; 1501 PetscInt dof, off, c; 1502 PetscErrorCode ierr; 1503 1504 PetscFunctionBegin; 1505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1506 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1507 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1508 if (dof) PetscValidPointer(support, 3); 1509 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1510 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1511 for (c = 0; c < dof; ++c) { 1512 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1513 mesh->supports[off+c] = support[c]; 1514 } 1515 PetscFunctionReturn(0); 1516 } 1517 1518 #undef __FUNCT__ 1519 #define __FUNCT__ "DMPlexInsertSupport" 1520 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1521 { 1522 DM_Plex *mesh = (DM_Plex *) dm->data; 1523 PetscInt pStart, pEnd; 1524 PetscInt dof, off; 1525 PetscErrorCode ierr; 1526 1527 PetscFunctionBegin; 1528 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1529 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1530 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1531 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1532 if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1533 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1534 if (supportPos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1535 mesh->supports[off+supportPos] = supportPoint; 1536 PetscFunctionReturn(0); 1537 } 1538 1539 #undef __FUNCT__ 1540 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1541 /*@C 1542 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1543 1544 Not collective 1545 1546 Input Parameters: 1547 + mesh - The DMPlex 1548 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1549 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1550 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1551 1552 Output Parameters: 1553 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1554 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1555 1556 Note: 1557 If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1558 1559 Level: beginner 1560 1561 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1562 @*/ 1563 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1564 { 1565 DM_Plex *mesh = (DM_Plex *) dm->data; 1566 PetscInt *closure, *fifo; 1567 const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1568 PetscInt tmpSize, t; 1569 PetscInt depth = 0, maxSize; 1570 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1571 PetscErrorCode ierr; 1572 1573 PetscFunctionBegin; 1574 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1575 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1576 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1577 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1578 if (*points) { 1579 closure = *points; 1580 } else { 1581 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1582 } 1583 closure[0] = p; closure[1] = 0; 1584 /* This is only 1-level */ 1585 if (useCone) { 1586 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1587 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1588 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1589 } else { 1590 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1591 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1592 } 1593 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1594 const PetscInt cp = tmp[t]; 1595 const PetscInt co = tmpO ? tmpO[t] : 0; 1596 1597 closure[closureSize] = cp; 1598 closure[closureSize+1] = co; 1599 fifo[fifoSize] = cp; 1600 fifo[fifoSize+1] = co; 1601 } 1602 while (fifoSize - fifoStart) { 1603 const PetscInt q = fifo[fifoStart]; 1604 const PetscInt o = fifo[fifoStart+1]; 1605 const PetscInt rev = o >= 0 ? 0 : 1; 1606 const PetscInt off = rev ? -(o+1) : o; 1607 1608 if (useCone) { 1609 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1610 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1611 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1612 } else { 1613 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1614 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1615 tmpO = PETSC_NULL; 1616 } 1617 for (t = 0; t < tmpSize; ++t) { 1618 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1619 const PetscInt cp = tmp[i]; 1620 /* Must propogate orientation */ 1621 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1622 PetscInt c; 1623 1624 /* Check for duplicate */ 1625 for (c = 0; c < closureSize; c += 2) { 1626 if (closure[c] == cp) break; 1627 } 1628 if (c == closureSize) { 1629 closure[closureSize] = cp; 1630 closure[closureSize+1] = co; 1631 fifo[fifoSize] = cp; 1632 fifo[fifoSize+1] = co; 1633 closureSize += 2; 1634 fifoSize += 2; 1635 } 1636 } 1637 fifoStart += 2; 1638 } 1639 if (numPoints) *numPoints = closureSize/2; 1640 if (points) *points = closure; 1641 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1642 PetscFunctionReturn(0); 1643 } 1644 1645 #undef __FUNCT__ 1646 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1647 /*@C 1648 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1649 1650 Not collective 1651 1652 Input Parameters: 1653 + mesh - The DMPlex 1654 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1655 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1656 - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1657 1658 Output Parameters: 1659 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1660 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1661 1662 Note: 1663 If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1664 1665 Level: beginner 1666 1667 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1668 @*/ 1669 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1670 { 1671 PetscErrorCode ierr; 1672 1673 PetscFunctionBegin; 1674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1675 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1676 PetscFunctionReturn(0); 1677 } 1678 1679 #undef __FUNCT__ 1680 #define __FUNCT__ "DMPlexGetFaces" 1681 /* 1682 DMPlexGetFaces - 1683 1684 Note: This will only work for cell-vertex meshes. 1685 */ 1686 PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1687 { 1688 DM_Plex *mesh = (DM_Plex *) dm->data; 1689 const PetscInt *cone = PETSC_NULL; 1690 PetscInt depth = 0, dim, coneSize; 1691 PetscErrorCode ierr; 1692 1693 PetscFunctionBegin; 1694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1695 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1696 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1697 if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1698 if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1699 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1700 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1701 switch (dim) { 1702 case 2: 1703 switch (coneSize) { 1704 case 3: 1705 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1706 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1707 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1708 *numFaces = 3; 1709 *faceSize = 2; 1710 *faces = mesh->facesTmp; 1711 break; 1712 case 4: 1713 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1714 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1715 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1716 mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1717 *numFaces = 4; 1718 *faceSize = 2; 1719 *faces = mesh->facesTmp; 1720 break; 1721 default: 1722 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1723 } 1724 break; 1725 case 3: 1726 switch (coneSize) { 1727 case 3: 1728 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1729 mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1730 mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1731 *numFaces = 3; 1732 *faceSize = 2; 1733 *faces = mesh->facesTmp; 1734 break; 1735 case 4: 1736 mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1737 mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1738 mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1739 mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1740 *numFaces = 4; 1741 *faceSize = 3; 1742 *faces = mesh->facesTmp; 1743 break; 1744 default: 1745 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1746 } 1747 break; 1748 default: 1749 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1750 } 1751 PetscFunctionReturn(0); 1752 } 1753 1754 #undef __FUNCT__ 1755 #define __FUNCT__ "DMPlexGetMaxSizes" 1756 /*@ 1757 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1758 1759 Not collective 1760 1761 Input Parameter: 1762 . mesh - The DMPlex 1763 1764 Output Parameters: 1765 + maxConeSize - The maximum number of in-edges 1766 - maxSupportSize - The maximum number of out-edges 1767 1768 Level: beginner 1769 1770 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1771 @*/ 1772 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1773 { 1774 DM_Plex *mesh = (DM_Plex *) dm->data; 1775 1776 PetscFunctionBegin; 1777 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1778 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1779 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1780 PetscFunctionReturn(0); 1781 } 1782 1783 #undef __FUNCT__ 1784 #define __FUNCT__ "DMSetUp_Plex" 1785 PetscErrorCode DMSetUp_Plex(DM dm) 1786 { 1787 DM_Plex *mesh = (DM_Plex *) dm->data; 1788 PetscInt size; 1789 PetscErrorCode ierr; 1790 1791 PetscFunctionBegin; 1792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1793 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1794 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1795 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1796 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1797 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1798 if (mesh->maxSupportSize) { 1799 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1800 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1801 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1802 } 1803 PetscFunctionReturn(0); 1804 } 1805 1806 #undef __FUNCT__ 1807 #define __FUNCT__ "DMCreateSubDM_Plex" 1808 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1809 { 1810 PetscSection section, sectionGlobal; 1811 PetscInt *subIndices; 1812 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1813 PetscErrorCode ierr; 1814 1815 PetscFunctionBegin; 1816 if (!numFields) PetscFunctionReturn(0); 1817 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1818 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1819 if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1820 if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1821 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1822 if (numFields > nF) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1823 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1824 for (p = pStart; p < pEnd; ++p) { 1825 PetscInt gdof; 1826 1827 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1828 if (gdof > 0) { 1829 for (f = 0; f < numFields; ++f) { 1830 PetscInt fdof, fcdof; 1831 1832 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1833 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1834 subSize += fdof-fcdof; 1835 } 1836 } 1837 } 1838 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1839 for (p = pStart; p < pEnd; ++p) { 1840 PetscInt gdof, goff; 1841 1842 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1843 if (gdof > 0) { 1844 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1845 for (f = 0; f < numFields; ++f) { 1846 PetscInt fdof, fcdof, fc, f2, poff = 0; 1847 1848 /* Can get rid of this loop by storing field information in the global section */ 1849 for (f2 = 0; f2 < fields[f]; ++f2) { 1850 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1851 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1852 poff += fdof-fcdof; 1853 } 1854 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1855 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1856 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1857 subIndices[subOff] = goff+poff+fc; 1858 } 1859 } 1860 } 1861 } 1862 if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1863 if (subdm) { 1864 PetscSection subsection; 1865 PetscBool haveNull = PETSC_FALSE; 1866 PetscInt f, nf = 0; 1867 1868 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1869 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1870 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1871 for (f = 0; f < numFields; ++f) { 1872 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1873 if ((*subdm)->nullspaceConstructors[f]) { 1874 haveNull = PETSC_TRUE; 1875 nf = f; 1876 } 1877 } 1878 if (haveNull) { 1879 MatNullSpace nullSpace; 1880 1881 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1882 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1883 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1884 } 1885 if (dm->fields) { 1886 if (nF != dm->numFields) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1887 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1888 for (f = 0; f < numFields; ++f) { 1889 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1890 } 1891 if (numFields == 1) { 1892 MatNullSpace space; 1893 Mat pmat; 1894 1895 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr); 1896 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1897 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr); 1898 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1899 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr); 1900 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1901 } 1902 } 1903 } 1904 PetscFunctionReturn(0); 1905 } 1906 1907 #undef __FUNCT__ 1908 #define __FUNCT__ "DMPlexSymmetrize" 1909 /*@ 1910 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1911 1912 Not collective 1913 1914 Input Parameter: 1915 . mesh - The DMPlex 1916 1917 Output Parameter: 1918 1919 Note: 1920 This should be called after all calls to DMPlexSetCone() 1921 1922 Level: beginner 1923 1924 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1925 @*/ 1926 PetscErrorCode DMPlexSymmetrize(DM dm) 1927 { 1928 DM_Plex *mesh = (DM_Plex *) dm->data; 1929 PetscInt *offsets; 1930 PetscInt supportSize; 1931 PetscInt pStart, pEnd, p; 1932 PetscErrorCode ierr; 1933 1934 PetscFunctionBegin; 1935 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1936 if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1937 /* Calculate support sizes */ 1938 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1939 for (p = pStart; p < pEnd; ++p) { 1940 PetscInt dof, off, c; 1941 1942 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1943 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1944 for (c = off; c < off+dof; ++c) { 1945 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1946 } 1947 } 1948 for (p = pStart; p < pEnd; ++p) { 1949 PetscInt dof; 1950 1951 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1952 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1953 } 1954 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1955 /* Calculate supports */ 1956 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1957 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1958 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1959 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1960 for (p = pStart; p < pEnd; ++p) { 1961 PetscInt dof, off, c; 1962 1963 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1964 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1965 for (c = off; c < off+dof; ++c) { 1966 const PetscInt q = mesh->cones[c]; 1967 PetscInt offS; 1968 1969 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1970 mesh->supports[offS+offsets[q]] = p; 1971 ++offsets[q]; 1972 } 1973 } 1974 ierr = PetscFree(offsets);CHKERRQ(ierr); 1975 PetscFunctionReturn(0); 1976 } 1977 1978 #undef __FUNCT__ 1979 #define __FUNCT__ "DMPlexSetDepth_Private" 1980 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1981 { 1982 PetscInt d; 1983 PetscErrorCode ierr; 1984 1985 PetscFunctionBegin; 1986 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1987 if (d < 0) { 1988 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1989 const PetscInt *cone = PETSC_NULL; 1990 PetscInt dCone; 1991 1992 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1993 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1994 d = dCone+1; 1995 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1996 } 1997 *depth = d; 1998 PetscFunctionReturn(0); 1999 } 2000 2001 #undef __FUNCT__ 2002 #define __FUNCT__ "DMPlexStratify" 2003 /*@ 2004 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2005 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2006 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2007 the DAG. 2008 2009 Not collective 2010 2011 Input Parameter: 2012 . mesh - The DMPlex 2013 2014 Output Parameter: 2015 2016 Notes: 2017 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2018 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2019 2020 This should be called after all calls to DMPlexSymmetrize() 2021 2022 Level: beginner 2023 2024 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2025 @*/ 2026 PetscErrorCode DMPlexStratify(DM dm) 2027 { 2028 DM_Plex *mesh = (DM_Plex *) dm->data; 2029 PetscInt pStart, pEnd, p; 2030 PetscInt numRoots = 0, numLeaves = 0; 2031 PetscErrorCode ierr; 2032 2033 PetscFunctionBegin; 2034 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2035 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2036 /* Calculate depth */ 2037 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2038 /* Initialize roots and count leaves */ 2039 for (p = pStart; p < pEnd; ++p) { 2040 PetscInt coneSize, supportSize; 2041 2042 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2043 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2044 if (!coneSize && supportSize) { 2045 ++numRoots; 2046 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2047 } else if (!supportSize && coneSize) { 2048 ++numLeaves; 2049 } else if (!supportSize && !coneSize) { 2050 /* Isolated points */ 2051 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2052 } 2053 } 2054 if (numRoots + numLeaves == (pEnd - pStart)) { 2055 for (p = pStart; p < pEnd; ++p) { 2056 PetscInt coneSize, supportSize; 2057 2058 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2059 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2060 if (!supportSize && coneSize) { 2061 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2062 } 2063 } 2064 } else { 2065 /* This might be slow since lookup is not fast */ 2066 for (p = pStart; p < pEnd; ++p) { 2067 PetscInt depth; 2068 2069 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2070 } 2071 } 2072 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2073 PetscFunctionReturn(0); 2074 } 2075 2076 #undef __FUNCT__ 2077 #define __FUNCT__ "DMPlexGetJoin" 2078 /*@C 2079 DMPlexGetJoin - Get an array for the join of the set of points 2080 2081 Not Collective 2082 2083 Input Parameters: 2084 + dm - The DMPlex object 2085 . numPoints - The number of input points for the join 2086 - points - The input points 2087 2088 Output Parameters: 2089 + numCoveredPoints - The number of points in the join 2090 - coveredPoints - The points in the join 2091 2092 Level: intermediate 2093 2094 Note: Currently, this is restricted to a single level join 2095 2096 .keywords: mesh 2097 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2098 @*/ 2099 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2100 { 2101 DM_Plex *mesh = (DM_Plex *) dm->data; 2102 PetscInt *join[2]; 2103 PetscInt joinSize, i = 0; 2104 PetscInt dof, off, p, c, m; 2105 PetscErrorCode ierr; 2106 2107 PetscFunctionBegin; 2108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2109 PetscValidPointer(points, 2); 2110 PetscValidPointer(numCoveredPoints, 3); 2111 PetscValidPointer(coveredPoints, 4); 2112 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2113 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2114 /* Copy in support of first point */ 2115 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2116 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2117 for (joinSize = 0; joinSize < dof; ++joinSize) { 2118 join[i][joinSize] = mesh->supports[off+joinSize]; 2119 } 2120 /* Check each successive support */ 2121 for (p = 1; p < numPoints; ++p) { 2122 PetscInt newJoinSize = 0; 2123 2124 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2125 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2126 for (c = 0; c < dof; ++c) { 2127 const PetscInt point = mesh->supports[off+c]; 2128 2129 for (m = 0; m < joinSize; ++m) { 2130 if (point == join[i][m]) { 2131 join[1-i][newJoinSize++] = point; 2132 break; 2133 } 2134 } 2135 } 2136 joinSize = newJoinSize; 2137 i = 1-i; 2138 } 2139 *numCoveredPoints = joinSize; 2140 *coveredPoints = join[i]; 2141 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2142 PetscFunctionReturn(0); 2143 } 2144 2145 #undef __FUNCT__ 2146 #define __FUNCT__ "DMPlexRestoreJoin" 2147 /*@C 2148 DMPlexRestoreJoin - Restore an array for the join of the set of points 2149 2150 Not Collective 2151 2152 Input Parameters: 2153 + dm - The DMPlex object 2154 . numPoints - The number of input points for the join 2155 - points - The input points 2156 2157 Output Parameters: 2158 + numCoveredPoints - The number of points in the join 2159 - coveredPoints - The points in the join 2160 2161 Level: intermediate 2162 2163 .keywords: mesh 2164 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2165 @*/ 2166 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2167 { 2168 PetscErrorCode ierr; 2169 2170 PetscFunctionBegin; 2171 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2172 PetscValidPointer(coveredPoints, 4); 2173 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2174 PetscFunctionReturn(0); 2175 } 2176 2177 #undef __FUNCT__ 2178 #define __FUNCT__ "DMPlexGetFullJoin" 2179 /*@C 2180 DMPlexGetFullJoin - Get an array for the join of the set of points 2181 2182 Not Collective 2183 2184 Input Parameters: 2185 + dm - The DMPlex object 2186 . numPoints - The number of input points for the join 2187 - points - The input points 2188 2189 Output Parameters: 2190 + numCoveredPoints - The number of points in the join 2191 - coveredPoints - The points in the join 2192 2193 Level: intermediate 2194 2195 .keywords: mesh 2196 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2197 @*/ 2198 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2199 { 2200 DM_Plex *mesh = (DM_Plex *) dm->data; 2201 PetscInt *offsets, **closures; 2202 PetscInt *join[2]; 2203 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2204 PetscInt p, d, c, m; 2205 PetscErrorCode ierr; 2206 2207 PetscFunctionBegin; 2208 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2209 PetscValidPointer(points, 2); 2210 PetscValidPointer(numCoveredPoints, 3); 2211 PetscValidPointer(coveredPoints, 4); 2212 2213 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2214 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2215 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2216 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2217 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2218 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2219 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2220 2221 for (p = 0; p < numPoints; ++p) { 2222 PetscInt closureSize; 2223 2224 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2225 offsets[p*(depth+2)+0] = 0; 2226 for (d = 0; d < depth+1; ++d) { 2227 PetscInt pStart, pEnd, i; 2228 2229 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2230 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2231 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2232 offsets[p*(depth+2)+d+1] = i; 2233 break; 2234 } 2235 } 2236 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2237 } 2238 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2239 } 2240 for (d = 0; d < depth+1; ++d) { 2241 PetscInt dof; 2242 2243 /* Copy in support of first point */ 2244 dof = offsets[d+1] - offsets[d]; 2245 for (joinSize = 0; joinSize < dof; ++joinSize) { 2246 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2247 } 2248 /* Check each successive cone */ 2249 for (p = 1; p < numPoints && joinSize; ++p) { 2250 PetscInt newJoinSize = 0; 2251 2252 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2253 for (c = 0; c < dof; ++c) { 2254 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2255 2256 for (m = 0; m < joinSize; ++m) { 2257 if (point == join[i][m]) { 2258 join[1-i][newJoinSize++] = point; 2259 break; 2260 } 2261 } 2262 } 2263 joinSize = newJoinSize; 2264 i = 1-i; 2265 } 2266 if (joinSize) break; 2267 } 2268 *numCoveredPoints = joinSize; 2269 *coveredPoints = join[i]; 2270 for (p = 0; p < numPoints; ++p) { 2271 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2272 } 2273 ierr = PetscFree(closures);CHKERRQ(ierr); 2274 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2275 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2276 PetscFunctionReturn(0); 2277 } 2278 2279 #undef __FUNCT__ 2280 #define __FUNCT__ "DMPlexGetMeet" 2281 /*@C 2282 DMPlexGetMeet - Get an array for the meet of the set of points 2283 2284 Not Collective 2285 2286 Input Parameters: 2287 + dm - The DMPlex object 2288 . numPoints - The number of input points for the meet 2289 - points - The input points 2290 2291 Output Parameters: 2292 + numCoveredPoints - The number of points in the meet 2293 - coveredPoints - The points in the meet 2294 2295 Level: intermediate 2296 2297 Note: Currently, this is restricted to a single level meet 2298 2299 .keywords: mesh 2300 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2301 @*/ 2302 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2303 { 2304 DM_Plex *mesh = (DM_Plex *) dm->data; 2305 PetscInt *meet[2]; 2306 PetscInt meetSize, i = 0; 2307 PetscInt dof, off, p, c, m; 2308 PetscErrorCode ierr; 2309 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2312 PetscValidPointer(points, 2); 2313 PetscValidPointer(numCoveringPoints, 3); 2314 PetscValidPointer(coveringPoints, 4); 2315 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2316 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2317 /* Copy in cone of first point */ 2318 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2319 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2320 for (meetSize = 0; meetSize < dof; ++meetSize) { 2321 meet[i][meetSize] = mesh->cones[off+meetSize]; 2322 } 2323 /* Check each successive cone */ 2324 for (p = 1; p < numPoints; ++p) { 2325 PetscInt newMeetSize = 0; 2326 2327 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2328 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2329 for (c = 0; c < dof; ++c) { 2330 const PetscInt point = mesh->cones[off+c]; 2331 2332 for (m = 0; m < meetSize; ++m) { 2333 if (point == meet[i][m]) { 2334 meet[1-i][newMeetSize++] = point; 2335 break; 2336 } 2337 } 2338 } 2339 meetSize = newMeetSize; 2340 i = 1-i; 2341 } 2342 *numCoveringPoints = meetSize; 2343 *coveringPoints = meet[i]; 2344 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2345 PetscFunctionReturn(0); 2346 } 2347 2348 #undef __FUNCT__ 2349 #define __FUNCT__ "DMPlexRestoreMeet" 2350 /*@C 2351 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2352 2353 Not Collective 2354 2355 Input Parameters: 2356 + dm - The DMPlex object 2357 . numPoints - The number of input points for the meet 2358 - points - The input points 2359 2360 Output Parameters: 2361 + numCoveredPoints - The number of points in the meet 2362 - coveredPoints - The points in the meet 2363 2364 Level: intermediate 2365 2366 .keywords: mesh 2367 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2368 @*/ 2369 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2370 { 2371 PetscErrorCode ierr; 2372 2373 PetscFunctionBegin; 2374 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2375 PetscValidPointer(coveredPoints, 4); 2376 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2377 PetscFunctionReturn(0); 2378 } 2379 2380 #undef __FUNCT__ 2381 #define __FUNCT__ "DMPlexGetFullMeet" 2382 /*@C 2383 DMPlexGetFullMeet - Get an array for the meet of the set of points 2384 2385 Not Collective 2386 2387 Input Parameters: 2388 + dm - The DMPlex object 2389 . numPoints - The number of input points for the meet 2390 - points - The input points 2391 2392 Output Parameters: 2393 + numCoveredPoints - The number of points in the meet 2394 - coveredPoints - The points in the meet 2395 2396 Level: intermediate 2397 2398 .keywords: mesh 2399 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2400 @*/ 2401 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2402 { 2403 DM_Plex *mesh = (DM_Plex *) dm->data; 2404 PetscInt *offsets, **closures; 2405 PetscInt *meet[2]; 2406 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2407 PetscInt p, h, c, m; 2408 PetscErrorCode ierr; 2409 2410 PetscFunctionBegin; 2411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2412 PetscValidPointer(points, 2); 2413 PetscValidPointer(numCoveredPoints, 3); 2414 PetscValidPointer(coveredPoints, 4); 2415 2416 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2417 ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2418 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2419 maxSize = PetscPowInt(mesh->maxConeSize,height); 2420 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2421 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2422 2423 for (p = 0; p < numPoints; ++p) { 2424 PetscInt closureSize; 2425 2426 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2427 offsets[p*(height+2)+0] = 0; 2428 for (h = 0; h < height+1; ++h) { 2429 PetscInt pStart, pEnd, i; 2430 2431 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2432 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2433 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2434 offsets[p*(height+2)+h+1] = i; 2435 break; 2436 } 2437 } 2438 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2439 } 2440 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2441 } 2442 for (h = 0; h < height+1; ++h) { 2443 PetscInt dof; 2444 2445 /* Copy in cone of first point */ 2446 dof = offsets[h+1] - offsets[h]; 2447 for (meetSize = 0; meetSize < dof; ++meetSize) { 2448 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2449 } 2450 /* Check each successive cone */ 2451 for (p = 1; p < numPoints && meetSize; ++p) { 2452 PetscInt newMeetSize = 0; 2453 2454 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2455 for (c = 0; c < dof; ++c) { 2456 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2457 2458 for (m = 0; m < meetSize; ++m) { 2459 if (point == meet[i][m]) { 2460 meet[1-i][newMeetSize++] = point; 2461 break; 2462 } 2463 } 2464 } 2465 meetSize = newMeetSize; 2466 i = 1-i; 2467 } 2468 if (meetSize) break; 2469 } 2470 *numCoveredPoints = meetSize; 2471 *coveredPoints = meet[i]; 2472 for (p = 0; p < numPoints; ++p) { 2473 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2474 } 2475 ierr = PetscFree(closures);CHKERRQ(ierr); 2476 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2477 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2478 PetscFunctionReturn(0); 2479 } 2480 2481 #undef __FUNCT__ 2482 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2483 static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) 2484 { 2485 MPI_Comm comm = ((PetscObject) dm)->comm; 2486 PetscInt cellDim; 2487 PetscErrorCode ierr; 2488 2489 PetscFunctionBegin; 2490 PetscValidPointer(numFaceVertices,3); 2491 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2492 switch (cellDim) { 2493 case 0: 2494 *numFaceVertices = 0; 2495 break; 2496 case 1: 2497 *numFaceVertices = 1; 2498 break; 2499 case 2: 2500 switch (numCorners) { 2501 case 3: /* triangle */ 2502 *numFaceVertices = 2; /* Edge has 2 vertices */ 2503 break; 2504 case 4: /* quadrilateral */ 2505 *numFaceVertices = 2; /* Edge has 2 vertices */ 2506 break; 2507 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2508 *numFaceVertices = 3; /* Edge has 3 vertices */ 2509 break; 2510 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2511 *numFaceVertices = 3; /* Edge has 3 vertices */ 2512 break; 2513 default: 2514 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2515 } 2516 break; 2517 case 3: 2518 switch (numCorners) { 2519 case 4: /* tetradehdron */ 2520 *numFaceVertices = 3; /* Face has 3 vertices */ 2521 break; 2522 case 6: /* tet cohesive cells */ 2523 *numFaceVertices = 4; /* Face has 4 vertices */ 2524 break; 2525 case 8: /* hexahedron */ 2526 *numFaceVertices = 4; /* Face has 4 vertices */ 2527 break; 2528 case 9: /* tet cohesive Lagrange cells */ 2529 *numFaceVertices = 6; /* Face has 6 vertices */ 2530 break; 2531 case 10: /* quadratic tetrahedron */ 2532 *numFaceVertices = 6; /* Face has 6 vertices */ 2533 break; 2534 case 12: /* hex cohesive Lagrange cells */ 2535 *numFaceVertices = 6; /* Face has 6 vertices */ 2536 break; 2537 case 18: /* quadratic tet cohesive Lagrange cells */ 2538 *numFaceVertices = 6; /* Face has 6 vertices */ 2539 break; 2540 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2541 *numFaceVertices = 9; /* Face has 9 vertices */ 2542 break; 2543 default: 2544 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2545 } 2546 break; 2547 default: 2548 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2549 } 2550 PetscFunctionReturn(0); 2551 } 2552 2553 #undef __FUNCT__ 2554 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2555 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2556 { 2557 const PetscInt maxFaceCases = 30; 2558 PetscInt numFaceCases = 0; 2559 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2560 PetscInt *off, *adj; 2561 PetscInt *neighborCells, *tmpClosure; 2562 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2563 PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2564 PetscErrorCode ierr; 2565 2566 PetscFunctionBegin; 2567 /* For parallel partitioning, I think you have to communicate supports */ 2568 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2569 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2570 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2571 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2572 if (cEnd - cStart == 0) { 2573 if (numVertices) *numVertices = 0; 2574 if (offsets) *offsets = PETSC_NULL; 2575 if (adjacency) *adjacency = PETSC_NULL; 2576 PetscFunctionReturn(0); 2577 } 2578 numCells = cEnd - cStart; 2579 /* Setup face recognition */ 2580 { 2581 PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */ 2582 2583 for (c = cStart; c < cEnd; ++c) { 2584 PetscInt corners; 2585 2586 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2587 if (!cornersSeen[corners]) { 2588 PetscInt nFV; 2589 2590 if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2591 cornersSeen[corners] = 1; 2592 ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2593 numFaceVertices[numFaceCases++] = nFV; 2594 } 2595 } 2596 } 2597 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2598 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2599 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2600 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2601 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2602 /* Count neighboring cells */ 2603 for (cell = cStart; cell < cEnd; ++cell) { 2604 PetscInt numNeighbors = maxNeighbors, n; 2605 2606 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2607 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2608 for (n = 0; n < numNeighbors; ++n) { 2609 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2610 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2611 PetscInt meetSize = 0; 2612 const PetscInt *meet = PETSC_NULL; 2613 2614 if (cellPair[0] == cellPair[1]) continue; 2615 if (!found) { 2616 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2617 if (meetSize) { 2618 PetscInt f; 2619 2620 for (f = 0; f < numFaceCases; ++f) { 2621 if (numFaceVertices[f] == meetSize) { 2622 found = PETSC_TRUE; 2623 break; 2624 } 2625 } 2626 } 2627 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2628 } 2629 if (found) { 2630 ++off[cell-cStart+1]; 2631 } 2632 } 2633 } 2634 /* Prefix sum */ 2635 for (cell = 1; cell <= numCells; ++cell) { 2636 off[cell] += off[cell-1]; 2637 } 2638 if (adjacency) { 2639 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2640 /* Get neighboring cells */ 2641 for (cell = cStart; cell < cEnd; ++cell) { 2642 PetscInt numNeighbors = maxNeighbors, n; 2643 PetscInt cellOffset = 0; 2644 2645 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2646 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2647 for (n = 0; n < numNeighbors; ++n) { 2648 PetscInt cellPair[2] = {cell, neighborCells[n]}; 2649 PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2650 PetscInt meetSize = 0; 2651 const PetscInt *meet = PETSC_NULL; 2652 2653 if (cellPair[0] == cellPair[1]) continue; 2654 if (!found) { 2655 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2656 if (meetSize) { 2657 PetscInt f; 2658 2659 for (f = 0; f < numFaceCases; ++f) { 2660 if (numFaceVertices[f] == meetSize) { 2661 found = PETSC_TRUE; 2662 break; 2663 } 2664 } 2665 } 2666 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2667 } 2668 if (found) { 2669 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2670 ++cellOffset; 2671 } 2672 } 2673 } 2674 } 2675 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2676 if (numVertices) *numVertices = numCells; 2677 if (offsets) *offsets = off; 2678 if (adjacency) *adjacency = adj; 2679 PetscFunctionReturn(0); 2680 } 2681 2682 #if defined(PETSC_HAVE_CHACO) 2683 #if defined(PETSC_HAVE_UNISTD_H) 2684 #include <unistd.h> 2685 #endif 2686 /* Chaco does not have an include file */ 2687 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2688 float *ewgts, float *x, float *y, float *z, char *outassignname, 2689 char *outfilename, short *assignment, int architecture, int ndims_tot, 2690 int mesh_dims[3], double *goal, int global_method, int local_method, 2691 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2692 2693 extern int FREE_GRAPH; 2694 2695 #undef __FUNCT__ 2696 #define __FUNCT__ "DMPlexPartition_Chaco" 2697 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2698 { 2699 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2700 MPI_Comm comm = ((PetscObject) dm)->comm; 2701 int nvtxs = numVertices; /* number of vertices in full graph */ 2702 int *vwgts = NULL; /* weights for all vertices */ 2703 float *ewgts = NULL; /* weights for all edges */ 2704 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2705 char *outassignname = NULL; /* name of assignment output file */ 2706 char *outfilename = NULL; /* output file name */ 2707 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2708 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2709 int mesh_dims[3]; /* dimensions of mesh of processors */ 2710 double *goal = NULL; /* desired set sizes for each set */ 2711 int global_method = 1; /* global partitioning algorithm */ 2712 int local_method = 1; /* local partitioning algorithm */ 2713 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2714 int vmax = 200; /* how many vertices to coarsen down to? */ 2715 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2716 double eigtol = 0.001; /* tolerance on eigenvectors */ 2717 long seed = 123636512; /* for random graph mutations */ 2718 short int *assignment; /* Output partition */ 2719 int fd_stdout, fd_pipe[2]; 2720 PetscInt *points; 2721 PetscMPIInt commSize; 2722 int i, v, p; 2723 PetscErrorCode ierr; 2724 2725 PetscFunctionBegin; 2726 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2727 if (!numVertices) { 2728 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2729 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2730 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2731 ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2732 PetscFunctionReturn(0); 2733 } 2734 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2735 for (i = 0; i < start[numVertices]; ++i) { 2736 ++adjacency[i]; 2737 } 2738 if (global_method == INERTIAL_METHOD) { 2739 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2740 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2741 } 2742 mesh_dims[0] = commSize; 2743 mesh_dims[1] = 1; 2744 mesh_dims[2] = 1; 2745 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2746 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2747 /* TODO: check error codes for UNIX calls */ 2748 #if defined(PETSC_HAVE_UNISTD_H) 2749 { 2750 int piperet; 2751 piperet = pipe(fd_pipe); 2752 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2753 fd_stdout = dup(1); 2754 close(1); 2755 dup2(fd_pipe[1], 1); 2756 } 2757 #endif 2758 ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2759 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2760 vmax, ndims, eigtol, seed); 2761 #if defined(PETSC_HAVE_UNISTD_H) 2762 { 2763 char msgLog[10000]; 2764 int count; 2765 2766 fflush(stdout); 2767 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2768 if (count < 0) count = 0; 2769 msgLog[count] = 0; 2770 close(1); 2771 dup2(fd_stdout, 1); 2772 close(fd_stdout); 2773 close(fd_pipe[0]); 2774 close(fd_pipe[1]); 2775 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2776 } 2777 #endif 2778 /* Convert to PetscSection+IS */ 2779 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2780 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2781 for (v = 0; v < nvtxs; ++v) { 2782 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2783 } 2784 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2785 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2786 for (p = 0, i = 0; p < commSize; ++p) { 2787 for (v = 0; v < nvtxs; ++v) { 2788 if (assignment[v] == p) points[i++] = v; 2789 } 2790 } 2791 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2792 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2793 if (global_method == INERTIAL_METHOD) { 2794 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2795 } 2796 ierr = PetscFree(assignment);CHKERRQ(ierr); 2797 for (i = 0; i < start[numVertices]; ++i) { 2798 --adjacency[i]; 2799 } 2800 PetscFunctionReturn(0); 2801 } 2802 #endif 2803 2804 #if defined(PETSC_HAVE_PARMETIS) 2805 #undef __FUNCT__ 2806 #define __FUNCT__ "DMPlexPartition_ParMetis" 2807 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2808 { 2809 PetscFunctionBegin; 2810 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2811 PetscFunctionReturn(0); 2812 } 2813 #endif 2814 2815 #undef __FUNCT__ 2816 #define __FUNCT__ "DMPlexEnlargePartition" 2817 /* Expand the partition by BFS on the adjacency graph */ 2818 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2819 { 2820 PetscHashI h; 2821 const PetscInt *points; 2822 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2823 PetscInt pStart, pEnd, part, q; 2824 PetscErrorCode ierr; 2825 2826 PetscFunctionBegin; 2827 PetscHashICreate(h); 2828 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2829 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2830 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2831 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2832 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2833 for (part = pStart; part < pEnd; ++part) { 2834 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2835 2836 PetscHashIClear(h); 2837 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2838 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2839 /* Add all existing points to h */ 2840 for (p = 0; p < numPoints; ++p) { 2841 const PetscInt point = points[off+p]; 2842 PetscHashIAdd(h, point, 1); 2843 } 2844 PetscHashISize(h, nP); 2845 if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2846 /* Add all points in next BFS level */ 2847 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2848 for (p = 0; p < numPoints; ++p) { 2849 const PetscInt point = points[off+p]; 2850 PetscInt s = start[point], e = start[point+1], a; 2851 2852 for (a = s; a < e; ++a) { 2853 PetscHashIAdd(h, adjacency[a], 1); 2854 } 2855 } 2856 PetscHashISize(h, numNewPoints); 2857 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2858 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2859 if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2860 totPoints += numNewPoints; 2861 } 2862 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2863 PetscHashIDestroy(h); 2864 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2865 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2866 for (part = pStart, q = 0; part < pEnd; ++part) { 2867 PetscInt numPoints, p; 2868 2869 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2870 for (p = 0; p < numPoints; ++p, ++q) { 2871 newPoints[q] = tmpPoints[part][p]; 2872 } 2873 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2874 } 2875 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2876 ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2877 PetscFunctionReturn(0); 2878 } 2879 2880 #undef __FUNCT__ 2881 #define __FUNCT__ "DMPlexCreatePartition" 2882 /* 2883 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2884 2885 Collective on DM 2886 2887 Input Parameters: 2888 + dm - The DM 2889 . height - The height for points in the partition 2890 - enlarge - Expand each partition with neighbors 2891 2892 Output Parameters: 2893 + partSection - The PetscSection giving the division of points by partition 2894 . partition - The list of points by partition 2895 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2896 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2897 2898 Level: developer 2899 2900 .seealso DMPlexDistribute() 2901 */ 2902 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2903 { 2904 PetscMPIInt size; 2905 PetscErrorCode ierr; 2906 2907 PetscFunctionBegin; 2908 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2909 *origPartSection = PETSC_NULL; 2910 *origPartition = PETSC_NULL; 2911 if (size == 1) { 2912 PetscInt *points; 2913 PetscInt cStart, cEnd, c; 2914 2915 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2916 ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2917 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2918 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2919 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2920 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2921 for (c = cStart; c < cEnd; ++c) { 2922 points[c] = c; 2923 } 2924 ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2925 PetscFunctionReturn(0); 2926 } 2927 if (height == 0) { 2928 PetscInt numVertices; 2929 PetscInt *start = PETSC_NULL; 2930 PetscInt *adjacency = PETSC_NULL; 2931 2932 ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2933 if (1) { 2934 #if defined(PETSC_HAVE_CHACO) 2935 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2936 #endif 2937 } else { 2938 #if defined(PETSC_HAVE_PARMETIS) 2939 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2940 #endif 2941 } 2942 if (enlarge) { 2943 *origPartSection = *partSection; 2944 *origPartition = *partition; 2945 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2946 } 2947 ierr = PetscFree(start);CHKERRQ(ierr); 2948 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2949 # if 0 2950 } else if (height == 1) { 2951 /* Build the dual graph for faces and partition the hypergraph */ 2952 PetscInt numEdges; 2953 2954 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2955 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2956 destroyCSR(numEdges, start, adjacency); 2957 #endif 2958 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2959 PetscFunctionReturn(0); 2960 } 2961 2962 #undef __FUNCT__ 2963 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2964 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2965 { 2966 /* const PetscInt height = 0; */ 2967 const PetscInt *partArray; 2968 PetscInt *allPoints, *partPoints = PETSC_NULL; 2969 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2970 PetscErrorCode ierr; 2971 2972 PetscFunctionBegin; 2973 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2974 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2975 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2976 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2977 for (rank = rStart; rank < rEnd; ++rank) { 2978 PetscInt partSize = 0; 2979 PetscInt numPoints, offset, p; 2980 2981 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2982 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2983 for (p = 0; p < numPoints; ++p) { 2984 PetscInt point = partArray[offset+p], closureSize, c; 2985 PetscInt *closure = PETSC_NULL; 2986 2987 /* TODO Include support for height > 0 case */ 2988 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2989 /* Merge into existing points */ 2990 if (partSize+closureSize > maxPartSize) { 2991 PetscInt *tmpPoints; 2992 2993 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2994 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2995 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2996 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2997 partPoints = tmpPoints; 2998 } 2999 for (c = 0; c < closureSize; ++c) { 3000 partPoints[partSize+c] = closure[c*2]; 3001 } 3002 partSize += closureSize; 3003 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3004 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3005 } 3006 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3007 } 3008 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3009 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3010 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3011 3012 for (rank = rStart; rank < rEnd; ++rank) { 3013 PetscInt partSize = 0, newOffset; 3014 PetscInt numPoints, offset, p; 3015 3016 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3017 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3018 for (p = 0; p < numPoints; ++p) { 3019 PetscInt point = partArray[offset+p], closureSize, c; 3020 PetscInt *closure = PETSC_NULL; 3021 3022 /* TODO Include support for height > 0 case */ 3023 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3024 /* Merge into existing points */ 3025 for (c = 0; c < closureSize; ++c) { 3026 partPoints[partSize+c] = closure[c*2]; 3027 } 3028 partSize += closureSize; 3029 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3030 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3031 } 3032 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3033 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3034 } 3035 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3036 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3037 ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3038 PetscFunctionReturn(0); 3039 } 3040 3041 #undef __FUNCT__ 3042 #define __FUNCT__ "DMPlexDistributeField" 3043 /* 3044 Input Parameters: 3045 . originalSection 3046 , originalVec 3047 3048 Output Parameters: 3049 . newSection 3050 . newVec 3051 */ 3052 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3053 { 3054 PetscSF fieldSF; 3055 PetscInt *remoteOffsets, fieldSize; 3056 PetscScalar *originalValues, *newValues; 3057 PetscErrorCode ierr; 3058 3059 PetscFunctionBegin; 3060 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3061 3062 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3063 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3064 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3065 3066 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3067 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3068 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3069 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3070 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3071 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3072 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3073 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3074 PetscFunctionReturn(0); 3075 } 3076 3077 #undef __FUNCT__ 3078 #define __FUNCT__ "DMPlexDistribute" 3079 /*@C 3080 DMPlexDistribute - Distributes the mesh and any associated sections. 3081 3082 Not Collective 3083 3084 Input Parameter: 3085 + dm - The original DMPlex object 3086 . partitioner - The partitioning package, or NULL for the default 3087 - overlap - The overlap of partitions, 0 is the default 3088 3089 Output Parameter: 3090 . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3091 3092 Note: If the mesh was not distributed, the return value is PETSC_NULL 3093 3094 Level: intermediate 3095 3096 .keywords: mesh, elements 3097 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3098 @*/ 3099 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3100 { 3101 DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3102 MPI_Comm comm = ((PetscObject) dm)->comm; 3103 const PetscInt height = 0; 3104 PetscInt dim, numRemoteRanks; 3105 IS origCellPart, cellPart, part; 3106 PetscSection origCellPartSection, cellPartSection, partSection; 3107 PetscSFNode *remoteRanks; 3108 PetscSF partSF, pointSF, coneSF; 3109 ISLocalToGlobalMapping renumbering; 3110 PetscSection originalConeSection, newConeSection; 3111 PetscInt *remoteOffsets; 3112 PetscInt *cones, *newCones, newConesSize; 3113 PetscBool flg; 3114 PetscMPIInt rank, numProcs, p; 3115 PetscErrorCode ierr; 3116 3117 PetscFunctionBegin; 3118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3119 PetscValidPointer(dmParallel,4); 3120 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3121 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3122 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3123 *dmParallel = PETSC_NULL; 3124 if (numProcs == 1) PetscFunctionReturn(0); 3125 3126 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3127 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3128 if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3129 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3130 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3131 if (!rank) { 3132 numRemoteRanks = numProcs; 3133 } else { 3134 numRemoteRanks = 0; 3135 } 3136 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3137 for (p = 0; p < numRemoteRanks; ++p) { 3138 remoteRanks[p].rank = p; 3139 remoteRanks[p].index = 0; 3140 } 3141 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3142 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3143 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3144 if (flg) { 3145 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3146 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3147 ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3148 if (origCellPart) { 3149 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3150 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3151 ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3152 } 3153 ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3154 } 3155 /* Close the partition over the mesh */ 3156 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3157 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3158 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3159 /* Create new mesh */ 3160 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3161 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3162 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3163 pmesh = (DM_Plex *) (*dmParallel)->data; 3164 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3165 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3166 if (flg) { 3167 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3168 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3169 ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3170 ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3171 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3172 ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3173 } 3174 /* Distribute cone section */ 3175 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3176 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3177 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3178 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3179 { 3180 PetscInt pStart, pEnd, p; 3181 3182 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3183 for (p = pStart; p < pEnd; ++p) { 3184 PetscInt coneSize; 3185 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3186 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3187 } 3188 } 3189 /* Communicate and renumber cones */ 3190 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3191 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3192 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3193 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3194 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3195 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3196 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3197 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3198 if (flg) { 3199 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3200 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3201 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3202 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3203 ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3204 } 3205 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3206 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3207 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3208 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3209 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3210 /* Create supports and stratify sieve */ 3211 { 3212 PetscInt pStart, pEnd; 3213 3214 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3215 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3216 } 3217 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3218 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3219 /* Distribute Coordinates */ 3220 { 3221 PetscSection originalCoordSection, newCoordSection; 3222 Vec originalCoordinates, newCoordinates; 3223 const char *name; 3224 3225 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3226 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3227 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3228 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3229 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3230 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3231 3232 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3233 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3234 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3235 } 3236 /* Distribute labels */ 3237 { 3238 DMLabel next = mesh->labels, newNext = pmesh->labels; 3239 PetscInt numLabels = 0, l; 3240 3241 /* Bcast number of labels */ 3242 while (next) {++numLabels; next = next->next;} 3243 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3244 next = mesh->labels; 3245 for (l = 0; l < numLabels; ++l) { 3246 DMLabel newLabel; 3247 const PetscInt *partArray; 3248 char *name; 3249 PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3250 PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3251 PetscInt nameSize, s, p; 3252 PetscBool isdepth; 3253 size_t len = 0; 3254 3255 /* Bcast name (could filter for no points) */ 3256 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3257 nameSize = len; 3258 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3259 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3260 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3261 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3262 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3263 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3264 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3265 newLabel->name = name; 3266 /* Bcast numStrata (could filter for no points in stratum) */ 3267 if (!rank) {newLabel->numStrata = next->numStrata;} 3268 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3269 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3270 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3271 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3272 /* Bcast stratumValues (could filter for no points in stratum) */ 3273 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3274 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3275 /* Find size on each process and Scatter */ 3276 if (!rank) { 3277 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3278 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3279 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3280 for (s = 0; s < next->numStrata; ++s) { 3281 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3282 const PetscInt point = next->points[p]; 3283 PetscInt proc; 3284 3285 for (proc = 0; proc < numProcs; ++proc) { 3286 PetscInt dof, off, pPart; 3287 3288 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3289 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3290 for (pPart = off; pPart < off+dof; ++pPart) { 3291 if (partArray[pPart] == point) { 3292 ++stratumSizes[proc*next->numStrata+s]; 3293 break; 3294 } 3295 } 3296 } 3297 } 3298 } 3299 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3300 } 3301 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3302 /* Calculate stratumOffsets */ 3303 newLabel->stratumOffsets[0] = 0; 3304 for (s = 0; s < newLabel->numStrata; ++s) { 3305 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3306 } 3307 /* Pack points and Scatter */ 3308 if (!rank) { 3309 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3310 displs[0] = 0; 3311 for (p = 0; p < numProcs; ++p) { 3312 sendcnts[p] = 0; 3313 for (s = 0; s < next->numStrata; ++s) { 3314 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3315 } 3316 offsets[p] = displs[p]; 3317 displs[p+1] = displs[p] + sendcnts[p]; 3318 } 3319 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3320 for (s = 0; s < next->numStrata; ++s) { 3321 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3322 const PetscInt point = next->points[p]; 3323 PetscInt proc; 3324 3325 for (proc = 0; proc < numProcs; ++proc) { 3326 PetscInt dof, off, pPart; 3327 3328 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3329 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3330 for (pPart = off; pPart < off+dof; ++pPart) { 3331 if (partArray[pPart] == point) { 3332 points[offsets[proc]++] = point; 3333 break; 3334 } 3335 } 3336 } 3337 } 3338 } 3339 } 3340 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3341 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3342 ierr = PetscFree(points);CHKERRQ(ierr); 3343 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3344 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3345 /* Renumber points */ 3346 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3347 /* Sort points */ 3348 for (s = 0; s < newLabel->numStrata; ++s) { 3349 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3350 } 3351 /* Insert into list */ 3352 if (newNext) { 3353 newNext->next = newLabel; 3354 } else { 3355 pmesh->labels = newLabel; 3356 } 3357 newNext = newLabel; 3358 if (!rank) {next = next->next;} 3359 } 3360 } 3361 /* Cleanup Partition */ 3362 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3363 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3364 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3365 ierr = ISDestroy(&part);CHKERRQ(ierr); 3366 /* Create point SF for parallel mesh */ 3367 { 3368 const PetscInt *leaves; 3369 PetscSFNode *remotePoints, *rowners, *lowners; 3370 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3371 PetscInt pStart, pEnd; 3372 3373 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3374 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3375 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3376 for (p=0; p<numRoots; p++) { 3377 rowners[p].rank = -1; 3378 rowners[p].index = -1; 3379 } 3380 if (origCellPart) { 3381 /* Make sure cells in the original partition are not assigned to other procs */ 3382 const PetscInt *origCells; 3383 3384 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3385 for (p = 0; p < numProcs; ++p) { 3386 PetscInt dof, off, d; 3387 3388 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3389 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3390 for (d = off; d < off+dof; ++d) { 3391 rowners[origCells[d]].rank = p; 3392 } 3393 } 3394 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3395 } 3396 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3397 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3398 3399 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3400 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3401 for (p = 0; p < numLeaves; ++p) { 3402 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3403 lowners[p].rank = rank; 3404 lowners[p].index = leaves ? leaves[p] : p; 3405 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3406 lowners[p].rank = -2; 3407 lowners[p].index = -2; 3408 } 3409 } 3410 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3411 rowners[p].rank = -3; 3412 rowners[p].index = -3; 3413 } 3414 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3415 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3416 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3417 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3418 for (p = 0; p < numLeaves; ++p) { 3419 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3420 if (lowners[p].rank != rank) ++numGhostPoints; 3421 } 3422 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3423 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3424 for (p = 0, gp = 0; p < numLeaves; ++p) { 3425 if (lowners[p].rank != rank) { 3426 ghostPoints[gp] = leaves ? leaves[p] : p; 3427 remotePoints[gp].rank = lowners[p].rank; 3428 remotePoints[gp].index = lowners[p].index; 3429 ++gp; 3430 } 3431 } 3432 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3433 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3434 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3435 } 3436 /* Cleanup */ 3437 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3438 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3439 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3440 PetscFunctionReturn(0); 3441 } 3442 3443 #undef __FUNCT__ 3444 #define __FUNCT__ "DMPlexRenumber_Private" 3445 /* 3446 Reasons to renumber: 3447 3448 1) Permute points, e.g. bandwidth reduction (Renumber) 3449 3450 a) Must not mix strata 3451 3452 2) Shift numbers for point insertion (Shift) 3453 3454 a) Want operation brken into parts so that insertion can be interleaved 3455 3456 renumbering - An IS which provides the new numbering 3457 */ 3458 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3459 { 3460 PetscFunctionBegin; 3461 PetscFunctionReturn(0); 3462 } 3463 3464 #undef __FUNCT__ 3465 #define __FUNCT__ "DMPlexShiftPoint_Private" 3466 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3467 { 3468 if (depth < 0) return p; 3469 /* Cells */ if (p < depthEnd[depth]) return p; 3470 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3471 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3472 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3473 } 3474 3475 #undef __FUNCT__ 3476 #define __FUNCT__ "DMPlexShiftSizes_Private" 3477 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3478 { 3479 PetscInt *depthEnd; 3480 PetscInt depth = 0, d, pStart, pEnd, p; 3481 PetscErrorCode ierr; 3482 3483 PetscFunctionBegin; 3484 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3485 if (depth < 0) PetscFunctionReturn(0); 3486 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3487 /* Step 1: Expand chart */ 3488 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3489 for (d = 0; d <= depth; ++d) { 3490 pEnd += depthShift[d]; 3491 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3492 } 3493 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3494 /* Step 2: Set cone and support sizes */ 3495 for (d = 0; d <= depth; ++d) { 3496 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3497 for (p = pStart; p < pEnd; ++p) { 3498 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3499 PetscInt size; 3500 3501 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3502 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3503 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3504 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3505 } 3506 } 3507 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3508 PetscFunctionReturn(0); 3509 } 3510 3511 #undef __FUNCT__ 3512 #define __FUNCT__ "DMPlexShiftPoints_Private" 3513 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3514 { 3515 PetscInt *depthEnd, *newpoints; 3516 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3517 PetscErrorCode ierr; 3518 3519 PetscFunctionBegin; 3520 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3521 if (depth < 0) PetscFunctionReturn(0); 3522 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3523 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3524 for (d = 0; d <= depth; ++d) { 3525 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3526 } 3527 /* Step 5: Set cones and supports */ 3528 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3529 for (p = pStart; p < pEnd; ++p) { 3530 const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3531 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3532 3533 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3534 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3535 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3536 for (i = 0; i < size; ++i) { 3537 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3538 } 3539 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3540 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3541 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3542 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3543 for (i = 0; i < size; ++i) { 3544 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3545 } 3546 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3547 } 3548 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3549 PetscFunctionReturn(0); 3550 } 3551 3552 #undef __FUNCT__ 3553 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3554 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3555 { 3556 PetscSection coordSection, newCoordSection; 3557 Vec coordinates, 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_2D" 3899 PetscErrorCode DMPlexConstructCohesiveCells_2D(DM dm, const char labelName[], DM sdm) 3900 { 3901 MPI_Comm comm = ((PetscObject) dm)->comm; 3902 DMLabel label; 3903 IS valueIS, svIS = PETSC_NULL, seIS = PETSC_NULL; 3904 const PetscInt *values, *splitVertices = PETSC_NULL, *splitEdges = PETSC_NULL; 3905 PetscSection coordSection; 3906 Vec coordinates; 3907 PetscScalar *coords; 3908 PetscInt *depthShift, *depthOffset, *pMaxNew, *coneNew, *supportNew; 3909 PetscInt shift = 100, depth = 0, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numSplitVertices = 0, v, numSplitEdges = 0, numLabels, l; 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 ierr = DMLabelGetStratumIS(label, 0, &svIS);CHKERRQ(ierr); 3921 if (svIS) { 3922 ierr = ISGetLocalSize(svIS, &numSplitVertices);CHKERRQ(ierr); 3923 ierr = ISGetIndices(svIS, &splitVertices);CHKERRQ(ierr); 3924 } 3925 ierr = DMLabelGetStratumIS(label, 1, &seIS);CHKERRQ(ierr); 3926 if (seIS) { 3927 ierr = ISGetLocalSize(seIS, &numSplitEdges);CHKERRQ(ierr); 3928 ierr = ISGetIndices(seIS, &splitEdges);CHKERRQ(ierr); 3929 } 3930 } 3931 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3932 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3933 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3934 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3935 for(d = 0; d <= depth; ++d) { 3936 ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &pMaxNew[d]);CHKERRQ(ierr); 3937 } 3938 for(sp = 0; sp < numSP; ++sp) { 3939 if ((values[sp] < 0) || (values[sp] > depth)) continue; 3940 ierr = DMLabelGetStratumSize(label, values[sp], &depthShift[values[sp]]);CHKERRQ(ierr); 3941 } 3942 if (depth >= 0) { 3943 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3944 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3945 pMaxNew[0] += depthShift[depth]; 3946 if (depth > 1) {pMaxNew[1] += depthShift[depth] + depthShift[0];} 3947 if (depth > 2) {pMaxNew[2] += depthShift[depth] + depthShift[0] + depthShift[1];} 3948 depthOffset[depth] = 0; 3949 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3950 if (depth > 1) {depthOffset[1] = depthOffset[0] + depthShift[0];} 3951 if (depth > 2) {depthOffset[2] = depthOffset[1] + depthShift[1];} 3952 } 3953 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3954 /* Step 3: Set cone/support sizes for new points */ 3955 for(sp = 0; sp < numSP; ++sp) { 3956 const PetscInt dep = values[sp]; 3957 const PetscInt *points; 3958 IS dimIS; 3959 PetscInt numPoints, p; 3960 3961 if ((values[sp] < 0) || (values[sp] > depth)) continue; 3962 ierr = DMLabelGetStratumIS(label, dep, &dimIS);CHKERRQ(ierr); 3963 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 3964 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 3965 for(p = 0; p < numPoints; ++p) { 3966 const PetscInt *support; 3967 PetscInt coneSize, supportSize, q, e; 3968 3969 ierr = DMPlexGetConeSize(dm, points[p], &coneSize);CHKERRQ(ierr); 3970 ierr = DMPlexSetConeSize(sdm, pMaxNew[dep] + p, coneSize);CHKERRQ(ierr); 3971 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 3972 ierr = DMPlexSetSupportSize(sdm, pMaxNew[dep] + p, supportSize);CHKERRQ(ierr); 3973 if (dep == depth-1) { 3974 /* Add cohesive cells, they are prisms */ 3975 ierr = DMPlexSetConeSize(sdm, pMaxNew[depth] + p, 2 + coneSize);CHKERRQ(ierr); 3976 } else if (dep == 0) { 3977 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 3978 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3979 for(e = 0, q = 0; e < supportSize; ++e) { 3980 PetscInt val; 3981 3982 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3983 if ((val == 1) || (val == (shift + 1))) ++q; 3984 } 3985 ierr = DMPlexSetSupportSize(sdm, depthShift[depth] + points[p], q+1);CHKERRQ(ierr); 3986 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3987 for(e = 0, q = 0; e < supportSize; ++e) { 3988 PetscInt val; 3989 3990 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3991 if ((val == 1) || (val == -(shift + 1))) ++q; 3992 } 3993 ierr = DMPlexSetSupportSize(sdm, pMaxNew[dep] + p, q+1);CHKERRQ(ierr); 3994 /* Add cohesive edges */ 3995 ierr = DMPlexSetConeSize(sdm, pMaxNew[1] + (depthShift[1] - depthShift[0]) + p, 2);CHKERRQ(ierr); 3996 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3997 } 3998 } 3999 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4000 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4001 } 4002 /* Step 4: Setup ghosted DM */ 4003 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4004 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4005 /* Step 6: Set cones and supports for new points */ 4006 for(sp = 0; sp < numSP; ++sp) { 4007 const PetscInt dep = values[sp]; 4008 const PetscInt *points; 4009 IS dimIS; 4010 PetscInt numPoints, p; 4011 4012 if ((values[sp] < 0) || (values[sp] > depth)) continue; 4013 ierr = DMLabelGetStratumIS(label, dep, &dimIS);CHKERRQ(ierr); 4014 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4015 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4016 for(p = 0; p < numPoints; ++p) { 4017 const PetscInt *cone, *support; 4018 PetscInt coneSize, supportSize, q, v, e, s; 4019 4020 ierr = DMPlexGetConeSize(dm, points[p], &coneSize);CHKERRQ(ierr); 4021 ierr = DMPlexGetCone(dm, points[p], &cone);CHKERRQ(ierr); 4022 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4023 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4024 if (dep == depth-1) { 4025 const PetscInt newp = depthOffset[dep] + points[p]; 4026 const PetscInt splitp = pMaxNew[dep] + p; 4027 const PetscInt ccell = pMaxNew[depth] + p; 4028 const PetscInt *supportF; 4029 4030 /* Split face: copy in old face to new face to start */ 4031 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4032 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4033 /* Split old face: old vertices in cone so no change */ 4034 /* Split new face: new vertices in cone */ 4035 for(q = 0; q < coneSize; ++q) { 4036 ierr = PetscFindInt(cone[q], numSplitVertices, splitVertices, &v);CHKERRQ(ierr); 4037 coneNew[2+q] = pMaxNew[0] + v; 4038 } 4039 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4040 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4041 coneNew[0] = newp; 4042 coneNew[1] = splitp; 4043 for(q = 0; q < coneSize; ++q) { 4044 coneNew[2+q] = (pMaxNew[1] - pMaxNew[0]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4045 } 4046 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4047 for(s = 0; s < supportSize; ++s) { 4048 PetscInt val; 4049 4050 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4051 if (val < 0) { 4052 const PetscInt *scone; 4053 PetscInt sconeSize, sc; 4054 4055 /* Split old face: Replace negative side cell with cohesive cell */ 4056 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4057 /* Negative cell: replace split face */ 4058 ierr = DMPlexGetConeSize(sdm, support[s], &sconeSize);CHKERRQ(ierr); 4059 ierr = DMPlexGetCone(sdm, support[s], &scone);CHKERRQ(ierr); 4060 for(sc = 0; sc < sconeSize; ++sc) { 4061 if (scone[sc] == newp) { 4062 ierr = DMPlexInsertCone(sdm, support[s], sc, splitp);CHKERRQ(ierr); 4063 break; 4064 } 4065 } 4066 } else { 4067 /* Split new face: Replace positive side cell with cohesive cell */ 4068 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4069 } 4070 } 4071 } else if (dep == 0) { 4072 const PetscInt newp = depthOffset[dep] + points[p]; 4073 const PetscInt splitp = pMaxNew[dep] + p; 4074 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4075 4076 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4077 for(e = 0, q = 0; e < supportSize; ++e) { 4078 PetscInt val; 4079 4080 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4081 if ((val == 1) || (val == (shift + 1))) { 4082 supportNew[q++] = depthOffset[1] + support[e]; 4083 } 4084 } 4085 supportNew[q] = cedge; 4086 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4087 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4088 for(e = 0, q = 0; e < supportSize; ++e) { 4089 PetscInt val, edge; 4090 4091 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4092 if (val == 1) { 4093 ierr = PetscFindInt(support[e], numSplitEdges, splitEdges, &edge);CHKERRQ(ierr); 4094 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4095 supportNew[q++] = pMaxNew[1] + edge; 4096 } else if (val == -(shift + 1)) { 4097 const PetscInt *scone; 4098 PetscInt sconeSize, sc; 4099 4100 supportNew[q++] = depthOffset[1] + support[e]; 4101 /* Negative edge: replace split vertex */ 4102 ierr = DMPlexGetConeSize(sdm, depthOffset[1] + support[e], &sconeSize);CHKERRQ(ierr); 4103 ierr = DMPlexGetCone(sdm, depthOffset[1] + support[e], &scone);CHKERRQ(ierr); 4104 for(sc = 0; sc < sconeSize; ++sc) { 4105 if (scone[sc] == newp) { 4106 ierr = DMPlexInsertCone(sdm, depthOffset[1] + support[e], sc, splitp);CHKERRQ(ierr); 4107 break; 4108 } 4109 } 4110 if (sc == sconeSize) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Edge %d does not contain split vertex %d", support[e], newp); 4111 } 4112 } 4113 supportNew[q] = cedge; 4114 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4115 /* Cohesive edge: Old and new split vertex, punting on support */ 4116 coneNew[0] = newp; 4117 coneNew[1] = splitp; 4118 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4119 } 4120 } 4121 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4122 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4123 } 4124 if (label) { 4125 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4126 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4127 } 4128 /* Step 7: Stratify */ 4129 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4130 /* Step 8: Coordinates */ 4131 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4132 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4133 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4134 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4135 for(v = 0; v < numSplitVertices; ++v) { 4136 const PetscInt newp = depthOffset[0] + splitVertices[v]; 4137 const PetscInt splitp = pMaxNew[0] + v; 4138 PetscInt dof, off, soff, d; 4139 4140 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4141 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4142 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4143 for(d = 0; d < dof; ++d) { 4144 coords[soff+d] = coords[off+d]; 4145 } 4146 } 4147 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4148 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4149 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4150 /* Step 10: Labels */ 4151 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4152 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4153 for(sp = 0; sp < numSP; ++sp) { 4154 const PetscInt dep = values[sp]; 4155 const PetscInt *points; 4156 IS dimIS; 4157 PetscInt numPoints, p; 4158 4159 if ((values[sp] < 0) || (values[sp] > depth)) continue; 4160 ierr = DMLabelGetStratumIS(label, dep, &dimIS);CHKERRQ(ierr); 4161 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4162 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4163 for(p = 0; p < numPoints; ++p) { 4164 const PetscInt newp = depthOffset[dep] + points[p]; 4165 const PetscInt splitp = pMaxNew[dep] + p; 4166 4167 for (l = 0; l < numLabels; ++l) { 4168 DMLabel label; 4169 const char *lname; 4170 PetscInt val; 4171 4172 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4173 ierr = DMPlexGetLabel(sdm, lname, &label);CHKERRQ(ierr); 4174 ierr = DMLabelGetValue(label, newp, &val);CHKERRQ(ierr); 4175 if (val >= 0) { 4176 ierr = DMLabelSetValue(label, splitp, val);CHKERRQ(ierr); 4177 if (dep == 0) { 4178 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4179 ierr = DMLabelSetValue(label, cedge, val);CHKERRQ(ierr); 4180 } 4181 } 4182 } 4183 } 4184 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4185 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4186 } 4187 if (svIS) {ierr = ISRestoreIndices(svIS, &splitVertices);CHKERRQ(ierr);} 4188 if (seIS) {ierr = ISRestoreIndices(seIS, &splitEdges);CHKERRQ(ierr);} 4189 ierr = ISDestroy(&svIS);CHKERRQ(ierr); 4190 ierr = ISDestroy(&seIS);CHKERRQ(ierr); 4191 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4192 PetscFunctionReturn(0); 4193 } 4194 4195 #undef __FUNCT__ 4196 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4197 /*@C 4198 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4199 4200 Collective on dm 4201 4202 Input Parameters: 4203 + dm - The original DM 4204 - labelName - The label specifying the boundary faces (this could be auto-generated) 4205 4206 Output Parameters: 4207 - dmSplit - The new DM 4208 4209 Level: developer 4210 4211 .seealso: DMCreate() 4212 */ 4213 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, const char labelName[], DM *dmSplit) 4214 { 4215 DM sdm; 4216 PetscInt dim; 4217 PetscErrorCode ierr; 4218 4219 PetscFunctionBegin; 4220 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4221 PetscValidPointer(dmSplit, 4); 4222 ierr = DMCreate(((PetscObject) dm)->comm, &sdm);CHKERRQ(ierr); 4223 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4224 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4225 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4226 switch(dim) { 4227 case 2: 4228 ierr = DMPlexConstructCohesiveCells_2D(dm, labelName, sdm);CHKERRQ(ierr); 4229 break; 4230 default: 4231 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4232 } 4233 *dmSplit = sdm; 4234 PetscFunctionReturn(0); 4235 } 4236 4237 #undef __FUNCT__ 4238 #define __FUNCT__ "DMLabelCohesiveComplete" 4239 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4240 { 4241 IS dimIS; 4242 const PetscInt *points; 4243 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4244 PetscErrorCode ierr; 4245 4246 PetscFunctionBegin; 4247 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4248 /* Cell orientation for face gives the side of the fault */ 4249 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4250 if (!dimIS) PetscFunctionReturn(0); 4251 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4252 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4253 for(p = 0; p < numPoints; ++p) { 4254 const PetscInt *support; 4255 PetscInt supportSize, s; 4256 4257 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4258 if (supportSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4259 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4260 for(s = 0; s < supportSize; ++s) { 4261 const PetscInt *cone, *ornt; 4262 PetscInt coneSize, c; 4263 PetscBool pos = PETSC_TRUE; 4264 4265 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4266 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4267 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4268 for(c = 0; c < coneSize; ++c) { 4269 if (cone[c] == points[p]) { 4270 if (ornt[c] >= 0) { 4271 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4272 } else { 4273 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4274 pos = PETSC_FALSE; 4275 } 4276 break; 4277 } 4278 } 4279 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]); 4280 /* Put faces touching the fault in the label */ 4281 for(c = 0; c < coneSize; ++c) { 4282 const PetscInt point = cone[c]; 4283 4284 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4285 if (val == -1) { 4286 PetscInt *closure = PETSC_NULL; 4287 PetscInt closureSize, cl; 4288 4289 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4290 for (cl = 0; cl < closureSize*2; cl += 2) { 4291 const PetscInt clp = closure[cl]; 4292 4293 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4294 if ((val >= 0) && (val < dim-1)) { 4295 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4296 break; 4297 } 4298 } 4299 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4300 } 4301 } 4302 } 4303 } 4304 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4305 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4306 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4307 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4308 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4309 if (!dimIS) PetscFunctionReturn(0); 4310 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4311 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4312 for(p = 0; p < numPoints; ++p) { 4313 PetscInt *star = PETSC_NULL; 4314 PetscInt starSize, s; 4315 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4316 4317 /* First mark cells connected to the fault */ 4318 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4319 while (again) { 4320 if (again > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4321 again = 0; 4322 for (s = 0; s < starSize*2; s += 2) { 4323 const PetscInt point = star[s]; 4324 const PetscInt *cone, *ornt; 4325 PetscInt coneSize, c; 4326 4327 if ((point < cStart) || (point >= cEnd)) continue; 4328 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4329 if (val != -1) continue; 4330 again = 2; 4331 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4332 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4333 for(c = 0; c < coneSize; ++c) { 4334 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4335 if (val != -1) { 4336 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); 4337 if (val > 0) { 4338 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4339 } else { 4340 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4341 } 4342 again = 1; 4343 break; 4344 } 4345 } 4346 } 4347 } 4348 /* Classify the rest by cell membership */ 4349 for (s = 0; s < starSize*2; s += 2) { 4350 const PetscInt point = star[s]; 4351 4352 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4353 if (val == -1) { 4354 PetscInt *sstar = PETSC_NULL; 4355 PetscInt sstarSize, ss; 4356 PetscBool marked = PETSC_FALSE; 4357 4358 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4359 for (ss = 0; ss < sstarSize*2; ss += 2) { 4360 const PetscInt spoint = sstar[ss]; 4361 4362 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4363 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4364 if (val == -1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4365 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4366 if (val > 0) { 4367 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4368 } else { 4369 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4370 } 4371 marked = PETSC_TRUE; 4372 break; 4373 } 4374 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4375 if (!marked) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d could not be classified", point); 4376 } 4377 } 4378 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4379 } 4380 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4381 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4382 PetscFunctionReturn(0); 4383 } 4384 4385 #undef __FUNCT__ 4386 #define __FUNCT__ "DMPlexInterpolate_2D" 4387 PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 4388 { 4389 DM idm; 4390 DM_Plex *mesh; 4391 PetscHashIJ edgeTable; 4392 PetscInt *off; 4393 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4394 PetscInt numEdges, firstEdge, edge, e; 4395 PetscErrorCode ierr; 4396 4397 PetscFunctionBegin; 4398 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4399 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4400 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4401 numCells = cEnd - cStart; 4402 numVertices = vEnd - vStart; 4403 firstEdge = numCells + numVertices; 4404 numEdges = 0 ; 4405 /* Count edges using algorithm from CreateNeighborCSR */ 4406 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4407 if (off) { 4408 PetscInt numCorners = 0; 4409 4410 numEdges = off[numCells]/2; 4411 #if 0 4412 /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 4413 numEdges += 3*numCells - off[numCells]; 4414 #else 4415 /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 4416 for (c = cStart; c < cEnd; ++c) { 4417 PetscInt coneSize; 4418 4419 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 4420 numCorners += coneSize; 4421 } 4422 numEdges += numCorners - off[numCells]; 4423 #endif 4424 } 4425 #if 0 4426 /* Check Euler characteristic V - E + F = 1 */ 4427 if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 4428 #endif 4429 /* Create interpolated mesh */ 4430 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4431 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4432 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4433 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 4434 for (c = 0; c < numCells; ++c) { 4435 PetscInt numCorners; 4436 4437 ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 4438 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4439 } 4440 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4441 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4442 } 4443 ierr = DMSetUp(idm);CHKERRQ(ierr); 4444 /* Get edge cones from subsets of cell vertices */ 4445 ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 4446 ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 4447 4448 for (c = 0, edge = firstEdge; c < numCells; ++c) { 4449 const PetscInt *cellFaces; 4450 PetscInt numCellFaces, faceSize, cf; 4451 4452 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4453 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4454 for (cf = 0; cf < numCellFaces; ++cf) { 4455 #if 1 4456 PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]), 4457 PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])}; 4458 4459 ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 4460 if (e < 0) { 4461 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4462 ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 4463 e = edge++; 4464 } 4465 #else 4466 PetscBool found = PETSC_FALSE; 4467 4468 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4469 for (e = firstEdge; e < edge; ++e) { 4470 const PetscInt *cone; 4471 4472 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4473 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4474 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4475 found = PETSC_TRUE; 4476 break; 4477 } 4478 } 4479 if (!found) { 4480 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4481 ++edge; 4482 } 4483 #endif 4484 ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 4485 } 4486 } 4487 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4488 ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4489 ierr = PetscFree(off);CHKERRQ(ierr); 4490 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4491 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4492 mesh = (DM_Plex *) (idm)->data; 4493 /* Orient edges */ 4494 for (c = 0; c < numCells; ++c) { 4495 const PetscInt *cone = PETSC_NULL, *cellFaces; 4496 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4497 4498 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4499 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4500 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4501 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4502 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4503 for (cf = 0; cf < numCellFaces; ++cf) { 4504 const PetscInt *econe = PETSC_NULL; 4505 PetscInt esize; 4506 4507 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4508 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4509 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]); 4510 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4511 /* Correctly oriented */ 4512 mesh->coneOrientations[coff+cf] = 0; 4513 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4514 /* Start at index 1, and reverse orientation */ 4515 mesh->coneOrientations[coff+cf] = -(1+1); 4516 } 4517 } 4518 } 4519 *dmInt = idm; 4520 PetscFunctionReturn(0); 4521 } 4522 4523 #undef __FUNCT__ 4524 #define __FUNCT__ "DMPlexInterpolate_3D" 4525 PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4526 { 4527 DM idm, fdm; 4528 DM_Plex *mesh; 4529 PetscInt *off; 4530 const PetscInt numCorners = 4; 4531 PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4532 PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4533 PetscErrorCode ierr; 4534 4535 PetscFunctionBegin; 4536 { 4537 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4538 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4539 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4540 } 4541 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4542 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4543 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4544 numCells = cEnd - cStart; 4545 numVertices = vEnd - vStart; 4546 firstFace = numCells + numVertices; 4547 numFaces = 0 ; 4548 /* Count faces using algorithm from CreateNeighborCSR */ 4549 ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4550 if (off) { 4551 numFaces = off[numCells]/2; 4552 /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4553 numFaces += 4*numCells - off[numCells]; 4554 } 4555 /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4556 firstEdge = firstFace + numFaces; 4557 numEdges = numVertices + numFaces - numCells - 1; 4558 /* Create interpolated mesh */ 4559 ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4560 ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4561 ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4562 ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4563 for (c = 0; c < numCells; ++c) { 4564 ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4565 } 4566 for (f = firstFace; f < firstFace+numFaces; ++f) { 4567 ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4568 } 4569 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4570 ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4571 } 4572 ierr = DMSetUp(idm);CHKERRQ(ierr); 4573 /* Get face cones from subsets of cell vertices */ 4574 ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4575 ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4576 ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4577 ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4578 for (f = firstFace; f < firstFace+numFaces; ++f) { 4579 ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4580 } 4581 ierr = DMSetUp(fdm);CHKERRQ(ierr); 4582 for (c = 0, face = firstFace; c < numCells; ++c) { 4583 const PetscInt *cellFaces; 4584 PetscInt numCellFaces, faceSize, cf; 4585 4586 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4587 if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4588 for (cf = 0; cf < numCellFaces; ++cf) { 4589 PetscBool found = PETSC_FALSE; 4590 4591 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4592 for (f = firstFace; f < face; ++f) { 4593 const PetscInt *cone = PETSC_NULL; 4594 4595 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4596 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4597 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4598 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4599 ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4600 ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4601 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4602 found = PETSC_TRUE; 4603 break; 4604 } 4605 } 4606 if (!found) { 4607 ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4608 /* Save the vertices for orientation calculation */ 4609 ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4610 ++face; 4611 } 4612 ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4613 } 4614 } 4615 if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4616 /* Get edge cones from subsets of face vertices */ 4617 for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4618 const PetscInt *cellFaces; 4619 PetscInt numCellFaces, faceSize, cf; 4620 4621 ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4622 if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4623 for (cf = 0; cf < numCellFaces; ++cf) { 4624 PetscBool found = PETSC_FALSE; 4625 4626 /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4627 for (e = firstEdge; e < edge; ++e) { 4628 const PetscInt *cone = PETSC_NULL; 4629 4630 ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4631 if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4632 ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4633 found = PETSC_TRUE; 4634 break; 4635 } 4636 } 4637 if (!found) { 4638 ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4639 ++edge; 4640 } 4641 ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4642 } 4643 } 4644 if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4645 ierr = PetscFree(off);CHKERRQ(ierr); 4646 ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4647 ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4648 mesh = (DM_Plex *) (idm)->data; 4649 /* Orient edges */ 4650 for (f = firstFace; f < firstFace+numFaces; ++f) { 4651 const PetscInt *cone, *cellFaces; 4652 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4653 4654 ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4655 ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4656 ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4657 ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4658 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4659 for (cf = 0; cf < numCellFaces; ++cf) { 4660 const PetscInt *econe; 4661 PetscInt esize; 4662 4663 ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4664 ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4665 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]); 4666 if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4667 /* Correctly oriented */ 4668 mesh->coneOrientations[coff+cf] = 0; 4669 } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4670 /* Start at index 1, and reverse orientation */ 4671 mesh->coneOrientations[coff+cf] = -(1+1); 4672 } 4673 } 4674 } 4675 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4676 /* Orient faces */ 4677 for (c = 0; c < numCells; ++c) { 4678 const PetscInt *cone, *cellFaces; 4679 PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4680 4681 ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4682 ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4683 ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4684 ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4685 if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4686 for (cf = 0; cf < numCellFaces; ++cf) { 4687 PetscInt *origClosure = PETSC_NULL, *closure; 4688 PetscInt closureSize, i; 4689 4690 ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4691 if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4692 for (i = 4; i < 7; ++i) { 4693 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); 4694 } 4695 closure = &origClosure[4*2]; 4696 /* Remember that this is the orientation for edges, not vertices */ 4697 if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4698 /* Correctly oriented */ 4699 mesh->coneOrientations[coff+cf] = 0; 4700 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4701 /* Shifted by 1 */ 4702 mesh->coneOrientations[coff+cf] = 1; 4703 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4704 /* Shifted by 2 */ 4705 mesh->coneOrientations[coff+cf] = 2; 4706 } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4707 /* Start at edge 1, and reverse orientation */ 4708 mesh->coneOrientations[coff+cf] = -(1+1); 4709 } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4710 /* Start at index 0, and reverse orientation */ 4711 mesh->coneOrientations[coff+cf] = -(0+1); 4712 } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4713 /* Start at index 2, and reverse orientation */ 4714 mesh->coneOrientations[coff+cf] = -(2+1); 4715 } 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); 4716 ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4717 } 4718 } 4719 { 4720 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4721 ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4722 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4723 } 4724 *dmInt = idm; 4725 PetscFunctionReturn(0); 4726 } 4727 4728 #undef __FUNCT__ 4729 #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4730 /* 4731 This takes as input the common mesh generator output, a list of the vertices for each cell 4732 */ 4733 PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4734 { 4735 PetscInt *cone, c, p; 4736 PetscErrorCode ierr; 4737 4738 PetscFunctionBegin; 4739 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4740 for (c = 0; c < numCells; ++c) { 4741 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4742 } 4743 ierr = DMSetUp(dm);CHKERRQ(ierr); 4744 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4745 for (c = 0; c < numCells; ++c) { 4746 for (p = 0; p < numCorners; ++p) { 4747 cone[p] = cells[c*numCorners+p]+numCells; 4748 } 4749 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4750 } 4751 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4752 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4753 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4754 PetscFunctionReturn(0); 4755 } 4756 4757 #undef __FUNCT__ 4758 #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4759 /* 4760 This takes as input the coordinates for each vertex 4761 */ 4762 PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4763 { 4764 PetscSection coordSection; 4765 Vec coordinates; 4766 PetscScalar *coords; 4767 PetscInt coordSize, v, d; 4768 PetscErrorCode ierr; 4769 4770 PetscFunctionBegin; 4771 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4772 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4773 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4774 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4775 for (v = numCells; v < numCells+numVertices; ++v) { 4776 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4777 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4778 } 4779 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4780 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4781 ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4782 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4783 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4784 ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4785 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4786 for (v = 0; v < numVertices; ++v) { 4787 for (d = 0; d < spaceDim; ++d) { 4788 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4789 } 4790 } 4791 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4792 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4793 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4794 PetscFunctionReturn(0); 4795 } 4796 4797 #undef __FUNCT__ 4798 #define __FUNCT__ "DMPlexCreateFromCellList" 4799 /* 4800 This takes as input the common mesh generator output, a list of the vertices for each cell 4801 */ 4802 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4803 { 4804 PetscErrorCode ierr; 4805 4806 PetscFunctionBegin; 4807 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4808 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4809 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4810 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4811 if (interpolate) { 4812 DM idm; 4813 4814 switch (dim) { 4815 case 2: 4816 ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4817 case 3: 4818 ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4819 default: 4820 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4821 } 4822 ierr = DMDestroy(dm);CHKERRQ(ierr); 4823 *dm = idm; 4824 } 4825 ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4826 PetscFunctionReturn(0); 4827 } 4828 4829 #if defined(PETSC_HAVE_TRIANGLE) 4830 #include <triangle.h> 4831 4832 #undef __FUNCT__ 4833 #define __FUNCT__ "InitInput_Triangle" 4834 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4835 { 4836 PetscFunctionBegin; 4837 inputCtx->numberofpoints = 0; 4838 inputCtx->numberofpointattributes = 0; 4839 inputCtx->pointlist = PETSC_NULL; 4840 inputCtx->pointattributelist = PETSC_NULL; 4841 inputCtx->pointmarkerlist = PETSC_NULL; 4842 inputCtx->numberofsegments = 0; 4843 inputCtx->segmentlist = PETSC_NULL; 4844 inputCtx->segmentmarkerlist = PETSC_NULL; 4845 inputCtx->numberoftriangleattributes = 0; 4846 inputCtx->trianglelist = PETSC_NULL; 4847 inputCtx->numberofholes = 0; 4848 inputCtx->holelist = PETSC_NULL; 4849 inputCtx->numberofregions = 0; 4850 inputCtx->regionlist = PETSC_NULL; 4851 PetscFunctionReturn(0); 4852 } 4853 4854 #undef __FUNCT__ 4855 #define __FUNCT__ "InitOutput_Triangle" 4856 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4857 { 4858 PetscFunctionBegin; 4859 outputCtx->numberofpoints = 0; 4860 outputCtx->pointlist = PETSC_NULL; 4861 outputCtx->pointattributelist = PETSC_NULL; 4862 outputCtx->pointmarkerlist = PETSC_NULL; 4863 outputCtx->numberoftriangles = 0; 4864 outputCtx->trianglelist = PETSC_NULL; 4865 outputCtx->triangleattributelist = PETSC_NULL; 4866 outputCtx->neighborlist = PETSC_NULL; 4867 outputCtx->segmentlist = PETSC_NULL; 4868 outputCtx->segmentmarkerlist = PETSC_NULL; 4869 outputCtx->numberofedges = 0; 4870 outputCtx->edgelist = PETSC_NULL; 4871 outputCtx->edgemarkerlist = PETSC_NULL; 4872 PetscFunctionReturn(0); 4873 } 4874 4875 #undef __FUNCT__ 4876 #define __FUNCT__ "FiniOutput_Triangle" 4877 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4878 { 4879 PetscFunctionBegin; 4880 free(outputCtx->pointmarkerlist); 4881 free(outputCtx->edgelist); 4882 free(outputCtx->edgemarkerlist); 4883 free(outputCtx->trianglelist); 4884 free(outputCtx->neighborlist); 4885 PetscFunctionReturn(0); 4886 } 4887 4888 #undef __FUNCT__ 4889 #define __FUNCT__ "DMPlexGenerate_Triangle" 4890 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4891 { 4892 MPI_Comm comm = ((PetscObject) boundary)->comm; 4893 PetscInt dim = 2; 4894 const PetscBool createConvexHull = PETSC_FALSE; 4895 const PetscBool constrained = PETSC_FALSE; 4896 struct triangulateio in; 4897 struct triangulateio out; 4898 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4899 PetscMPIInt rank; 4900 PetscErrorCode ierr; 4901 4902 PetscFunctionBegin; 4903 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4904 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4905 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4906 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4907 in.numberofpoints = vEnd - vStart; 4908 if (in.numberofpoints > 0) { 4909 PetscSection coordSection; 4910 Vec coordinates; 4911 PetscScalar *array; 4912 4913 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4914 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4915 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4916 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4917 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4918 for (v = vStart; v < vEnd; ++v) { 4919 const PetscInt idx = v - vStart; 4920 PetscInt off, d; 4921 4922 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4923 for (d = 0; d < dim; ++d) { 4924 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4925 } 4926 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4927 } 4928 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4929 } 4930 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4931 in.numberofsegments = eEnd - eStart; 4932 if (in.numberofsegments > 0) { 4933 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4934 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4935 for (e = eStart; e < eEnd; ++e) { 4936 const PetscInt idx = e - eStart; 4937 const PetscInt *cone; 4938 4939 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4940 in.segmentlist[idx*2+0] = cone[0] - vStart; 4941 in.segmentlist[idx*2+1] = cone[1] - vStart; 4942 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4943 } 4944 } 4945 #if 0 /* Do not currently support holes */ 4946 PetscReal *holeCoords; 4947 PetscInt h, d; 4948 4949 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4950 if (in.numberofholes > 0) { 4951 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4952 for (h = 0; h < in.numberofholes; ++h) { 4953 for (d = 0; d < dim; ++d) { 4954 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4955 } 4956 } 4957 } 4958 #endif 4959 if (!rank) { 4960 char args[32]; 4961 4962 /* Take away 'Q' for verbose output */ 4963 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4964 if (createConvexHull) { 4965 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4966 } 4967 if (constrained) { 4968 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4969 } 4970 triangulate(args, &in, &out, PETSC_NULL); 4971 } 4972 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4973 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4974 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4975 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4976 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4977 4978 { 4979 const PetscInt numCorners = 3; 4980 const PetscInt numCells = out.numberoftriangles; 4981 const PetscInt numVertices = out.numberofpoints; 4982 const int *cells = out.trianglelist; 4983 const double *meshCoords = out.pointlist; 4984 4985 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4986 /* Set labels */ 4987 for (v = 0; v < numVertices; ++v) { 4988 if (out.pointmarkerlist[v]) { 4989 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4990 } 4991 } 4992 if (interpolate) { 4993 for (e = 0; e < out.numberofedges; e++) { 4994 if (out.edgemarkerlist[e]) { 4995 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4996 const PetscInt *edges; 4997 PetscInt numEdges; 4998 4999 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5000 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5001 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5002 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5003 } 5004 } 5005 } 5006 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5007 } 5008 #if 0 /* Do not currently support holes */ 5009 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5010 #endif 5011 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5012 PetscFunctionReturn(0); 5013 } 5014 5015 #undef __FUNCT__ 5016 #define __FUNCT__ "DMPlexRefine_Triangle" 5017 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 5018 { 5019 MPI_Comm comm = ((PetscObject) dm)->comm; 5020 PetscInt dim = 2; 5021 struct triangulateio in; 5022 struct triangulateio out; 5023 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5024 PetscMPIInt rank; 5025 PetscErrorCode ierr; 5026 5027 PetscFunctionBegin; 5028 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5029 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 5030 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 5031 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5032 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5033 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5034 in.numberofpoints = vEnd - vStart; 5035 if (in.numberofpoints > 0) { 5036 PetscSection coordSection; 5037 Vec coordinates; 5038 PetscScalar *array; 5039 5040 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 5041 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 5042 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5043 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5044 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5045 for (v = vStart; v < vEnd; ++v) { 5046 const PetscInt idx = v - vStart; 5047 PetscInt off, d; 5048 5049 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5050 for (d = 0; d < dim; ++d) { 5051 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5052 } 5053 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5054 } 5055 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5056 } 5057 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5058 in.numberofcorners = 3; 5059 in.numberoftriangles = cEnd - cStart; 5060 in.trianglearealist = (double *) maxVolumes; 5061 if (in.numberoftriangles > 0) { 5062 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 5063 for (c = cStart; c < cEnd; ++c) { 5064 const PetscInt idx = c - cStart; 5065 PetscInt *closure = PETSC_NULL; 5066 PetscInt closureSize; 5067 5068 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5069 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 5070 for (v = 0; v < 3; ++v) { 5071 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 5072 } 5073 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5074 } 5075 } 5076 /* TODO: Segment markers are missing on input */ 5077 #if 0 /* Do not currently support holes */ 5078 PetscReal *holeCoords; 5079 PetscInt h, d; 5080 5081 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 5082 if (in.numberofholes > 0) { 5083 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 5084 for (h = 0; h < in.numberofholes; ++h) { 5085 for (d = 0; d < dim; ++d) { 5086 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 5087 } 5088 } 5089 } 5090 #endif 5091 if (!rank) { 5092 char args[32]; 5093 5094 /* Take away 'Q' for verbose output */ 5095 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 5096 triangulate(args, &in, &out, PETSC_NULL); 5097 } 5098 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 5099 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 5100 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 5101 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 5102 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 5103 5104 { 5105 const PetscInt numCorners = 3; 5106 const PetscInt numCells = out.numberoftriangles; 5107 const PetscInt numVertices = out.numberofpoints; 5108 const int *cells = out.trianglelist; 5109 const double *meshCoords = out.pointlist; 5110 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5111 5112 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5113 /* Set labels */ 5114 for (v = 0; v < numVertices; ++v) { 5115 if (out.pointmarkerlist[v]) { 5116 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5117 } 5118 } 5119 if (interpolate) { 5120 PetscInt e; 5121 5122 for (e = 0; e < out.numberofedges; e++) { 5123 if (out.edgemarkerlist[e]) { 5124 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5125 const PetscInt *edges; 5126 PetscInt numEdges; 5127 5128 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5129 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5130 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5131 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5132 } 5133 } 5134 } 5135 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5136 } 5137 #if 0 /* Do not currently support holes */ 5138 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 5139 #endif 5140 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 5141 PetscFunctionReturn(0); 5142 } 5143 #endif 5144 5145 #if defined(PETSC_HAVE_TETGEN) 5146 #include <tetgen.h> 5147 #undef __FUNCT__ 5148 #define __FUNCT__ "DMPlexGenerate_Tetgen" 5149 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 5150 { 5151 MPI_Comm comm = ((PetscObject) boundary)->comm; 5152 const PetscInt dim = 3; 5153 ::tetgenio in; 5154 ::tetgenio out; 5155 PetscInt vStart, vEnd, v, fStart, fEnd, f; 5156 PetscMPIInt rank; 5157 PetscErrorCode ierr; 5158 5159 PetscFunctionBegin; 5160 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5161 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5162 in.numberofpoints = vEnd - vStart; 5163 if (in.numberofpoints > 0) { 5164 PetscSection coordSection; 5165 Vec coordinates; 5166 PetscScalar *array; 5167 5168 in.pointlist = new double[in.numberofpoints*dim]; 5169 in.pointmarkerlist = new int[in.numberofpoints]; 5170 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5171 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5172 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5173 for (v = vStart; v < vEnd; ++v) { 5174 const PetscInt idx = v - vStart; 5175 PetscInt off, d; 5176 5177 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5178 for (d = 0; d < dim; ++d) { 5179 in.pointlist[idx*dim + d] = array[off+d]; 5180 } 5181 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5182 } 5183 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5184 } 5185 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5186 in.numberoffacets = fEnd - fStart; 5187 if (in.numberoffacets > 0) { 5188 in.facetlist = new tetgenio::facet[in.numberoffacets]; 5189 in.facetmarkerlist = new int[in.numberoffacets]; 5190 for (f = fStart; f < fEnd; ++f) { 5191 const PetscInt idx = f - fStart; 5192 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 5193 5194 in.facetlist[idx].numberofpolygons = 1; 5195 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 5196 in.facetlist[idx].numberofholes = 0; 5197 in.facetlist[idx].holelist = NULL; 5198 5199 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5200 for (p = 0; p < numPoints*2; p += 2) { 5201 const PetscInt point = points[p]; 5202 if ((point >= vStart) && (point < vEnd)) { 5203 points[numVertices++] = point; 5204 } 5205 } 5206 5207 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 5208 poly->numberofvertices = numVertices; 5209 poly->vertexlist = new int[poly->numberofvertices]; 5210 for (v = 0; v < numVertices; ++v) { 5211 const PetscInt vIdx = points[v] - vStart; 5212 poly->vertexlist[v] = vIdx; 5213 } 5214 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 5215 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5216 } 5217 } 5218 if (!rank) { 5219 char args[32]; 5220 5221 /* Take away 'Q' for verbose output */ 5222 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 5223 ::tetrahedralize(args, &in, &out); 5224 } 5225 { 5226 const PetscInt numCorners = 4; 5227 const PetscInt numCells = out.numberoftetrahedra; 5228 const PetscInt numVertices = out.numberofpoints; 5229 const int *cells = out.tetrahedronlist; 5230 const double *meshCoords = out.pointlist; 5231 5232 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5233 /* Set labels */ 5234 for (v = 0; v < numVertices; ++v) { 5235 if (out.pointmarkerlist[v]) { 5236 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5237 } 5238 } 5239 if (interpolate) { 5240 PetscInt e; 5241 5242 for (e = 0; e < out.numberofedges; e++) { 5243 if (out.edgemarkerlist[e]) { 5244 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5245 const PetscInt *edges; 5246 PetscInt numEdges; 5247 5248 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5249 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5250 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5251 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5252 } 5253 } 5254 for (f = 0; f < out.numberoftrifaces; f++) { 5255 if (out.trifacemarkerlist[f]) { 5256 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5257 const PetscInt *faces; 5258 PetscInt numFaces; 5259 5260 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5261 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5262 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5263 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5264 } 5265 } 5266 } 5267 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5268 } 5269 PetscFunctionReturn(0); 5270 } 5271 5272 #undef __FUNCT__ 5273 #define __FUNCT__ "DMPlexRefine_Tetgen" 5274 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 5275 { 5276 MPI_Comm comm = ((PetscObject) dm)->comm; 5277 const PetscInt dim = 3; 5278 ::tetgenio in; 5279 ::tetgenio out; 5280 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5281 PetscMPIInt rank; 5282 PetscErrorCode ierr; 5283 5284 PetscFunctionBegin; 5285 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5286 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5287 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5288 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5289 in.numberofpoints = vEnd - vStart; 5290 if (in.numberofpoints > 0) { 5291 PetscSection coordSection; 5292 Vec coordinates; 5293 PetscScalar *array; 5294 5295 in.pointlist = new double[in.numberofpoints*dim]; 5296 in.pointmarkerlist = new int[in.numberofpoints]; 5297 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5298 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5299 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5300 for (v = vStart; v < vEnd; ++v) { 5301 const PetscInt idx = v - vStart; 5302 PetscInt off, d; 5303 5304 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5305 for (d = 0; d < dim; ++d) { 5306 in.pointlist[idx*dim + d] = array[off+d]; 5307 } 5308 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 5309 } 5310 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5311 } 5312 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5313 in.numberofcorners = 4; 5314 in.numberoftetrahedra = cEnd - cStart; 5315 in.tetrahedronvolumelist = (double *) maxVolumes; 5316 if (in.numberoftetrahedra > 0) { 5317 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 5318 for (c = cStart; c < cEnd; ++c) { 5319 const PetscInt idx = c - cStart; 5320 PetscInt *closure = PETSC_NULL; 5321 PetscInt closureSize; 5322 5323 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5324 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5325 for (v = 0; v < 4; ++v) { 5326 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5327 } 5328 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5329 } 5330 } 5331 /* TODO: Put in boundary faces with markers */ 5332 if (!rank) { 5333 char args[32]; 5334 5335 /* Take away 'Q' for verbose output */ 5336 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 5337 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 5338 ::tetrahedralize(args, &in, &out); 5339 } 5340 in.tetrahedronvolumelist = NULL; 5341 5342 { 5343 const PetscInt numCorners = 4; 5344 const PetscInt numCells = out.numberoftetrahedra; 5345 const PetscInt numVertices = out.numberofpoints; 5346 const int *cells = out.tetrahedronlist; 5347 const double *meshCoords = out.pointlist; 5348 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5349 5350 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5351 /* Set labels */ 5352 for (v = 0; v < numVertices; ++v) { 5353 if (out.pointmarkerlist[v]) { 5354 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 5355 } 5356 } 5357 if (interpolate) { 5358 PetscInt e, f; 5359 5360 for (e = 0; e < out.numberofedges; e++) { 5361 if (out.edgemarkerlist[e]) { 5362 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 5363 const PetscInt *edges; 5364 PetscInt numEdges; 5365 5366 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5367 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5368 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 5369 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5370 } 5371 } 5372 for (f = 0; f < out.numberoftrifaces; f++) { 5373 if (out.trifacemarkerlist[f]) { 5374 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 5375 const PetscInt *faces; 5376 PetscInt numFaces; 5377 5378 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5379 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5380 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 5381 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5382 } 5383 } 5384 } 5385 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5386 } 5387 PetscFunctionReturn(0); 5388 } 5389 #endif 5390 5391 #if defined(PETSC_HAVE_CTETGEN) 5392 #include "ctetgen.h" 5393 5394 #undef __FUNCT__ 5395 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5396 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5397 { 5398 MPI_Comm comm = ((PetscObject) boundary)->comm; 5399 const PetscInt dim = 3; 5400 PLC *in, *out; 5401 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5402 PetscMPIInt rank; 5403 PetscErrorCode ierr; 5404 5405 PetscFunctionBegin; 5406 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5407 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5408 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5409 ierr = PLCCreate(&in);CHKERRQ(ierr); 5410 ierr = PLCCreate(&out);CHKERRQ(ierr); 5411 in->numberofpoints = vEnd - vStart; 5412 if (in->numberofpoints > 0) { 5413 PetscSection coordSection; 5414 Vec coordinates; 5415 PetscScalar *array; 5416 5417 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5418 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5419 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5420 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5421 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5422 for (v = vStart; v < vEnd; ++v) { 5423 const PetscInt idx = v - vStart; 5424 PetscInt off, d, m; 5425 5426 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5427 for (d = 0; d < dim; ++d) { 5428 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5429 } 5430 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5431 in->pointmarkerlist[idx] = (int) m; 5432 } 5433 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5434 } 5435 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5436 in->numberoffacets = fEnd - fStart; 5437 if (in->numberoffacets > 0) { 5438 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5439 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5440 for (f = fStart; f < fEnd; ++f) { 5441 const PetscInt idx = f - fStart; 5442 PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 5443 polygon *poly; 5444 5445 in->facetlist[idx].numberofpolygons = 1; 5446 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5447 in->facetlist[idx].numberofholes = 0; 5448 in->facetlist[idx].holelist = PETSC_NULL; 5449 5450 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5451 for (p = 0; p < numPoints*2; p += 2) { 5452 const PetscInt point = points[p]; 5453 if ((point >= vStart) && (point < vEnd)) { 5454 points[numVertices++] = point; 5455 } 5456 } 5457 5458 poly = in->facetlist[idx].polygonlist; 5459 poly->numberofvertices = numVertices; 5460 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5461 for (v = 0; v < numVertices; ++v) { 5462 const PetscInt vIdx = points[v] - vStart; 5463 poly->vertexlist[v] = vIdx; 5464 } 5465 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5466 in->facetmarkerlist[idx] = (int) m; 5467 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5468 } 5469 } 5470 if (!rank) { 5471 TetGenOpts t; 5472 5473 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5474 t.in = boundary; /* Should go away */ 5475 t.plc = 1; 5476 t.quality = 1; 5477 t.edgesout = 1; 5478 t.zeroindex = 1; 5479 t.quiet = 1; 5480 t.verbose = verbose; 5481 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5482 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5483 } 5484 { 5485 const PetscInt numCorners = 4; 5486 const PetscInt numCells = out->numberoftetrahedra; 5487 const PetscInt numVertices = out->numberofpoints; 5488 const int *cells = out->tetrahedronlist; 5489 const double *meshCoords = out->pointlist; 5490 5491 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5492 /* Set labels */ 5493 for (v = 0; v < numVertices; ++v) { 5494 if (out->pointmarkerlist[v]) { 5495 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5496 } 5497 } 5498 if (interpolate) { 5499 PetscInt e; 5500 5501 for (e = 0; e < out->numberofedges; e++) { 5502 if (out->edgemarkerlist[e]) { 5503 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5504 const PetscInt *edges; 5505 PetscInt numEdges; 5506 5507 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5508 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5509 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5510 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5511 } 5512 } 5513 for (f = 0; f < out->numberoftrifaces; f++) { 5514 if (out->trifacemarkerlist[f]) { 5515 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5516 const PetscInt *faces; 5517 PetscInt numFaces; 5518 5519 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5520 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5521 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5522 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5523 } 5524 } 5525 } 5526 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5527 } 5528 5529 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5530 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5531 PetscFunctionReturn(0); 5532 } 5533 5534 #undef __FUNCT__ 5535 #define __FUNCT__ "DMPlexRefine_CTetgen" 5536 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5537 { 5538 MPI_Comm comm = ((PetscObject) dm)->comm; 5539 const PetscInt dim = 3; 5540 PLC *in, *out; 5541 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5542 PetscMPIInt rank; 5543 PetscErrorCode ierr; 5544 5545 PetscFunctionBegin; 5546 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5547 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5548 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5549 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5550 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5551 ierr = PLCCreate(&in);CHKERRQ(ierr); 5552 ierr = PLCCreate(&out);CHKERRQ(ierr); 5553 in->numberofpoints = vEnd - vStart; 5554 if (in->numberofpoints > 0) { 5555 PetscSection coordSection; 5556 Vec coordinates; 5557 PetscScalar *array; 5558 5559 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5560 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5561 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5562 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5563 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5564 for (v = vStart; v < vEnd; ++v) { 5565 const PetscInt idx = v - vStart; 5566 PetscInt off, d, m; 5567 5568 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5569 for (d = 0; d < dim; ++d) { 5570 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5571 } 5572 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5573 in->pointmarkerlist[idx] = (int) m; 5574 } 5575 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5576 } 5577 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5578 in->numberofcorners = 4; 5579 in->numberoftetrahedra = cEnd - cStart; 5580 in->tetrahedronvolumelist = maxVolumes; 5581 if (in->numberoftetrahedra > 0) { 5582 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5583 for (c = cStart; c < cEnd; ++c) { 5584 const PetscInt idx = c - cStart; 5585 PetscInt *closure = PETSC_NULL; 5586 PetscInt closureSize; 5587 5588 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5589 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5590 for (v = 0; v < 4; ++v) { 5591 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5592 } 5593 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5594 } 5595 } 5596 if (!rank) { 5597 TetGenOpts t; 5598 5599 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5600 t.in = dm; /* Should go away */ 5601 t.refine = 1; 5602 t.varvolume = 1; 5603 t.quality = 1; 5604 t.edgesout = 1; 5605 t.zeroindex = 1; 5606 t.quiet = 1; 5607 t.verbose = verbose; /* Change this */ 5608 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5609 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5610 } 5611 { 5612 const PetscInt numCorners = 4; 5613 const PetscInt numCells = out->numberoftetrahedra; 5614 const PetscInt numVertices = out->numberofpoints; 5615 const int *cells = out->tetrahedronlist; 5616 const double *meshCoords = out->pointlist; 5617 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5618 5619 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5620 /* Set labels */ 5621 for (v = 0; v < numVertices; ++v) { 5622 if (out->pointmarkerlist[v]) { 5623 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5624 } 5625 } 5626 if (interpolate) { 5627 PetscInt e, f; 5628 5629 for (e = 0; e < out->numberofedges; e++) { 5630 if (out->edgemarkerlist[e]) { 5631 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5632 const PetscInt *edges; 5633 PetscInt numEdges; 5634 5635 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5636 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5637 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5638 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5639 } 5640 } 5641 for (f = 0; f < out->numberoftrifaces; f++) { 5642 if (out->trifacemarkerlist[f]) { 5643 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5644 const PetscInt *faces; 5645 PetscInt numFaces; 5646 5647 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5648 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5649 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5650 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5651 } 5652 } 5653 } 5654 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5655 } 5656 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5657 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5658 PetscFunctionReturn(0); 5659 } 5660 #endif 5661 5662 #undef __FUNCT__ 5663 #define __FUNCT__ "DMPlexGenerate" 5664 /*@C 5665 DMPlexGenerate - Generates a mesh. 5666 5667 Not Collective 5668 5669 Input Parameters: 5670 + boundary - The DMPlex boundary object 5671 . name - The mesh generation package name 5672 - interpolate - Flag to create intermediate mesh elements 5673 5674 Output Parameter: 5675 . mesh - The DMPlex object 5676 5677 Level: intermediate 5678 5679 .keywords: mesh, elements 5680 .seealso: DMPlexCreate(), DMRefine() 5681 @*/ 5682 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5683 { 5684 PetscInt dim; 5685 char genname[1024]; 5686 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5687 PetscErrorCode ierr; 5688 5689 PetscFunctionBegin; 5690 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5691 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5692 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5693 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5694 if (flg) {name = genname;} 5695 if (name) { 5696 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5697 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5698 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5699 } 5700 switch (dim) { 5701 case 1: 5702 if (!name || isTriangle) { 5703 #if defined(PETSC_HAVE_TRIANGLE) 5704 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5705 #else 5706 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5707 #endif 5708 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5709 break; 5710 case 2: 5711 if (!name || isCTetgen) { 5712 #if defined(PETSC_HAVE_CTETGEN) 5713 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5714 #else 5715 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5716 #endif 5717 } else if (isTetgen) { 5718 #if defined(PETSC_HAVE_TETGEN) 5719 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5720 #else 5721 SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5722 #endif 5723 } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5724 break; 5725 default: 5726 SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5727 } 5728 PetscFunctionReturn(0); 5729 } 5730 5731 typedef PetscInt CellRefiner; 5732 5733 #undef __FUNCT__ 5734 #define __FUNCT__ "GetDepthStart_Private" 5735 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5736 { 5737 PetscFunctionBegin; 5738 if (cStart) *cStart = 0; 5739 if (vStart) *vStart = depthSize[depth]; 5740 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5741 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5742 PetscFunctionReturn(0); 5743 } 5744 5745 #undef __FUNCT__ 5746 #define __FUNCT__ "GetDepthEnd_Private" 5747 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5748 { 5749 PetscFunctionBegin; 5750 if (cEnd) *cEnd = depthSize[depth]; 5751 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5752 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5753 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5754 PetscFunctionReturn(0); 5755 } 5756 5757 #undef __FUNCT__ 5758 #define __FUNCT__ "CellRefinerGetSizes" 5759 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5760 { 5761 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5762 PetscErrorCode ierr; 5763 5764 PetscFunctionBegin; 5765 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5766 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5767 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5768 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5769 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5770 switch (refiner) { 5771 case 1: 5772 /* Simplicial 2D */ 5773 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5774 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5775 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5776 break; 5777 case 3: 5778 /* Hybrid 2D */ 5779 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5780 cMax = PetscMin(cEnd, cMax); 5781 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5782 fMax = PetscMin(fEnd, fMax); 5783 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5784 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 */ 5785 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5786 break; 5787 case 2: 5788 /* Hex 2D */ 5789 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5790 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5791 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5792 break; 5793 default: 5794 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5795 } 5796 PetscFunctionReturn(0); 5797 } 5798 5799 #undef __FUNCT__ 5800 #define __FUNCT__ "CellRefinerSetConeSizes" 5801 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5802 { 5803 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5804 PetscErrorCode ierr; 5805 5806 PetscFunctionBegin; 5807 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5808 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5809 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5810 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5811 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5812 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5813 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5814 switch (refiner) { 5815 case 1: 5816 /* Simplicial 2D */ 5817 /* All cells have 3 faces */ 5818 for (c = cStart; c < cEnd; ++c) { 5819 for (r = 0; r < 4; ++r) { 5820 const PetscInt newp = (c - cStart)*4 + r; 5821 5822 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5823 } 5824 } 5825 /* Split faces have 2 vertices and the same cells as the parent */ 5826 for (f = fStart; f < fEnd; ++f) { 5827 for (r = 0; r < 2; ++r) { 5828 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5829 PetscInt size; 5830 5831 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5832 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5833 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5834 } 5835 } 5836 /* Interior faces have 2 vertices and 2 cells */ 5837 for (c = cStart; c < cEnd; ++c) { 5838 for (r = 0; r < 3; ++r) { 5839 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5840 5841 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5842 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5843 } 5844 } 5845 /* Old vertices have identical supports */ 5846 for (v = vStart; v < vEnd; ++v) { 5847 const PetscInt newp = vStartNew + (v - vStart); 5848 PetscInt size; 5849 5850 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5851 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5852 } 5853 /* Face vertices have 2 + cells*2 supports */ 5854 for (f = fStart; f < fEnd; ++f) { 5855 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5856 PetscInt size; 5857 5858 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5859 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5860 } 5861 break; 5862 case 2: 5863 /* Hex 2D */ 5864 /* All cells have 4 faces */ 5865 for (c = cStart; c < cEnd; ++c) { 5866 for (r = 0; r < 4; ++r) { 5867 const PetscInt newp = (c - cStart)*4 + r; 5868 5869 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5870 } 5871 } 5872 /* Split faces have 2 vertices and the same cells as the parent */ 5873 for (f = fStart; f < fEnd; ++f) { 5874 for (r = 0; r < 2; ++r) { 5875 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5876 PetscInt size; 5877 5878 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5879 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5880 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5881 } 5882 } 5883 /* Interior faces have 2 vertices and 2 cells */ 5884 for (c = cStart; c < cEnd; ++c) { 5885 for (r = 0; r < 4; ++r) { 5886 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5887 5888 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5889 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5890 } 5891 } 5892 /* Old vertices have identical supports */ 5893 for (v = vStart; v < vEnd; ++v) { 5894 const PetscInt newp = vStartNew + (v - vStart); 5895 PetscInt size; 5896 5897 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5898 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5899 } 5900 /* Face vertices have 2 + cells supports */ 5901 for (f = fStart; f < fEnd; ++f) { 5902 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5903 PetscInt size; 5904 5905 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5906 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5907 } 5908 /* Cell vertices have 4 supports */ 5909 for (c = cStart; c < cEnd; ++c) { 5910 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5911 5912 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5913 } 5914 break; 5915 case 3: 5916 /* Hybrid 2D */ 5917 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5918 cMax = PetscMin(cEnd, cMax); 5919 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5920 fMax = PetscMin(fEnd, fMax); 5921 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5922 /* Interior cells have 3 faces */ 5923 for (c = cStart; c < cMax; ++c) { 5924 for (r = 0; r < 4; ++r) { 5925 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5926 5927 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5928 } 5929 } 5930 /* Hybrid cells have 4 faces */ 5931 for (c = cMax; c < cEnd; ++c) { 5932 for (r = 0; r < 2; ++r) { 5933 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5934 5935 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5936 } 5937 } 5938 /* Interior split faces have 2 vertices and the same cells as the parent */ 5939 for (f = fStart; f < fMax; ++f) { 5940 for (r = 0; r < 2; ++r) { 5941 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5942 PetscInt size; 5943 5944 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5945 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5946 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5947 } 5948 } 5949 /* Interior cell faces have 2 vertices and 2 cells */ 5950 for (c = cStart; c < cMax; ++c) { 5951 for (r = 0; r < 3; ++r) { 5952 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5953 5954 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5955 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5956 } 5957 } 5958 /* Hybrid faces have 2 vertices and the same cells */ 5959 for (f = fMax; f < fEnd; ++f) { 5960 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5961 PetscInt size; 5962 5963 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5964 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5965 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5966 } 5967 /* Hybrid cell faces have 2 vertices and 2 cells */ 5968 for (c = cMax; c < cEnd; ++c) { 5969 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5970 5971 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5972 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5973 } 5974 /* Old vertices have identical supports */ 5975 for (v = vStart; v < vEnd; ++v) { 5976 const PetscInt newp = vStartNew + (v - vStart); 5977 PetscInt size; 5978 5979 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5980 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5981 } 5982 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5983 for (f = fStart; f < fMax; ++f) { 5984 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5985 const PetscInt *support; 5986 PetscInt size, newSize = 2, s; 5987 5988 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5989 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5990 for (s = 0; s < size; ++s) { 5991 if (support[s] >= cMax) { 5992 newSize += 1; 5993 } else { 5994 newSize += 2; 5995 } 5996 } 5997 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5998 } 5999 break; 6000 default: 6001 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6002 } 6003 PetscFunctionReturn(0); 6004 } 6005 6006 #undef __FUNCT__ 6007 #define __FUNCT__ "CellRefinerSetCones" 6008 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6009 { 6010 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; 6011 PetscInt maxSupportSize, *supportRef; 6012 PetscErrorCode ierr; 6013 6014 PetscFunctionBegin; 6015 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6016 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6017 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6018 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6019 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6020 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6021 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6022 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 6023 switch (refiner) { 6024 case 1: 6025 /* Simplicial 2D */ 6026 /* 6027 2 6028 |\ 6029 | \ 6030 | \ 6031 | \ 6032 | C \ 6033 | \ 6034 | \ 6035 2---1---1 6036 |\ D / \ 6037 | 2 0 \ 6038 |A \ / B \ 6039 0---0-------1 6040 */ 6041 /* All cells have 3 faces */ 6042 for (c = cStart; c < cEnd; ++c) { 6043 const PetscInt newp = cStartNew + (c - cStart)*4; 6044 const PetscInt *cone, *ornt; 6045 PetscInt coneNew[3], orntNew[3]; 6046 6047 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6048 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6049 /* A triangle */ 6050 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6051 orntNew[0] = ornt[0]; 6052 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6053 orntNew[1] = -2; 6054 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6055 orntNew[2] = ornt[2]; 6056 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6057 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6058 #if 1 6059 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); 6060 for (p = 0; p < 3; ++p) { 6061 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); 6062 } 6063 #endif 6064 /* B triangle */ 6065 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6066 orntNew[0] = ornt[0]; 6067 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6068 orntNew[1] = ornt[1]; 6069 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6070 orntNew[2] = -2; 6071 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6072 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6073 #if 1 6074 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); 6075 for (p = 0; p < 3; ++p) { 6076 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); 6077 } 6078 #endif 6079 /* C triangle */ 6080 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6081 orntNew[0] = -2; 6082 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6083 orntNew[1] = ornt[1]; 6084 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6085 orntNew[2] = ornt[2]; 6086 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6087 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6088 #if 1 6089 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); 6090 for (p = 0; p < 3; ++p) { 6091 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6092 } 6093 #endif 6094 /* D triangle */ 6095 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 6096 orntNew[0] = 0; 6097 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 6098 orntNew[1] = 0; 6099 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 6100 orntNew[2] = 0; 6101 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6102 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6103 #if 1 6104 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); 6105 for (p = 0; p < 3; ++p) { 6106 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); 6107 } 6108 #endif 6109 } 6110 /* Split faces have 2 vertices and the same cells as the parent */ 6111 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6112 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6113 for (f = fStart; f < fEnd; ++f) { 6114 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6115 6116 for (r = 0; r < 2; ++r) { 6117 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6118 const PetscInt *cone, *support; 6119 PetscInt coneNew[2], coneSize, c, supportSize, s; 6120 6121 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6122 coneNew[0] = vStartNew + (cone[0] - vStart); 6123 coneNew[1] = vStartNew + (cone[1] - vStart); 6124 coneNew[(r+1)%2] = newv; 6125 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6126 #if 1 6127 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6128 for (p = 0; p < 2; ++p) { 6129 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); 6130 } 6131 #endif 6132 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6133 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6134 for (s = 0; s < supportSize; ++s) { 6135 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6136 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6137 for (c = 0; c < coneSize; ++c) { 6138 if (cone[c] == f) { 6139 break; 6140 } 6141 } 6142 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6143 } 6144 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6145 #if 1 6146 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6147 for (p = 0; p < supportSize; ++p) { 6148 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); 6149 } 6150 #endif 6151 } 6152 } 6153 /* Interior faces have 2 vertices and 2 cells */ 6154 for (c = cStart; c < cEnd; ++c) { 6155 const PetscInt *cone; 6156 6157 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6158 for (r = 0; r < 3; ++r) { 6159 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 6160 PetscInt coneNew[2]; 6161 PetscInt supportNew[2]; 6162 6163 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6164 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6165 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6166 #if 1 6167 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6168 for (p = 0; p < 2; ++p) { 6169 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); 6170 } 6171 #endif 6172 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6173 supportNew[1] = (c - cStart)*4 + 3; 6174 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6175 #if 1 6176 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6177 for (p = 0; p < 2; ++p) { 6178 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); 6179 } 6180 #endif 6181 } 6182 } 6183 /* Old vertices have identical supports */ 6184 for (v = vStart; v < vEnd; ++v) { 6185 const PetscInt newp = vStartNew + (v - vStart); 6186 const PetscInt *support, *cone; 6187 PetscInt size, s; 6188 6189 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6190 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6191 for (s = 0; s < size; ++s) { 6192 PetscInt r = 0; 6193 6194 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6195 if (cone[1] == v) r = 1; 6196 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6197 } 6198 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6199 #if 1 6200 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6201 for (p = 0; p < size; ++p) { 6202 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); 6203 } 6204 #endif 6205 } 6206 /* Face vertices have 2 + cells*2 supports */ 6207 for (f = fStart; f < fEnd; ++f) { 6208 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6209 const PetscInt *cone, *support; 6210 PetscInt size, s; 6211 6212 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6213 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6214 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6215 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6216 for (s = 0; s < size; ++s) { 6217 PetscInt r = 0; 6218 6219 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6220 if (cone[1] == f) r = 1; 6221 else if (cone[2] == f) r = 2; 6222 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6223 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 6224 } 6225 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6226 #if 1 6227 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6228 for (p = 0; p < 2+size*2; ++p) { 6229 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); 6230 } 6231 #endif 6232 } 6233 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6234 break; 6235 case 2: 6236 /* Hex 2D */ 6237 /* 6238 3---------2---------2 6239 | | | 6240 | D 2 C | 6241 | | | 6242 3----3----0----1----1 6243 | | | 6244 | A 0 B | 6245 | | | 6246 0---------0---------1 6247 */ 6248 /* All cells have 4 faces */ 6249 for (c = cStart; c < cEnd; ++c) { 6250 const PetscInt newp = (c - cStart)*4; 6251 const PetscInt *cone, *ornt; 6252 PetscInt coneNew[4], orntNew[4]; 6253 6254 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6255 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6256 /* A quad */ 6257 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6258 orntNew[0] = ornt[0]; 6259 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6260 orntNew[1] = 0; 6261 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6262 orntNew[2] = -2; 6263 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 6264 orntNew[3] = ornt[3]; 6265 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6266 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6267 #if 1 6268 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); 6269 for (p = 0; p < 4; ++p) { 6270 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); 6271 } 6272 #endif 6273 /* B quad */ 6274 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6275 orntNew[0] = ornt[0]; 6276 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6277 orntNew[1] = ornt[1]; 6278 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6279 orntNew[2] = 0; 6280 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 6281 orntNew[3] = -2; 6282 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6283 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6284 #if 1 6285 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); 6286 for (p = 0; p < 4; ++p) { 6287 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); 6288 } 6289 #endif 6290 /* C quad */ 6291 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 6292 orntNew[0] = -2; 6293 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6294 orntNew[1] = ornt[1]; 6295 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6296 orntNew[2] = ornt[2]; 6297 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6298 orntNew[3] = 0; 6299 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6300 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6301 #if 1 6302 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); 6303 for (p = 0; p < 4; ++p) { 6304 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); 6305 } 6306 #endif 6307 /* D quad */ 6308 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 6309 orntNew[0] = 0; 6310 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 6311 orntNew[1] = -2; 6312 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6313 orntNew[2] = ornt[2]; 6314 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 6315 orntNew[3] = ornt[3]; 6316 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6317 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6318 #if 1 6319 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); 6320 for (p = 0; p < 4; ++p) { 6321 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); 6322 } 6323 #endif 6324 } 6325 /* Split faces have 2 vertices and the same cells as the parent */ 6326 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6327 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6328 for (f = fStart; f < fEnd; ++f) { 6329 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6330 6331 for (r = 0; r < 2; ++r) { 6332 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6333 const PetscInt *cone, *support; 6334 PetscInt coneNew[2], coneSize, c, supportSize, s; 6335 6336 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6337 coneNew[0] = vStartNew + (cone[0] - vStart); 6338 coneNew[1] = vStartNew + (cone[1] - vStart); 6339 coneNew[(r+1)%2] = newv; 6340 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6341 #if 1 6342 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6343 for (p = 0; p < 2; ++p) { 6344 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); 6345 } 6346 #endif 6347 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6348 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6349 for (s = 0; s < supportSize; ++s) { 6350 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6351 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6352 for (c = 0; c < coneSize; ++c) { 6353 if (cone[c] == f) { 6354 break; 6355 } 6356 } 6357 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 6358 } 6359 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6360 #if 1 6361 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6362 for (p = 0; p < supportSize; ++p) { 6363 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); 6364 } 6365 #endif 6366 } 6367 } 6368 /* Interior faces have 2 vertices and 2 cells */ 6369 for (c = cStart; c < cEnd; ++c) { 6370 const PetscInt *cone; 6371 PetscInt coneNew[2], supportNew[2]; 6372 6373 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6374 for (r = 0; r < 4; ++r) { 6375 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6376 6377 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6378 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6379 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6380 #if 1 6381 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6382 for (p = 0; p < 2; ++p) { 6383 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); 6384 } 6385 #endif 6386 supportNew[0] = (c - cStart)*4 + r; 6387 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6388 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6389 #if 1 6390 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6391 for (p = 0; p < 2; ++p) { 6392 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); 6393 } 6394 #endif 6395 } 6396 } 6397 /* Old vertices have identical supports */ 6398 for (v = vStart; v < vEnd; ++v) { 6399 const PetscInt newp = vStartNew + (v - vStart); 6400 const PetscInt *support, *cone; 6401 PetscInt size, s; 6402 6403 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6404 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6405 for (s = 0; s < size; ++s) { 6406 PetscInt r = 0; 6407 6408 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6409 if (cone[1] == v) r = 1; 6410 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6411 } 6412 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6413 #if 1 6414 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6415 for (p = 0; p < size; ++p) { 6416 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); 6417 } 6418 #endif 6419 } 6420 /* Face vertices have 2 + cells supports */ 6421 for (f = fStart; f < fEnd; ++f) { 6422 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6423 const PetscInt *cone, *support; 6424 PetscInt size, s; 6425 6426 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6427 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6428 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6429 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6430 for (s = 0; s < size; ++s) { 6431 PetscInt r = 0; 6432 6433 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6434 if (cone[1] == f) r = 1; 6435 else if (cone[2] == f) r = 2; 6436 else if (cone[3] == f) r = 3; 6437 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6438 } 6439 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6440 #if 1 6441 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6442 for (p = 0; p < 2+size; ++p) { 6443 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); 6444 } 6445 #endif 6446 } 6447 /* Cell vertices have 4 supports */ 6448 for (c = cStart; c < cEnd; ++c) { 6449 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6450 PetscInt supportNew[4]; 6451 6452 for (r = 0; r < 4; ++r) { 6453 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6454 } 6455 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6456 } 6457 break; 6458 case 3: 6459 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6460 cMax = PetscMin(cEnd, cMax); 6461 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6462 fMax = PetscMin(fEnd, fMax); 6463 /* Interior cells have 3 faces */ 6464 for (c = cStart; c < cMax; ++c) { 6465 const PetscInt newp = cStartNew + (c - cStart)*4; 6466 const PetscInt *cone, *ornt; 6467 PetscInt coneNew[3], orntNew[3]; 6468 6469 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6470 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6471 /* A triangle */ 6472 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6473 orntNew[0] = ornt[0]; 6474 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6475 orntNew[1] = -2; 6476 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6477 orntNew[2] = ornt[2]; 6478 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6479 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6480 #if 1 6481 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); 6482 for (p = 0; p < 3; ++p) { 6483 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); 6484 } 6485 #endif 6486 /* B triangle */ 6487 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6488 orntNew[0] = ornt[0]; 6489 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6490 orntNew[1] = ornt[1]; 6491 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6492 orntNew[2] = -2; 6493 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6494 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6495 #if 1 6496 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); 6497 for (p = 0; p < 3; ++p) { 6498 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); 6499 } 6500 #endif 6501 /* C triangle */ 6502 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6503 orntNew[0] = -2; 6504 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6505 orntNew[1] = ornt[1]; 6506 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6507 orntNew[2] = ornt[2]; 6508 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6509 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6510 #if 1 6511 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); 6512 for (p = 0; p < 3; ++p) { 6513 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); 6514 } 6515 #endif 6516 /* D triangle */ 6517 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6518 orntNew[0] = 0; 6519 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6520 orntNew[1] = 0; 6521 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6522 orntNew[2] = 0; 6523 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6524 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6525 #if 1 6526 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); 6527 for (p = 0; p < 3; ++p) { 6528 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); 6529 } 6530 #endif 6531 } 6532 /* 6533 2----3----3 6534 | | 6535 | B | 6536 | | 6537 0----4--- 1 6538 | | 6539 | A | 6540 | | 6541 0----2----1 6542 */ 6543 /* Hybrid cells have 4 faces */ 6544 for (c = cMax; c < cEnd; ++c) { 6545 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6546 const PetscInt *cone, *ornt; 6547 PetscInt coneNew[4], orntNew[4]; 6548 6549 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6550 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6551 /* A quad */ 6552 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6553 orntNew[0] = ornt[0]; 6554 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6555 orntNew[1] = ornt[1]; 6556 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6557 orntNew[2] = 0; 6558 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6559 orntNew[3] = 0; 6560 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6561 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6562 #if 1 6563 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); 6564 for (p = 0; p < 4; ++p) { 6565 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); 6566 } 6567 #endif 6568 /* B quad */ 6569 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6570 orntNew[0] = ornt[0]; 6571 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6572 orntNew[1] = ornt[1]; 6573 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6574 orntNew[2] = 0; 6575 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6576 orntNew[3] = 0; 6577 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6578 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6579 #if 1 6580 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); 6581 for (p = 0; p < 4; ++p) { 6582 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6583 } 6584 #endif 6585 } 6586 /* Interior split faces have 2 vertices and the same cells as the parent */ 6587 ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 6588 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6589 for (f = fStart; f < fMax; ++f) { 6590 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6591 6592 for (r = 0; r < 2; ++r) { 6593 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6594 const PetscInt *cone, *support; 6595 PetscInt coneNew[2], coneSize, c, supportSize, s; 6596 6597 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6598 coneNew[0] = vStartNew + (cone[0] - vStart); 6599 coneNew[1] = vStartNew + (cone[1] - vStart); 6600 coneNew[(r+1)%2] = newv; 6601 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6602 #if 1 6603 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6604 for (p = 0; p < 2; ++p) { 6605 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); 6606 } 6607 #endif 6608 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6609 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6610 for (s = 0; s < supportSize; ++s) { 6611 if (support[s] >= cMax) { 6612 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6613 } else { 6614 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6615 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6616 for (c = 0; c < coneSize; ++c) { 6617 if (cone[c] == f) { 6618 break; 6619 } 6620 } 6621 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6622 } 6623 } 6624 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6625 #if 1 6626 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6627 for (p = 0; p < supportSize; ++p) { 6628 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); 6629 } 6630 #endif 6631 } 6632 } 6633 /* Interior cell faces have 2 vertices and 2 cells */ 6634 for (c = cStart; c < cMax; ++c) { 6635 const PetscInt *cone; 6636 6637 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6638 for (r = 0; r < 3; ++r) { 6639 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6640 PetscInt coneNew[2]; 6641 PetscInt supportNew[2]; 6642 6643 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6644 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6645 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6646 #if 1 6647 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6648 for (p = 0; p < 2; ++p) { 6649 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); 6650 } 6651 #endif 6652 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6653 supportNew[1] = (c - cStart)*4 + 3; 6654 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6655 #if 1 6656 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6657 for (p = 0; p < 2; ++p) { 6658 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); 6659 } 6660 #endif 6661 } 6662 } 6663 /* Interior hybrid faces have 2 vertices and the same cells */ 6664 for (f = fMax; f < fEnd; ++f) { 6665 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6666 const PetscInt *cone; 6667 const PetscInt *support; 6668 PetscInt coneNew[2]; 6669 PetscInt supportNew[2]; 6670 PetscInt size, s, r; 6671 6672 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6673 coneNew[0] = vStartNew + (cone[0] - vStart); 6674 coneNew[1] = vStartNew + (cone[1] - vStart); 6675 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6676 #if 1 6677 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6678 for (p = 0; p < 2; ++p) { 6679 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); 6680 } 6681 #endif 6682 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6683 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6684 for (s = 0; s < size; ++s) { 6685 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6686 for (r = 0; r < 2; ++r) { 6687 if (cone[r+2] == f) break; 6688 } 6689 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6690 } 6691 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6692 #if 1 6693 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6694 for (p = 0; p < size; ++p) { 6695 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); 6696 } 6697 #endif 6698 } 6699 /* Cell hybrid faces have 2 vertices and 2 cells */ 6700 for (c = cMax; c < cEnd; ++c) { 6701 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6702 const PetscInt *cone; 6703 PetscInt coneNew[2]; 6704 PetscInt supportNew[2]; 6705 6706 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6707 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6708 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6709 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6710 #if 1 6711 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6712 for (p = 0; p < 2; ++p) { 6713 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); 6714 } 6715 #endif 6716 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6717 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6718 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6719 #if 1 6720 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6721 for (p = 0; p < 2; ++p) { 6722 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); 6723 } 6724 #endif 6725 } 6726 /* Old vertices have identical supports */ 6727 for (v = vStart; v < vEnd; ++v) { 6728 const PetscInt newp = vStartNew + (v - vStart); 6729 const PetscInt *support, *cone; 6730 PetscInt size, s; 6731 6732 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6733 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6734 for (s = 0; s < size; ++s) { 6735 if (support[s] >= fMax) { 6736 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6737 } else { 6738 PetscInt r = 0; 6739 6740 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6741 if (cone[1] == v) r = 1; 6742 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6743 } 6744 } 6745 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6746 #if 1 6747 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6748 for (p = 0; p < size; ++p) { 6749 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); 6750 } 6751 #endif 6752 } 6753 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6754 for (f = fStart; f < fMax; ++f) { 6755 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6756 const PetscInt *cone, *support; 6757 PetscInt size, newSize = 2, s; 6758 6759 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6760 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6761 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6762 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6763 for (s = 0; s < size; ++s) { 6764 PetscInt r = 0; 6765 6766 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6767 if (support[s] >= cMax) { 6768 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6769 newSize += 1; 6770 } else { 6771 if (cone[1] == f) r = 1; 6772 else if (cone[2] == f) r = 2; 6773 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6774 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6775 newSize += 2; 6776 } 6777 } 6778 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6779 #if 1 6780 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6781 for (p = 0; p < newSize; ++p) { 6782 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); 6783 } 6784 #endif 6785 } 6786 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6787 break; 6788 default: 6789 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6790 } 6791 PetscFunctionReturn(0); 6792 } 6793 6794 #undef __FUNCT__ 6795 #define __FUNCT__ "CellRefinerSetCoordinates" 6796 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6797 { 6798 PetscSection coordSection, coordSectionNew; 6799 Vec coordinates, coordinatesNew; 6800 PetscScalar *coords, *coordsNew; 6801 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6802 PetscErrorCode ierr; 6803 6804 PetscFunctionBegin; 6805 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6806 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6807 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6808 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6809 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6810 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, &fMax, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 6811 ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 6812 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6813 ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 6814 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6815 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6816 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6817 if (fMax < 0) fMax = fEnd; 6818 switch (refiner) { 6819 case 1: 6820 case 2: 6821 case 3: 6822 /* Simplicial and Hex 2D */ 6823 /* All vertices have the dim coordinates */ 6824 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6825 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6826 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6827 } 6828 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6829 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6830 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6831 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6832 ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 6833 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6834 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6835 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6836 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6837 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6838 /* Old vertices have the same coordinates */ 6839 for (v = vStart; v < vEnd; ++v) { 6840 const PetscInt newv = vStartNew + (v - vStart); 6841 PetscInt off, offnew, d; 6842 6843 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6844 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6845 for (d = 0; d < dim; ++d) { 6846 coordsNew[offnew+d] = coords[off+d]; 6847 } 6848 } 6849 /* Face vertices have the average of endpoint coordinates */ 6850 for (f = fStart; f < fMax; ++f) { 6851 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6852 const PetscInt *cone; 6853 PetscInt coneSize, offA, offB, offnew, d; 6854 6855 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6856 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6857 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6858 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6859 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6860 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6861 for (d = 0; d < dim; ++d) { 6862 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6863 } 6864 } 6865 /* Just Hex 2D */ 6866 if (refiner == 2) { 6867 /* Cell vertices have the average of corner coordinates */ 6868 for (c = cStart; c < cEnd; ++c) { 6869 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6870 PetscInt *cone = PETSC_NULL; 6871 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6872 6873 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6874 for (p = 0; p < closureSize*2; p += 2) { 6875 const PetscInt point = cone[p]; 6876 if ((point >= vStart) && (point < vEnd)) { 6877 cone[coneSize++] = point; 6878 } 6879 } 6880 if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6881 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6882 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6883 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6884 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6885 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6886 for (d = 0; d < dim; ++d) { 6887 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6888 } 6889 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6890 } 6891 } 6892 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6893 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6894 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6895 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6896 break; 6897 default: 6898 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6899 } 6900 PetscFunctionReturn(0); 6901 } 6902 6903 #undef __FUNCT__ 6904 #define __FUNCT__ "DMPlexCreateProcessSF" 6905 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6906 { 6907 PetscInt numRoots, numLeaves, l; 6908 const PetscInt *localPoints; 6909 const PetscSFNode *remotePoints; 6910 PetscInt *localPointsNew; 6911 PetscSFNode *remotePointsNew; 6912 PetscInt *ranks, *ranksNew; 6913 PetscErrorCode ierr; 6914 6915 PetscFunctionBegin; 6916 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6917 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6918 for (l = 0; l < numLeaves; ++l) { 6919 ranks[l] = remotePoints[l].rank; 6920 } 6921 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6922 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6923 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6924 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6925 for (l = 0; l < numLeaves; ++l) { 6926 ranksNew[l] = ranks[l]; 6927 localPointsNew[l] = l; 6928 remotePointsNew[l].index = 0; 6929 remotePointsNew[l].rank = ranksNew[l]; 6930 } 6931 ierr = PetscFree(ranks);CHKERRQ(ierr); 6932 ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6933 ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6934 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6935 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6936 PetscFunctionReturn(0); 6937 } 6938 6939 #undef __FUNCT__ 6940 #define __FUNCT__ "CellRefinerCreateSF" 6941 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6942 { 6943 PetscSF sf, sfNew, sfProcess; 6944 IS processRanks; 6945 MPI_Datatype depthType; 6946 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6947 const PetscInt *localPoints, *neighbors; 6948 const PetscSFNode *remotePoints; 6949 PetscInt *localPointsNew; 6950 PetscSFNode *remotePointsNew; 6951 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6952 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6953 PetscErrorCode ierr; 6954 6955 PetscFunctionBegin; 6956 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6957 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6958 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6959 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6960 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6961 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6962 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6963 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6964 switch (refiner) { 6965 case 3: 6966 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6967 cMax = PetscMin(cEnd, cMax); 6968 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6969 fMax = PetscMin(fEnd, fMax); 6970 } 6971 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6972 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6973 /* Caculate size of new SF */ 6974 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6975 if (numRoots < 0) PetscFunctionReturn(0); 6976 for (l = 0; l < numLeaves; ++l) { 6977 const PetscInt p = localPoints[l]; 6978 6979 switch (refiner) { 6980 case 1: 6981 /* Simplicial 2D */ 6982 if ((p >= vStart) && (p < vEnd)) { 6983 /* Old vertices stay the same */ 6984 ++numLeavesNew; 6985 } else if ((p >= fStart) && (p < fEnd)) { 6986 /* Old faces add new faces and vertex */ 6987 numLeavesNew += 1 + 2; 6988 } else if ((p >= cStart) && (p < cEnd)) { 6989 /* Old cells add new cells and interior faces */ 6990 numLeavesNew += 4 + 3; 6991 } 6992 break; 6993 case 2: 6994 /* Hex 2D */ 6995 if ((p >= vStart) && (p < vEnd)) { 6996 /* Old vertices stay the same */ 6997 ++numLeavesNew; 6998 } else if ((p >= fStart) && (p < fEnd)) { 6999 /* Old faces add new faces and vertex */ 7000 numLeavesNew += 1 + 2; 7001 } else if ((p >= cStart) && (p < cEnd)) { 7002 /* Old cells add new cells and interior faces */ 7003 numLeavesNew += 4 + 4; 7004 } 7005 break; 7006 default: 7007 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7008 } 7009 } 7010 /* Communicate depthSizes for each remote rank */ 7011 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 7012 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 7013 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 7014 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); 7015 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 7016 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 7017 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7018 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 7019 for (n = 0; n < numNeighbors; ++n) { 7020 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 7021 } 7022 depthSizeOld[depth] = cMax; 7023 depthSizeOld[0] = vMax; 7024 depthSizeOld[depth-1] = fMax; 7025 depthSizeOld[1] = eMax; 7026 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7027 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 7028 depthSizeOld[depth] = cEnd - cStart; 7029 depthSizeOld[0] = vEnd - vStart; 7030 depthSizeOld[depth-1] = fEnd - fStart; 7031 depthSizeOld[1] = eEnd - eStart; 7032 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7033 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 7034 for (n = 0; n < numNeighbors; ++n) { 7035 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 7036 } 7037 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 7038 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 7039 /* Calculate new point SF */ 7040 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 7041 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 7042 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 7043 for (l = 0, m = 0; l < numLeaves; ++l) { 7044 PetscInt p = localPoints[l]; 7045 PetscInt rp = remotePoints[l].index, n; 7046 PetscMPIInt rrank = remotePoints[l].rank; 7047 7048 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 7049 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 7050 switch (refiner) { 7051 case 1: 7052 /* Simplicial 2D */ 7053 if ((p >= vStart) && (p < vEnd)) { 7054 /* Old vertices stay the same */ 7055 localPointsNew[m] = vStartNew + (p - vStart); 7056 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7057 remotePointsNew[m].rank = rrank; 7058 ++m; 7059 } else if ((p >= fStart) && (p < fEnd)) { 7060 /* Old faces add new faces and vertex */ 7061 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7062 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7063 remotePointsNew[m].rank = rrank; 7064 ++m; 7065 for (r = 0; r < 2; ++r, ++m) { 7066 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7067 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7068 remotePointsNew[m].rank = rrank; 7069 } 7070 } else if ((p >= cStart) && (p < cEnd)) { 7071 /* Old cells add new cells and interior faces */ 7072 for (r = 0; r < 4; ++r, ++m) { 7073 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7074 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7075 remotePointsNew[m].rank = rrank; 7076 } 7077 for (r = 0; r < 3; ++r, ++m) { 7078 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7079 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 7080 remotePointsNew[m].rank = rrank; 7081 } 7082 } 7083 break; 7084 case 2: 7085 /* Hex 2D */ 7086 if ((p >= vStart) && (p < vEnd)) { 7087 /* Old vertices stay the same */ 7088 localPointsNew[m] = vStartNew + (p - vStart); 7089 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7090 remotePointsNew[m].rank = rrank; 7091 ++m; 7092 } else if ((p >= fStart) && (p < fEnd)) { 7093 /* Old faces add new faces and vertex */ 7094 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7095 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7096 remotePointsNew[m].rank = rrank; 7097 ++m; 7098 for (r = 0; r < 2; ++r, ++m) { 7099 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7100 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7101 remotePointsNew[m].rank = rrank; 7102 } 7103 } else if ((p >= cStart) && (p < cEnd)) { 7104 /* Old cells add new cells and interior faces */ 7105 for (r = 0; r < 4; ++r, ++m) { 7106 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7107 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7108 remotePointsNew[m].rank = rrank; 7109 } 7110 for (r = 0; r < 4; ++r, ++m) { 7111 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7112 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 7113 remotePointsNew[m].rank = rrank; 7114 } 7115 } 7116 break; 7117 case 3: 7118 /* Hybrid simplicial 2D */ 7119 if ((p >= vStart) && (p < vEnd)) { 7120 /* Old vertices stay the same */ 7121 localPointsNew[m] = vStartNew + (p - vStart); 7122 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 7123 remotePointsNew[m].rank = rrank; 7124 ++m; 7125 } else if ((p >= fStart) && (p < fMax)) { 7126 /* Old interior faces add new faces and vertex */ 7127 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 7128 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 7129 remotePointsNew[m].rank = rrank; 7130 ++m; 7131 for (r = 0; r < 2; ++r, ++m) { 7132 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 7133 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 7134 remotePointsNew[m].rank = rrank; 7135 } 7136 } else if ((p >= fMax) && (p < fEnd)) { 7137 /* Old hybrid faces stay the same */ 7138 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 7139 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 7140 remotePointsNew[m].rank = rrank; 7141 ++m; 7142 } else if ((p >= cStart) && (p < cMax)) { 7143 /* Old interior cells add new cells and interior faces */ 7144 for (r = 0; r < 4; ++r, ++m) { 7145 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7146 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7147 remotePointsNew[m].rank = rrank; 7148 } 7149 for (r = 0; r < 3; ++r, ++m) { 7150 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 7151 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 7152 remotePointsNew[m].rank = rrank; 7153 } 7154 } else if ((p >= cStart) && (p < cMax)) { 7155 /* Old hybrid cells add new cells and hybrid face */ 7156 for (r = 0; r < 2; ++r, ++m) { 7157 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 7158 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 7159 remotePointsNew[m].rank = rrank; 7160 } 7161 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7162 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]); 7163 remotePointsNew[m].rank = rrank; 7164 ++m; 7165 } 7166 break; 7167 default: 7168 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7169 } 7170 } 7171 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 7172 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 7173 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 7174 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 7175 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 7176 PetscFunctionReturn(0); 7177 } 7178 7179 #undef __FUNCT__ 7180 #define __FUNCT__ "CellRefinerCreateLabels" 7181 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 7182 { 7183 PetscInt numLabels, l; 7184 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 7185 PetscErrorCode ierr; 7186 7187 PetscFunctionBegin; 7188 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7189 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 7190 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7191 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 7192 cStartNew = 0; 7193 vStartNew = depthSize[2]; 7194 fStartNew = depthSize[2] + depthSize[0]; 7195 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 7196 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 7197 switch (refiner) { 7198 case 3: 7199 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 7200 cMax = PetscMin(cEnd, cMax); 7201 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 7202 fMax = PetscMin(fEnd, fMax); 7203 } 7204 for (l = 0; l < numLabels; ++l) { 7205 DMLabel label, labelNew; 7206 const char *lname; 7207 PetscBool isDepth; 7208 IS valueIS; 7209 const PetscInt *values; 7210 PetscInt numValues, val; 7211 7212 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 7213 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 7214 if (isDepth) continue; 7215 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 7216 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 7217 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 7218 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 7219 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 7220 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 7221 for (val = 0; val < numValues; ++val) { 7222 IS pointIS; 7223 const PetscInt *points; 7224 PetscInt numPoints, n; 7225 7226 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 7227 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 7228 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 7229 for (n = 0; n < numPoints; ++n) { 7230 const PetscInt p = points[n]; 7231 switch (refiner) { 7232 case 1: 7233 /* Simplicial 2D */ 7234 if ((p >= vStart) && (p < vEnd)) { 7235 /* Old vertices stay the same */ 7236 newp = vStartNew + (p - vStart); 7237 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7238 } else if ((p >= fStart) && (p < fEnd)) { 7239 /* Old faces add new faces and vertex */ 7240 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7241 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7242 for (r = 0; r < 2; ++r) { 7243 newp = fStartNew + (p - fStart)*2 + r; 7244 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7245 } 7246 } else if ((p >= cStart) && (p < cEnd)) { 7247 /* Old cells add new cells and interior faces */ 7248 for (r = 0; r < 4; ++r) { 7249 newp = cStartNew + (p - cStart)*4 + r; 7250 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7251 } 7252 for (r = 0; r < 3; ++r) { 7253 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 7254 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7255 } 7256 } 7257 break; 7258 case 2: 7259 /* Hex 2D */ 7260 if ((p >= vStart) && (p < vEnd)) { 7261 /* Old vertices stay the same */ 7262 newp = vStartNew + (p - vStart); 7263 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7264 } else if ((p >= fStart) && (p < fEnd)) { 7265 /* Old faces add new faces and vertex */ 7266 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7267 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7268 for (r = 0; r < 2; ++r) { 7269 newp = fStartNew + (p - fStart)*2 + r; 7270 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7271 } 7272 } else if ((p >= cStart) && (p < cEnd)) { 7273 /* Old cells add new cells and interior faces and vertex */ 7274 for (r = 0; r < 4; ++r) { 7275 newp = cStartNew + (p - cStart)*4 + r; 7276 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7277 } 7278 for (r = 0; r < 4; ++r) { 7279 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 7280 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7281 } 7282 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 7283 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7284 } 7285 break; 7286 case 3: 7287 /* Hybrid simplicial 2D */ 7288 if ((p >= vStart) && (p < vEnd)) { 7289 /* Old vertices stay the same */ 7290 newp = vStartNew + (p - vStart); 7291 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7292 } else if ((p >= fStart) && (p < fMax)) { 7293 /* Old interior faces add new faces and vertex */ 7294 newp = vStartNew + (vEnd - vStart) + (p - fStart); 7295 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7296 for (r = 0; r < 2; ++r) { 7297 newp = fStartNew + (p - fStart)*2 + r; 7298 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7299 } 7300 } else if ((p >= fMax) && (p < fEnd)) { 7301 /* Old hybrid faces stay the same */ 7302 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 7303 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7304 } else if ((p >= cStart) && (p < cMax)) { 7305 /* Old interior 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 } else if ((p >= cMax) && (p < cEnd)) { 7315 /* Old hybrid cells add new cells and hybrid face */ 7316 for (r = 0; r < 2; ++r) { 7317 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 7318 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7319 } 7320 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 7321 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 7322 } 7323 break; 7324 default: 7325 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 7326 } 7327 } 7328 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 7329 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 7330 } 7331 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 7332 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 7333 if (0) { 7334 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 7335 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7336 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 7337 } 7338 } 7339 PetscFunctionReturn(0); 7340 } 7341 7342 #undef __FUNCT__ 7343 #define __FUNCT__ "DMPlexRefine_Uniform" 7344 /* This will only work for interpolated meshes */ 7345 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 7346 { 7347 DM rdm; 7348 PetscInt *depthSize; 7349 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 7350 PetscErrorCode ierr; 7351 7352 PetscFunctionBegin; 7353 ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 7354 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 7355 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7356 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 7357 /* Calculate number of new points of each depth */ 7358 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7359 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 7360 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 7361 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 7362 /* Step 1: Set chart */ 7363 for (d = 0; d <= depth; ++d) { 7364 pEnd += depthSize[d]; 7365 } 7366 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 7367 /* Step 2: Set cone/support sizes */ 7368 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7369 /* Step 3: Setup refined DM */ 7370 ierr = DMSetUp(rdm);CHKERRQ(ierr); 7371 /* Step 4: Set cones and supports */ 7372 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7373 /* Step 5: Stratify */ 7374 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 7375 /* Step 6: Set coordinates for vertices */ 7376 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7377 /* Step 7: Create pointSF */ 7378 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7379 /* Step 8: Create labels */ 7380 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7381 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7382 7383 *dmRefined = rdm; 7384 #if 0 7385 DM_Plex *mesh = (DM_Plex *) dm->data; 7386 PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 7387 /* ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); */ 7388 7389 PetscFunctionBegin; 7390 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7391 /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 7392 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7393 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7394 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 7395 7396 /* Count number of new cells which are normal and extra */ 7397 PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 7398 PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 7399 for (c = cStart; c < cEnd2; ++c) { 7400 PetscInt n; 7401 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7402 newNumCellsNormal += n; 7403 } 7404 for (c = cEnd2; c < cEnd; ++c) { 7405 PetscInt n; 7406 ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); /* refiner.numNewCells */ 7407 newNumCellsExtra += n; 7408 } 7409 newNumCells = newNumCellsNormal + newNumCellsExtra; 7410 /* Count number of new vertices which are normal and extra */ 7411 PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 7412 PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 7413 for (c = cStart; c < cEnd; ++c) { 7414 PetscInt *closure = PETSC_NULL; 7415 PetscInt closureSize, numCorners = 0, p; 7416 7417 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7418 for (p = 0; p < closureSize*2; p += 2) { 7419 const PetscInt point = closure[p]; 7420 if ((point >= vStart) && (point < vEnd)) { 7421 closure[numCorners++] = point; 7422 } 7423 } 7424 ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCell */ 7425 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7426 } 7427 newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 7428 for (c = cEnd2; c < cEnd; ++c) { 7429 PetscInt *closure = PETSC_NULL; 7430 PetscInt closureSize, numCorners = 0, p; 7431 7432 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7433 for (p = 0; p < closureSize*2; p += 2) { 7434 const PetscInt point = closure[p]; 7435 if ((point >= vStart) && (point < vEnd)) { 7436 closure[numCorners++] = point; 7437 } 7438 } 7439 ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); /* refiner.splitCellUncensored */ 7440 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7441 } /* for */ 7442 newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 7443 newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 7444 7445 #if 1 7446 PetscInt oldNumCellsNormal = cEnd2 - cStart; 7447 PetscInt oldNumCellsExtra = cEnd - cEnd2; 7448 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 7449 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 7450 ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 7451 ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 7452 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 7453 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 7454 ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 7455 ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 7456 ierr = PetscSynchronizedFlush(comm); 7457 #endif 7458 7459 ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 7460 ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 7461 ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 7462 ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 7463 ierr = DMPlexGetHybridBounds(*dmRefined, newNumCellsNormal, PETSC_NULL, PETSC_NULL, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 7464 /* Set cone and support sizes for new normal cells */ 7465 PetscInt newCell = 0; 7466 for (c = cStart; c < cEnd2; ++c) { 7467 PetscInt coneSize, n, i; 7468 7469 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7470 ierr = CellRefinerGetNumSubcells(refiner, c, &n); /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7471 for (i = 0; i < n; ++i, ++newCell) { 7472 ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 7473 } 7474 7475 PetscInt *closure = PETSC_NULL; 7476 PetscInt closureSize, numCorners = 0, p; 7477 7478 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7479 for (p = 0; p < closureSize*2; p += 2) { 7480 const PetscInt point = closure[p]; 7481 if ((point >= vStart) && (point < vEnd)) { 7482 closure[numCorners++] = point; 7483 } 7484 } 7485 /* ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); */ /* refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); */ 7486 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7487 } 7488 7489 /* Reset current new cell value and loop over censored cells. */ 7490 curNewCell = _orderNewMesh->cellsCensored().min(); 7491 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7492 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7493 /* Set new cone and support sizes */ 7494 cV.clear(); 7495 sieve->cone(*c_iter, cV); 7496 const point_type* cone = cV.getPoints(); 7497 const int coneSize = cV.getSize(); 7498 7499 const point_type* newCells; 7500 int numNewCells = 0; 7501 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7502 7503 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7504 newSieve->setConeSize(curNewCell, coneSize); 7505 for (int iVertex=0; iVertex < coneSize; ++iVertex) { 7506 newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 7507 } /* for */ 7508 } /* for */ 7509 } /* for */ 7510 newSieve->allocate(); 7511 7512 ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 7513 7514 /* Create refined cells in new sieve. */ 7515 curNewCell = _orderNewMesh->cellsNormal().min(); 7516 oldCellsEnd = _orderOldMesh->cellsNormal().end(); 7517 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 7518 cV.clear(); 7519 sieve->cone(*c_iter, cV); 7520 const point_type *cone = cV.getPoints(); 7521 const int coneSize = cV.getSize(); 7522 7523 const point_type* newCells; 7524 int numNewCells = 0; 7525 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7526 7527 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7528 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7529 } /* for */ 7530 } /* for */ 7531 curNewCell = _orderNewMesh->cellsCensored().min(); 7532 oldCellsEnd = _orderOldMesh->cellsCensored().end(); 7533 for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 7534 cV.clear(); 7535 sieve->cone(*c_iter, cV); 7536 const point_type *cone = cV.getPoints(); 7537 const int coneSize = cV.getSize(); 7538 7539 const point_type* newCells; 7540 int numNewCells = 0; 7541 refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 7542 7543 for (int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 7544 newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 7545 } /* for */ 7546 } /* for */ 7547 newSieve->symmetrize(); 7548 7549 /* Set coordinates in refined mesh. */ 7550 const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 7551 assert(!coordinates.isNull()); 7552 const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 7553 assert(!newCoordinates.isNull()); 7554 7555 const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 7556 assert(vertices->size() > 0); 7557 const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 7558 assert(spaceDim > 0); 7559 newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 7560 7561 const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 7562 for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 7563 newCoordinates->setFiberDimension(*v_iter, spaceDim); 7564 } /* for */ 7565 newCoordinates->allocatePoint(); 7566 7567 interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 7568 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7569 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7570 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7571 } /* for */ 7572 oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 7573 for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 7574 /*std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; */ 7575 newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 7576 } /* for */ 7577 7578 refiner.setCoordsNewVertices(newCoordinates, coordinates); 7579 7580 /* Create sensored depth */ 7581 const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 7582 assert(!censoredLabel.isNull()); 7583 7584 mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 7585 7586 newSieve->roots(depthVisitor); 7587 while (depthVisitor.isModified()) { 7588 /* FIX: Avoid the copy here somehow by fixing the traversal */ 7589 std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 7590 7591 depthVisitor.clear(); 7592 newSieve->support(modifiedPoints, depthVisitor); 7593 } /* while */ 7594 /* Stratify refined mesh */ 7595 /* Calculate new point SF */ 7596 _calcNewOverlap(newMesh, mesh, refiner); 7597 /* Calculate new labels */ 7598 _createLabels(newMesh, mesh, refiner); 7599 #endif 7600 PetscFunctionReturn(0); 7601 } 7602 7603 #undef __FUNCT__ 7604 #define __FUNCT__ "DMPlexSetRefinementUniform" 7605 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7606 { 7607 DM_Plex *mesh = (DM_Plex *) dm->data; 7608 7609 PetscFunctionBegin; 7610 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7611 mesh->refinementUniform = refinementUniform; 7612 PetscFunctionReturn(0); 7613 } 7614 7615 #undef __FUNCT__ 7616 #define __FUNCT__ "DMPlexGetRefinementUniform" 7617 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7618 { 7619 DM_Plex *mesh = (DM_Plex *) dm->data; 7620 7621 PetscFunctionBegin; 7622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7623 PetscValidPointer(refinementUniform, 2); 7624 *refinementUniform = mesh->refinementUniform; 7625 PetscFunctionReturn(0); 7626 } 7627 7628 #undef __FUNCT__ 7629 #define __FUNCT__ "DMPlexSetRefinementLimit" 7630 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7631 { 7632 DM_Plex *mesh = (DM_Plex *) dm->data; 7633 7634 PetscFunctionBegin; 7635 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7636 mesh->refinementLimit = refinementLimit; 7637 PetscFunctionReturn(0); 7638 } 7639 7640 #undef __FUNCT__ 7641 #define __FUNCT__ "DMPlexGetRefinementLimit" 7642 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7643 { 7644 DM_Plex *mesh = (DM_Plex *) dm->data; 7645 7646 PetscFunctionBegin; 7647 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7648 PetscValidPointer(refinementLimit, 2); 7649 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7650 *refinementLimit = mesh->refinementLimit; 7651 PetscFunctionReturn(0); 7652 } 7653 7654 #undef __FUNCT__ 7655 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7656 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7657 { 7658 PetscInt dim, cStart, coneSize, cMax; 7659 PetscErrorCode ierr; 7660 7661 PetscFunctionBegin; 7662 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7663 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 7664 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7665 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 7666 switch (dim) { 7667 case 2: 7668 switch (coneSize) { 7669 case 3: 7670 if (cMax >= 0) { 7671 *cellRefiner = 3; /* Hybrid */ 7672 } else { 7673 *cellRefiner = 1; /* Triangular */ 7674 } 7675 break; 7676 case 4: 7677 if (cMax >= 0) { 7678 *cellRefiner = 4; /* Hybrid */ 7679 } else { 7680 *cellRefiner = 2; /* Quadrilateral */ 7681 } 7682 break; 7683 default: 7684 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7685 } 7686 break; 7687 default: 7688 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7689 } 7690 PetscFunctionReturn(0); 7691 } 7692 7693 #undef __FUNCT__ 7694 #define __FUNCT__ "DMRefine_Plex" 7695 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7696 { 7697 PetscReal refinementLimit; 7698 PetscInt dim, cStart, cEnd; 7699 char genname[1024], *name = PETSC_NULL; 7700 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7701 PetscErrorCode ierr; 7702 7703 PetscFunctionBegin; 7704 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7705 if (isUniform) { 7706 CellRefiner cellRefiner; 7707 7708 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7709 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7710 PetscFunctionReturn(0); 7711 } 7712 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7713 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7714 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7715 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7716 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7717 if (flg) {name = genname;} 7718 if (name) { 7719 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7720 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7721 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7722 } 7723 switch (dim) { 7724 case 2: 7725 if (!name || isTriangle) { 7726 #if defined(PETSC_HAVE_TRIANGLE) 7727 double *maxVolumes; 7728 PetscInt c; 7729 7730 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7731 for (c = 0; c < cEnd-cStart; ++c) { 7732 maxVolumes[c] = refinementLimit; 7733 } 7734 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7735 #else 7736 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7737 #endif 7738 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7739 break; 7740 case 3: 7741 if (!name || isCTetgen) { 7742 #if defined(PETSC_HAVE_CTETGEN) 7743 PetscReal *maxVolumes; 7744 PetscInt c; 7745 7746 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7747 for (c = 0; c < cEnd-cStart; ++c) { 7748 maxVolumes[c] = refinementLimit; 7749 } 7750 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7751 #else 7752 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7753 #endif 7754 } else if (isTetgen) { 7755 #if defined(PETSC_HAVE_TETGEN) 7756 double *maxVolumes; 7757 PetscInt c; 7758 7759 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7760 for (c = 0; c < cEnd-cStart; ++c) { 7761 maxVolumes[c] = refinementLimit; 7762 } 7763 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7764 #else 7765 SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7766 #endif 7767 } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7768 break; 7769 default: 7770 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7771 } 7772 PetscFunctionReturn(0); 7773 } 7774 7775 #undef __FUNCT__ 7776 #define __FUNCT__ "DMPlexGetDepth" 7777 /*@ 7778 DMPlexGetDepth - get the number of strata 7779 7780 Not Collective 7781 7782 Input Parameters: 7783 . dm - The DMPlex object 7784 7785 Output Parameters: 7786 . depth - number of strata 7787 7788 Level: developer 7789 7790 Notes: 7791 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7792 7793 .keywords: mesh, points 7794 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7795 @*/ 7796 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7797 { 7798 PetscInt d; 7799 PetscErrorCode ierr; 7800 7801 PetscFunctionBegin; 7802 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7803 PetscValidPointer(depth, 2); 7804 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7805 *depth = d-1; 7806 PetscFunctionReturn(0); 7807 } 7808 7809 #undef __FUNCT__ 7810 #define __FUNCT__ "DMPlexGetDepthStratum" 7811 /*@ 7812 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7813 7814 Not Collective 7815 7816 Input Parameters: 7817 + dm - The DMPlex object 7818 - stratumValue - The requested depth 7819 7820 Output Parameters: 7821 + start - The first point at this depth 7822 - end - One beyond the last point at this depth 7823 7824 Level: developer 7825 7826 .keywords: mesh, points 7827 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7828 @*/ 7829 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7830 { 7831 DM_Plex *mesh = (DM_Plex *) dm->data; 7832 DMLabel next = mesh->labels; 7833 PetscBool flg = PETSC_FALSE; 7834 PetscInt depth; 7835 PetscErrorCode ierr; 7836 7837 PetscFunctionBegin; 7838 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7839 if (stratumValue < 0) { 7840 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7841 PetscFunctionReturn(0); 7842 } else { 7843 PetscInt pStart, pEnd; 7844 7845 if (start) {*start = 0;} 7846 if (end) {*end = 0;} 7847 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7848 if (pStart == pEnd) {PetscFunctionReturn(0);} 7849 } 7850 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7851 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7852 /* We should have a generic GetLabel() and a Label class */ 7853 while (next) { 7854 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7855 if (flg) break; 7856 next = next->next; 7857 } 7858 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7859 depth = stratumValue; 7860 if ((depth < 0) || (depth >= next->numStrata)) { 7861 if (start) {*start = 0;} 7862 if (end) {*end = 0;} 7863 } else { 7864 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7865 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7866 } 7867 PetscFunctionReturn(0); 7868 } 7869 7870 #undef __FUNCT__ 7871 #define __FUNCT__ "DMPlexGetHeightStratum" 7872 /*@ 7873 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7874 7875 Not Collective 7876 7877 Input Parameters: 7878 + dm - The DMPlex object 7879 - stratumValue - The requested height 7880 7881 Output Parameters: 7882 + start - The first point at this height 7883 - end - One beyond the last point at this height 7884 7885 Level: developer 7886 7887 .keywords: mesh, points 7888 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7889 @*/ 7890 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7891 { 7892 DM_Plex *mesh = (DM_Plex *) dm->data; 7893 DMLabel next = mesh->labels; 7894 PetscBool flg = PETSC_FALSE; 7895 PetscInt depth; 7896 PetscErrorCode ierr; 7897 7898 PetscFunctionBegin; 7899 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7900 if (stratumValue < 0) { 7901 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7902 } else { 7903 PetscInt pStart, pEnd; 7904 7905 if (start) {*start = 0;} 7906 if (end) {*end = 0;} 7907 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7908 if (pStart == pEnd) {PetscFunctionReturn(0);} 7909 } 7910 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7911 if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7912 /* We should have a generic GetLabel() and a Label class */ 7913 while (next) { 7914 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7915 if (flg) break; 7916 next = next->next; 7917 } 7918 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7919 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7920 if ((depth < 0) || (depth >= next->numStrata)) { 7921 if (start) {*start = 0;} 7922 if (end) {*end = 0;} 7923 } else { 7924 if (start) {*start = next->points[next->stratumOffsets[depth]];} 7925 if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 7926 } 7927 PetscFunctionReturn(0); 7928 } 7929 7930 #undef __FUNCT__ 7931 #define __FUNCT__ "DMPlexCreateSectionInitial" 7932 /* Set the number of dof on each point and separate by fields */ 7933 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7934 { 7935 PetscInt *numDofTot; 7936 PetscInt pStart = 0, pEnd = 0; 7937 PetscInt p, d, f; 7938 PetscErrorCode ierr; 7939 7940 PetscFunctionBegin; 7941 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7942 for (d = 0; d <= dim; ++d) { 7943 numDofTot[d] = 0; 7944 for (f = 0; f < numFields; ++f) { 7945 numDofTot[d] += numDof[f*(dim+1)+d]; 7946 } 7947 } 7948 ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 7949 if (numFields > 0) { 7950 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7951 if (numComp) { 7952 for (f = 0; f < numFields; ++f) { 7953 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7954 } 7955 } 7956 } 7957 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7958 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7959 for (d = 0; d <= dim; ++d) { 7960 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7961 for (p = pStart; p < pEnd; ++p) { 7962 for (f = 0; f < numFields; ++f) { 7963 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7964 } 7965 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7966 } 7967 } 7968 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7969 PetscFunctionReturn(0); 7970 } 7971 7972 #undef __FUNCT__ 7973 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7974 /* Set the number of dof on each point and separate by fields 7975 If constDof is PETSC_DETERMINE, constrain every dof on the point 7976 */ 7977 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7978 { 7979 PetscInt numFields; 7980 PetscInt bc; 7981 PetscErrorCode ierr; 7982 7983 PetscFunctionBegin; 7984 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7985 for (bc = 0; bc < numBC; ++bc) { 7986 PetscInt field = 0; 7987 const PetscInt *idx; 7988 PetscInt n, i; 7989 7990 if (numFields) {field = bcField[bc];} 7991 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7992 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7993 for (i = 0; i < n; ++i) { 7994 const PetscInt p = idx[i]; 7995 PetscInt numConst = constDof; 7996 7997 /* Constrain every dof on the point */ 7998 if (numConst < 0) { 7999 if (numFields) { 8000 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 8001 } else { 8002 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 8003 } 8004 } 8005 if (numFields) { 8006 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 8007 } 8008 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 8009 } 8010 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 8011 } 8012 PetscFunctionReturn(0); 8013 } 8014 8015 #undef __FUNCT__ 8016 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 8017 /* Set the constrained indices on each point and separate by fields */ 8018 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 8019 { 8020 PetscInt *maxConstraints; 8021 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 8022 PetscErrorCode ierr; 8023 8024 PetscFunctionBegin; 8025 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8026 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8027 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 8028 for (f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 8029 for (p = pStart; p < pEnd; ++p) { 8030 PetscInt cdof; 8031 8032 if (numFields) { 8033 for (f = 0; f < numFields; ++f) { 8034 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 8035 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 8036 } 8037 } else { 8038 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8039 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 8040 } 8041 } 8042 for (f = 0; f < numFields; ++f) { 8043 maxConstraints[numFields] += maxConstraints[f]; 8044 } 8045 if (maxConstraints[numFields]) { 8046 PetscInt *indices; 8047 8048 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8049 for (p = pStart; p < pEnd; ++p) { 8050 PetscInt cdof, d; 8051 8052 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8053 if (cdof) { 8054 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 8055 if (numFields) { 8056 PetscInt numConst = 0, foff = 0; 8057 8058 for (f = 0; f < numFields; ++f) { 8059 PetscInt cfdof, fdof; 8060 8061 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8062 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 8063 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 8064 for (d = 0; d < cfdof; ++d) { 8065 indices[numConst+d] = d; 8066 } 8067 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 8068 for (d = 0; d < cfdof; ++d) { 8069 indices[numConst+d] += foff; 8070 } 8071 numConst += cfdof; 8072 foff += fdof; 8073 } 8074 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8075 } else { 8076 for (d = 0; d < cdof; ++d) { 8077 indices[d] = d; 8078 } 8079 } 8080 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8081 } 8082 } 8083 ierr = PetscFree(indices);CHKERRQ(ierr); 8084 } 8085 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 8086 PetscFunctionReturn(0); 8087 } 8088 8089 #undef __FUNCT__ 8090 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 8091 /* Set the constrained field indices on each point */ 8092 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 8093 { 8094 const PetscInt *points, *indices; 8095 PetscInt numFields, maxDof, numPoints, p, numConstraints; 8096 PetscErrorCode ierr; 8097 8098 PetscFunctionBegin; 8099 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8100 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 8101 8102 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 8103 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 8104 if (!constraintIndices) { 8105 PetscInt *idx, i; 8106 8107 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8108 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 8109 for (i = 0; i < maxDof; ++i) {idx[i] = i;} 8110 for (p = 0; p < numPoints; ++p) { 8111 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 8112 } 8113 ierr = PetscFree(idx);CHKERRQ(ierr); 8114 } else { 8115 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 8116 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 8117 for (p = 0; p < numPoints; ++p) { 8118 PetscInt fcdof; 8119 8120 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 8121 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); 8122 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 8123 } 8124 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 8125 } 8126 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 8127 PetscFunctionReturn(0); 8128 } 8129 8130 #undef __FUNCT__ 8131 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 8132 /* Set the constrained indices on each point and separate by fields */ 8133 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 8134 { 8135 PetscInt *indices; 8136 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 8137 PetscErrorCode ierr; 8138 8139 PetscFunctionBegin; 8140 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 8141 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 8142 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8143 if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 8144 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8145 for (p = pStart; p < pEnd; ++p) { 8146 PetscInt cdof, d; 8147 8148 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 8149 if (cdof) { 8150 PetscInt numConst = 0, foff = 0; 8151 8152 for (f = 0; f < numFields; ++f) { 8153 const PetscInt *fcind; 8154 PetscInt fdof, fcdof; 8155 8156 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8157 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8158 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 8159 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 8160 for (d = 0; d < fcdof; ++d) { 8161 indices[numConst+d] = fcind[d]+foff; 8162 } 8163 foff += fdof; 8164 numConst += fcdof; 8165 } 8166 if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 8167 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 8168 } 8169 } 8170 ierr = PetscFree(indices);CHKERRQ(ierr); 8171 PetscFunctionReturn(0); 8172 } 8173 8174 #undef __FUNCT__ 8175 #define __FUNCT__ "DMPlexCreateSection" 8176 /*@C 8177 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 8178 8179 Not Collective 8180 8181 Input Parameters: 8182 + dm - The DMPlex object 8183 . dim - The spatial dimension of the problem 8184 . numFields - The number of fields in the problem 8185 . numComp - An array of size numFields that holds the number of components for each field 8186 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 8187 . numBC - The number of boundary conditions 8188 . bcField - An array of size numBC giving the field number for each boundry condition 8189 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 8190 8191 Output Parameter: 8192 . section - The PetscSection object 8193 8194 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 8195 nubmer of dof for field 0 on each edge. 8196 8197 Level: developer 8198 8199 .keywords: mesh, elements 8200 .seealso: DMPlexCreate(), PetscSectionCreate() 8201 @*/ 8202 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 8203 { 8204 PetscErrorCode ierr; 8205 8206 PetscFunctionBegin; 8207 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 8208 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 8209 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 8210 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 8211 { 8212 PetscBool view = PETSC_FALSE; 8213 8214 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 8215 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 8216 } 8217 PetscFunctionReturn(0); 8218 } 8219 8220 #undef __FUNCT__ 8221 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 8222 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 8223 { 8224 PetscSection section; 8225 PetscErrorCode ierr; 8226 8227 PetscFunctionBegin; 8228 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 8229 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 8230 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 8231 PetscFunctionReturn(0); 8232 } 8233 8234 #undef __FUNCT__ 8235 #define __FUNCT__ "DMPlexGetCoordinateSection" 8236 /*@ 8237 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 8238 8239 Not Collective 8240 8241 Input Parameter: 8242 . dm - The DMPlex object 8243 8244 Output Parameter: 8245 . section - The PetscSection object 8246 8247 Level: intermediate 8248 8249 .keywords: mesh, coordinates 8250 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8251 @*/ 8252 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 8253 { 8254 DM cdm; 8255 PetscErrorCode ierr; 8256 8257 PetscFunctionBegin; 8258 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8259 PetscValidPointer(section, 2); 8260 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8261 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 8262 PetscFunctionReturn(0); 8263 } 8264 8265 #undef __FUNCT__ 8266 #define __FUNCT__ "DMPlexSetCoordinateSection" 8267 /*@ 8268 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 8269 8270 Not Collective 8271 8272 Input Parameters: 8273 + dm - The DMPlex object 8274 - section - The PetscSection object 8275 8276 Level: intermediate 8277 8278 .keywords: mesh, coordinates 8279 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 8280 @*/ 8281 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 8282 { 8283 DM cdm; 8284 PetscErrorCode ierr; 8285 8286 PetscFunctionBegin; 8287 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8288 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 8289 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 8290 PetscFunctionReturn(0); 8291 } 8292 8293 #undef __FUNCT__ 8294 #define __FUNCT__ "DMPlexGetConeSection" 8295 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 8296 { 8297 DM_Plex *mesh = (DM_Plex *) dm->data; 8298 8299 PetscFunctionBegin; 8300 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8301 if (section) *section = mesh->coneSection; 8302 PetscFunctionReturn(0); 8303 } 8304 8305 #undef __FUNCT__ 8306 #define __FUNCT__ "DMPlexGetCones" 8307 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 8308 { 8309 DM_Plex *mesh = (DM_Plex *) dm->data; 8310 8311 PetscFunctionBegin; 8312 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8313 if (cones) *cones = mesh->cones; 8314 PetscFunctionReturn(0); 8315 } 8316 8317 #undef __FUNCT__ 8318 #define __FUNCT__ "DMPlexGetConeOrientations" 8319 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 8320 { 8321 DM_Plex *mesh = (DM_Plex *) dm->data; 8322 8323 PetscFunctionBegin; 8324 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8325 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 8326 PetscFunctionReturn(0); 8327 } 8328 8329 #undef __FUNCT__ 8330 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 8331 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8332 { 8333 const PetscInt embedDim = 2; 8334 PetscReal x = PetscRealPart(point[0]); 8335 PetscReal y = PetscRealPart(point[1]); 8336 PetscReal v0[2], J[4], invJ[4], detJ; 8337 PetscReal xi, eta; 8338 PetscErrorCode ierr; 8339 8340 PetscFunctionBegin; 8341 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8342 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 8343 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 8344 8345 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 8346 *cell = c; 8347 } else { 8348 *cell = -1; 8349 } 8350 PetscFunctionReturn(0); 8351 } 8352 8353 #undef __FUNCT__ 8354 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 8355 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8356 { 8357 PetscSection coordSection; 8358 Vec coordsLocal; 8359 const PetscScalar *coords; 8360 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 8361 PetscReal x = PetscRealPart(point[0]); 8362 PetscReal y = PetscRealPart(point[1]); 8363 PetscInt crossings = 0, f; 8364 PetscErrorCode ierr; 8365 8366 PetscFunctionBegin; 8367 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8368 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8369 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8370 for (f = 0; f < 4; ++f) { 8371 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 8372 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 8373 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 8374 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 8375 PetscReal slope = (y_j - y_i) / (x_j - x_i); 8376 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 8377 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 8378 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 8379 if ((cond1 || cond2) && above) ++crossings; 8380 } 8381 if (crossings % 2) { 8382 *cell = c; 8383 } else { 8384 *cell = -1; 8385 } 8386 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8387 PetscFunctionReturn(0); 8388 } 8389 8390 #undef __FUNCT__ 8391 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 8392 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8393 { 8394 const PetscInt embedDim = 3; 8395 PetscReal v0[3], J[9], invJ[9], detJ; 8396 PetscReal x = PetscRealPart(point[0]); 8397 PetscReal y = PetscRealPart(point[1]); 8398 PetscReal z = PetscRealPart(point[2]); 8399 PetscReal xi, eta, zeta; 8400 PetscErrorCode ierr; 8401 8402 PetscFunctionBegin; 8403 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 8404 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 8405 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 8406 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 8407 8408 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 8409 *cell = c; 8410 } else { 8411 *cell = -1; 8412 } 8413 PetscFunctionReturn(0); 8414 } 8415 8416 #undef __FUNCT__ 8417 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 8418 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 8419 { 8420 PetscSection coordSection; 8421 Vec coordsLocal; 8422 const PetscScalar *coords; 8423 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 8424 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 8425 PetscBool found = PETSC_TRUE; 8426 PetscInt f; 8427 PetscErrorCode ierr; 8428 8429 PetscFunctionBegin; 8430 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 8431 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8432 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8433 for (f = 0; f < 6; ++f) { 8434 /* Check the point is under plane */ 8435 /* Get face normal */ 8436 PetscReal v_i[3] = {PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]), 8437 PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]), 8438 PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2])}; 8439 PetscReal v_j[3] = {PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]), 8440 PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]), 8441 PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2])}; 8442 PetscReal normal[3] = {v_i[1]*v_j[2] - v_i[2]*v_j[1], v_i[2]*v_j[0] - v_i[0]*v_j[2], v_i[0]*v_j[1] - v_i[1]*v_j[0]}; 8443 PetscReal pp[3] = {PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]), 8444 PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]), 8445 PetscRealPart(coords[faces[f*4+0]*3+2] - point[2])}; 8446 PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 8447 /* Check that projected point is in face (2D location problem) */ 8448 if (dot < 0.0) { 8449 found = PETSC_FALSE; 8450 break; 8451 } 8452 } 8453 if (found) { 8454 *cell = c; 8455 } else { 8456 *cell = -1; 8457 } 8458 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 8459 PetscFunctionReturn(0); 8460 } 8461 8462 #undef __FUNCT__ 8463 #define __FUNCT__ "DMLocatePoints_Plex" 8464 /* 8465 Need to implement using the guess 8466 */ 8467 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 8468 { 8469 PetscInt cell = -1/*, guess = -1*/; 8470 PetscInt bs, numPoints, p; 8471 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 8472 PetscInt *cells; 8473 PetscScalar *a; 8474 PetscErrorCode ierr; 8475 8476 PetscFunctionBegin; 8477 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8478 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8479 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 8480 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 8481 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 8482 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 8483 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 8484 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); 8485 numPoints /= bs; 8486 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 8487 for (p = 0; p < numPoints; ++p) { 8488 const PetscScalar *point = &a[p*bs]; 8489 8490 switch (dim) { 8491 case 2: 8492 for (c = cStart; c < cEnd; ++c) { 8493 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8494 switch (coneSize) { 8495 case 3: 8496 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 8497 break; 8498 case 4: 8499 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 8500 break; 8501 default: 8502 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8503 } 8504 if (cell >= 0) break; 8505 } 8506 break; 8507 case 3: 8508 for (c = cStart; c < cEnd; ++c) { 8509 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 8510 switch (coneSize) { 8511 case 4: 8512 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 8513 break; 8514 case 8: 8515 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 8516 break; 8517 default: 8518 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 8519 } 8520 if (cell >= 0) break; 8521 } 8522 break; 8523 default: 8524 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 8525 } 8526 cells[p] = cell; 8527 } 8528 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 8529 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 8530 PetscFunctionReturn(0); 8531 } 8532 8533 /******************************** FEM Support **********************************/ 8534 8535 #undef __FUNCT__ 8536 #define __FUNCT__ "DMPlexVecGetClosure" 8537 /*@C 8538 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 8539 8540 Not collective 8541 8542 Input Parameters: 8543 + dm - The DM 8544 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8545 . v - The local vector 8546 - point - The sieve point in the DM 8547 8548 Output Parameters: 8549 + csize - The number of values in the closure, or PETSC_NULL 8550 - values - The array of values, which is a borrowed array and should not be freed 8551 8552 Level: intermediate 8553 8554 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8555 @*/ 8556 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8557 { 8558 PetscScalar *array, *vArray; 8559 PetscInt *points = PETSC_NULL; 8560 PetscInt offsets[32]; 8561 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 8562 PetscErrorCode ierr; 8563 8564 PetscFunctionBegin; 8565 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8566 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8567 if (!section) { 8568 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8569 } 8570 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8571 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8572 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8573 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8574 /* Compress out points not in the section */ 8575 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8576 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8577 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8578 points[q*2] = points[p]; 8579 points[q*2+1] = points[p+1]; 8580 ++q; 8581 } 8582 } 8583 numPoints = q; 8584 for (p = 0, size = 0; p < numPoints*2; p += 2) { 8585 PetscInt dof, fdof; 8586 8587 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8588 for (f = 0; f < numFields; ++f) { 8589 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8590 offsets[f+1] += fdof; 8591 } 8592 size += dof; 8593 } 8594 for (f = 1; f < numFields; ++f) { 8595 offsets[f+1] += offsets[f]; 8596 } 8597 if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 8598 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 8599 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 8600 for (p = 0; p < numPoints*2; p += 2) { 8601 PetscInt o = points[p+1]; 8602 PetscInt dof, off, d; 8603 PetscScalar *varr; 8604 8605 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8606 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 8607 varr = &vArray[off]; 8608 if (numFields) { 8609 PetscInt fdof, foff, fcomp, f, c; 8610 8611 for (f = 0, foff = 0; f < numFields; ++f) { 8612 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8613 if (o >= 0) { 8614 for (d = 0; d < fdof; ++d, ++offsets[f]) { 8615 array[offsets[f]] = varr[foff+d]; 8616 } 8617 } else { 8618 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8619 for (d = fdof/fcomp-1; d >= 0; --d) { 8620 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8621 array[offsets[f]] = varr[foff+d*fcomp+c]; 8622 } 8623 } 8624 } 8625 foff += fdof; 8626 } 8627 } else { 8628 if (o >= 0) { 8629 for (d = 0; d < dof; ++d, ++offsets[0]) { 8630 array[offsets[0]] = varr[d]; 8631 } 8632 } else { 8633 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8634 array[offsets[0]] = varr[d]; 8635 } 8636 } 8637 } 8638 } 8639 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8640 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8641 if (csize) *csize = size; 8642 *values = array; 8643 PetscFunctionReturn(0); 8644 } 8645 8646 #undef __FUNCT__ 8647 #define __FUNCT__ "DMPlexVecRestoreClosure" 8648 /*@C 8649 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8650 8651 Not collective 8652 8653 Input Parameters: 8654 + dm - The DM 8655 . section - The section describing the layout in v, or PETSC_NULL to use the default section 8656 . v - The local vector 8657 . point - The sieve point in the DM 8658 . csize - The number of values in the closure, or PETSC_NULL 8659 - values - The array of values, which is a borrowed array and should not be freed 8660 8661 Level: intermediate 8662 8663 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8664 @*/ 8665 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8666 { 8667 PetscInt size = 0; 8668 PetscErrorCode ierr; 8669 8670 PetscFunctionBegin; 8671 /* Should work without recalculating size */ 8672 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 8673 PetscFunctionReturn(0); 8674 } 8675 8676 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8677 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8678 8679 #undef __FUNCT__ 8680 #define __FUNCT__ "updatePoint_private" 8681 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8682 { 8683 PetscInt cdof; /* The number of constraints on this point */ 8684 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8685 PetscScalar *a; 8686 PetscInt off, cind = 0, k; 8687 PetscErrorCode ierr; 8688 8689 PetscFunctionBegin; 8690 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8691 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8692 a = &array[off]; 8693 if (!cdof || setBC) { 8694 if (orientation >= 0) { 8695 for (k = 0; k < dof; ++k) { 8696 fuse(&a[k], values[k]); 8697 } 8698 } else { 8699 for (k = 0; k < dof; ++k) { 8700 fuse(&a[k], values[dof-k-1]); 8701 } 8702 } 8703 } else { 8704 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8705 if (orientation >= 0) { 8706 for (k = 0; k < dof; ++k) { 8707 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8708 fuse(&a[k], values[k]); 8709 } 8710 } else { 8711 for (k = 0; k < dof; ++k) { 8712 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8713 fuse(&a[k], values[dof-k-1]); 8714 } 8715 } 8716 } 8717 PetscFunctionReturn(0); 8718 } 8719 8720 #undef __FUNCT__ 8721 #define __FUNCT__ "updatePointFields_private" 8722 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8723 { 8724 PetscScalar *a; 8725 PetscInt numFields, off, foff, f; 8726 PetscErrorCode ierr; 8727 8728 PetscFunctionBegin; 8729 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8730 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8731 a = &array[off]; 8732 for (f = 0, foff = 0; f < numFields; ++f) { 8733 PetscInt fdof, fcomp, fcdof; 8734 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8735 PetscInt cind = 0, k, c; 8736 8737 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8738 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8739 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8740 if (!fcdof || setBC) { 8741 if (orientation >= 0) { 8742 for (k = 0; k < fdof; ++k) { 8743 fuse(&a[foff+k], values[foffs[f]+k]); 8744 } 8745 } else { 8746 for (k = fdof/fcomp-1; k >= 0; --k) { 8747 for (c = 0; c < fcomp; ++c) { 8748 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8749 } 8750 } 8751 } 8752 } else { 8753 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8754 if (orientation >= 0) { 8755 for (k = 0; k < fdof; ++k) { 8756 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8757 fuse(&a[foff+k], values[foffs[f]+k]); 8758 } 8759 } else { 8760 for (k = fdof/fcomp-1; k >= 0; --k) { 8761 for (c = 0; c < fcomp; ++c) { 8762 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8763 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8764 } 8765 } 8766 } 8767 } 8768 foff += fdof; 8769 foffs[f] += fdof; 8770 } 8771 PetscFunctionReturn(0); 8772 } 8773 8774 #undef __FUNCT__ 8775 #define __FUNCT__ "DMPlexVecSetClosure" 8776 /*@C 8777 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8778 8779 Not collective 8780 8781 Input Parameters: 8782 + dm - The DM 8783 . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 8784 . v - The local vector 8785 . point - The sieve point in the DM 8786 . values - The array of values, which is a borrowed array and should not be freed 8787 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8788 8789 Level: intermediate 8790 8791 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8792 @*/ 8793 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8794 { 8795 PetscScalar *array; 8796 PetscInt *points = PETSC_NULL; 8797 PetscInt offsets[32]; 8798 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8799 PetscErrorCode ierr; 8800 8801 PetscFunctionBegin; 8802 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8803 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8804 if (!section) { 8805 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8806 } 8807 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8808 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8809 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8810 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8811 /* Compress out points not in the section */ 8812 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8813 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8814 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8815 points[q*2] = points[p]; 8816 points[q*2+1] = points[p+1]; 8817 ++q; 8818 } 8819 } 8820 numPoints = q; 8821 for (p = 0; p < numPoints*2; p += 2) { 8822 PetscInt fdof; 8823 8824 for (f = 0; f < numFields; ++f) { 8825 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8826 offsets[f+1] += fdof; 8827 } 8828 } 8829 for (f = 1; f < numFields; ++f) { 8830 offsets[f+1] += offsets[f]; 8831 } 8832 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8833 if (numFields) { 8834 switch (mode) { 8835 case INSERT_VALUES: 8836 for (p = 0; p < numPoints*2; p += 2) { 8837 PetscInt o = points[p+1]; 8838 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8839 } break; 8840 case INSERT_ALL_VALUES: 8841 for (p = 0; p < numPoints*2; p += 2) { 8842 PetscInt o = points[p+1]; 8843 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8844 } break; 8845 case ADD_VALUES: 8846 for (p = 0; p < numPoints*2; p += 2) { 8847 PetscInt o = points[p+1]; 8848 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8849 } break; 8850 case ADD_ALL_VALUES: 8851 for (p = 0; p < numPoints*2; p += 2) { 8852 PetscInt o = points[p+1]; 8853 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8854 } break; 8855 default: 8856 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8857 } 8858 } else { 8859 switch (mode) { 8860 case INSERT_VALUES: 8861 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8862 PetscInt o = points[p+1]; 8863 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8864 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8865 } break; 8866 case INSERT_ALL_VALUES: 8867 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8868 PetscInt o = points[p+1]; 8869 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8870 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8871 } break; 8872 case ADD_VALUES: 8873 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8874 PetscInt o = points[p+1]; 8875 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8876 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8877 } break; 8878 case ADD_ALL_VALUES: 8879 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8880 PetscInt o = points[p+1]; 8881 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8882 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8883 } break; 8884 default: 8885 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8886 } 8887 } 8888 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8889 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8890 PetscFunctionReturn(0); 8891 } 8892 8893 #undef __FUNCT__ 8894 #define __FUNCT__ "DMPlexPrintMatSetValues" 8895 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8896 { 8897 PetscMPIInt rank; 8898 PetscInt i, j; 8899 PetscErrorCode ierr; 8900 8901 PetscFunctionBegin; 8902 ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 8903 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8904 for (i = 0; i < numIndices; i++) { 8905 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8906 } 8907 for (i = 0; i < numIndices; i++) { 8908 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8909 for (j = 0; j < numIndices; j++) { 8910 #if defined(PETSC_USE_COMPLEX) 8911 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8912 #else 8913 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8914 #endif 8915 } 8916 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8917 } 8918 PetscFunctionReturn(0); 8919 } 8920 8921 #undef __FUNCT__ 8922 #define __FUNCT__ "indicesPoint_private" 8923 /* . off - The global offset of this point */ 8924 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8925 { 8926 PetscInt cdof; /* The number of constraints on this point */ 8927 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8928 PetscInt cind = 0, k; 8929 PetscErrorCode ierr; 8930 8931 PetscFunctionBegin; 8932 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8933 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8934 if (!cdof || setBC) { 8935 if (orientation >= 0) { 8936 for (k = 0; k < dof; ++k) { 8937 indices[k] = off+k; 8938 } 8939 } else { 8940 for (k = 0; k < dof; ++k) { 8941 indices[dof-k-1] = off+k; 8942 } 8943 } 8944 } else { 8945 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8946 if (orientation >= 0) { 8947 for (k = 0; k < dof; ++k) { 8948 if ((cind < cdof) && (k == cdofs[cind])) { 8949 /* Insert check for returning constrained indices */ 8950 indices[k] = -(off+k+1); 8951 ++cind; 8952 } else { 8953 indices[k] = off+k-cind; 8954 } 8955 } 8956 } else { 8957 for (k = 0; k < dof; ++k) { 8958 if ((cind < cdof) && (k == cdofs[cind])) { 8959 /* Insert check for returning constrained indices */ 8960 indices[dof-k-1] = -(off+k+1); 8961 ++cind; 8962 } else { 8963 indices[dof-k-1] = off+k-cind; 8964 } 8965 } 8966 } 8967 } 8968 PetscFunctionReturn(0); 8969 } 8970 8971 #undef __FUNCT__ 8972 #define __FUNCT__ "indicesPointFields_private" 8973 /* . off - The global offset of this point */ 8974 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8975 { 8976 PetscInt numFields, foff, f; 8977 PetscErrorCode ierr; 8978 8979 PetscFunctionBegin; 8980 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8981 for (f = 0, foff = 0; f < numFields; ++f) { 8982 PetscInt fdof, fcomp, cfdof; 8983 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8984 PetscInt cind = 0, k, c; 8985 8986 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8987 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8988 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8989 if (!cfdof || setBC) { 8990 if (orientation >= 0) { 8991 for (k = 0; k < fdof; ++k) { 8992 indices[foffs[f]+k] = off+foff+k; 8993 } 8994 } else { 8995 for (k = fdof/fcomp-1; k >= 0; --k) { 8996 for (c = 0; c < fcomp; ++c) { 8997 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8998 } 8999 } 9000 } 9001 } else { 9002 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 9003 if (orientation >= 0) { 9004 for (k = 0; k < fdof; ++k) { 9005 if ((cind < cfdof) && (k == fcdofs[cind])) { 9006 indices[foffs[f]+k] = -(off+foff+k+1); 9007 ++cind; 9008 } else { 9009 indices[foffs[f]+k] = off+foff+k-cind; 9010 } 9011 } 9012 } else { 9013 for (k = fdof/fcomp-1; k >= 0; --k) { 9014 for (c = 0; c < fcomp; ++c) { 9015 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 9016 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 9017 ++cind; 9018 } else { 9019 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 9020 } 9021 } 9022 } 9023 } 9024 } 9025 foff += fdof - cfdof; 9026 foffs[f] += fdof; 9027 } 9028 PetscFunctionReturn(0); 9029 } 9030 9031 #undef __FUNCT__ 9032 #define __FUNCT__ "DMPlexMatSetClosure" 9033 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 9034 { 9035 DM_Plex *mesh = (DM_Plex *) dm->data; 9036 PetscInt *points = PETSC_NULL; 9037 PetscInt *indices; 9038 PetscInt offsets[32]; 9039 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 9040 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 9041 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 9042 PetscErrorCode ierr; 9043 9044 PetscFunctionBegin; 9045 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9046 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 9047 if (useDefault) { 9048 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9049 } 9050 if (useGlobalDefault) { 9051 if (useDefault) { 9052 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 9053 } else { 9054 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9055 } 9056 } 9057 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9058 if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 9059 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 9060 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9061 /* Compress out points not in the section */ 9062 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 9063 for (p = 0, q = 0; p < numPoints*2; p += 2) { 9064 if ((points[p] >= pStart) && (points[p] < pEnd)) { 9065 points[q*2] = points[p]; 9066 points[q*2+1] = points[p+1]; 9067 ++q; 9068 } 9069 } 9070 numPoints = q; 9071 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 9072 PetscInt fdof; 9073 9074 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 9075 for (f = 0; f < numFields; ++f) { 9076 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 9077 offsets[f+1] += fdof; 9078 } 9079 numIndices += dof; 9080 } 9081 for (f = 1; f < numFields; ++f) { 9082 offsets[f+1] += offsets[f]; 9083 } 9084 if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 9085 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9086 if (numFields) { 9087 for (p = 0; p < numPoints*2; p += 2) { 9088 PetscInt o = points[p+1]; 9089 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9090 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 9091 } 9092 } else { 9093 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 9094 PetscInt o = points[p+1]; 9095 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 9096 indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 9097 } 9098 } 9099 if (useGlobalDefault && !useDefault) { 9100 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9101 } 9102 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 9103 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 9104 if (ierr) { 9105 PetscMPIInt rank; 9106 PetscErrorCode ierr2; 9107 9108 ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 9109 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 9110 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 9111 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 9112 CHKERRQ(ierr); 9113 } 9114 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 9115 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 9116 PetscFunctionReturn(0); 9117 } 9118 9119 #undef __FUNCT__ 9120 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 9121 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9122 { 9123 PetscSection coordSection; 9124 Vec coordinates; 9125 const PetscScalar *coords; 9126 const PetscInt dim = 2; 9127 PetscInt d, f; 9128 PetscErrorCode ierr; 9129 9130 PetscFunctionBegin; 9131 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9132 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9133 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9134 if (v0) { 9135 for (d = 0; d < dim; d++) { 9136 v0[d] = PetscRealPart(coords[d]); 9137 } 9138 } 9139 if (J) { 9140 for (d = 0; d < dim; d++) { 9141 for (f = 0; f < dim; f++) { 9142 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9143 } 9144 } 9145 *detJ = J[0]*J[3] - J[1]*J[2]; 9146 #if 0 9147 if (detJ < 0.0) { 9148 const PetscReal xLength = mesh->periodicity[0]; 9149 9150 if (xLength != 0.0) { 9151 PetscReal v0x = coords[0*dim+0]; 9152 9153 if (v0x == 0.0) { 9154 v0x = v0[0] = xLength; 9155 } 9156 for (f = 0; f < dim; f++) { 9157 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 9158 9159 J[0*dim+f] = 0.5*(px - v0x); 9160 } 9161 } 9162 detJ = J[0]*J[3] - J[1]*J[2]; 9163 } 9164 #endif 9165 PetscLogFlops(8.0 + 3.0); 9166 } 9167 if (invJ) { 9168 const PetscReal invDet = 1.0/(*detJ); 9169 9170 invJ[0] = invDet*J[3]; 9171 invJ[1] = -invDet*J[1]; 9172 invJ[2] = -invDet*J[2]; 9173 invJ[3] = invDet*J[0]; 9174 PetscLogFlops(5.0); 9175 } 9176 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9177 PetscFunctionReturn(0); 9178 } 9179 9180 #undef __FUNCT__ 9181 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 9182 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9183 { 9184 PetscSection coordSection; 9185 Vec coordinates; 9186 const PetscScalar *coords; 9187 const PetscInt dim = 2; 9188 PetscInt d, f; 9189 PetscErrorCode ierr; 9190 9191 PetscFunctionBegin; 9192 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9193 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9194 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9195 if (v0) { 9196 for (d = 0; d < dim; d++) { 9197 v0[d] = PetscRealPart(coords[d]); 9198 } 9199 } 9200 if (J) { 9201 for (d = 0; d < dim; d++) { 9202 for (f = 0; f < dim; f++) { 9203 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9204 } 9205 } 9206 *detJ = J[0]*J[3] - J[1]*J[2]; 9207 PetscLogFlops(8.0 + 3.0); 9208 } 9209 if (invJ) { 9210 const PetscReal invDet = 1.0/(*detJ); 9211 9212 invJ[0] = invDet*J[3]; 9213 invJ[1] = -invDet*J[1]; 9214 invJ[2] = -invDet*J[2]; 9215 invJ[3] = invDet*J[0]; 9216 PetscLogFlops(5.0); 9217 } 9218 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9219 PetscFunctionReturn(0); 9220 } 9221 9222 #undef __FUNCT__ 9223 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 9224 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9225 { 9226 PetscSection coordSection; 9227 Vec coordinates; 9228 const PetscScalar *coords; 9229 const PetscInt dim = 3; 9230 PetscInt d, f; 9231 PetscErrorCode ierr; 9232 9233 PetscFunctionBegin; 9234 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9235 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9236 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9237 if (v0) { 9238 for (d = 0; d < dim; d++) { 9239 v0[d] = PetscRealPart(coords[d]); 9240 } 9241 } 9242 if (J) { 9243 for (d = 0; d < dim; d++) { 9244 for (f = 0; f < dim; f++) { 9245 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9246 } 9247 } 9248 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 9249 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9250 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9251 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9252 PetscLogFlops(18.0 + 12.0); 9253 } 9254 if (invJ) { 9255 const PetscReal invDet = 1.0/(*detJ); 9256 9257 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9258 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9259 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9260 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9261 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9262 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9263 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9264 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9265 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9266 PetscLogFlops(37.0); 9267 } 9268 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9269 PetscFunctionReturn(0); 9270 } 9271 9272 #undef __FUNCT__ 9273 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 9274 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 9275 { 9276 PetscSection coordSection; 9277 Vec coordinates; 9278 const PetscScalar *coords; 9279 const PetscInt dim = 3; 9280 PetscInt d; 9281 PetscErrorCode ierr; 9282 9283 PetscFunctionBegin; 9284 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9285 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9286 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9287 if (v0) { 9288 for (d = 0; d < dim; d++) { 9289 v0[d] = PetscRealPart(coords[d]); 9290 } 9291 } 9292 if (J) { 9293 for (d = 0; d < dim; d++) { 9294 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9295 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9296 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 9297 } 9298 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 9299 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 9300 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 9301 PetscLogFlops(18.0 + 12.0); 9302 } 9303 if (invJ) { 9304 const PetscReal invDet = -1.0/(*detJ); 9305 9306 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 9307 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 9308 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 9309 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 9310 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 9311 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 9312 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 9313 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 9314 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 9315 PetscLogFlops(37.0); 9316 } 9317 *detJ *= 8.0; 9318 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 9319 PetscFunctionReturn(0); 9320 } 9321 9322 #undef __FUNCT__ 9323 #define __FUNCT__ "DMPlexComputeCellGeometry" 9324 /*@C 9325 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 9326 9327 Collective on DM 9328 9329 Input Arguments: 9330 + dm - the DM 9331 - cell - the cell 9332 9333 Output Arguments: 9334 + v0 - the translation part of this affine transform 9335 . J - the Jacobian of the transform to the reference element 9336 . invJ - the inverse of the Jacobian 9337 - detJ - the Jacobian determinant 9338 9339 Level: advanced 9340 9341 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 9342 @*/ 9343 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 9344 { 9345 PetscInt dim, coneSize; 9346 PetscErrorCode ierr; 9347 9348 PetscFunctionBegin; 9349 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9350 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9351 switch (dim) { 9352 case 2: 9353 switch (coneSize) { 9354 case 3: 9355 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9356 break; 9357 case 4: 9358 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9359 break; 9360 default: 9361 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9362 } 9363 break; 9364 case 3: 9365 switch (coneSize) { 9366 case 4: 9367 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9368 break; 9369 case 8: 9370 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 9371 break; 9372 default: 9373 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 9374 } 9375 break; 9376 default: 9377 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 9378 } 9379 PetscFunctionReturn(0); 9380 } 9381 9382 #undef __FUNCT__ 9383 #define __FUNCT__ "DMPlexGetFaceOrientation" 9384 PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9385 { 9386 MPI_Comm comm = ((PetscObject) dm)->comm; 9387 PetscBool posOrient = PETSC_FALSE; 9388 const PetscInt debug = 0; 9389 PetscInt cellDim, faceSize, f; 9390 PetscErrorCode ierr; 9391 9392 ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 9393 if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 9394 9395 if (cellDim == numCorners-1) { 9396 /* Simplices */ 9397 faceSize = numCorners-1; 9398 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 9399 } else if (cellDim == 1 && numCorners == 3) { 9400 /* Quadratic line */ 9401 faceSize = 1; 9402 posOrient = PETSC_TRUE; 9403 } else if (cellDim == 2 && numCorners == 4) { 9404 /* Quads */ 9405 faceSize = 2; 9406 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 9407 posOrient = PETSC_TRUE; 9408 } else if ((indices[0] == 3) && (indices[1] == 0)) { 9409 posOrient = PETSC_TRUE; 9410 } else { 9411 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 9412 posOrient = PETSC_FALSE; 9413 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 9414 } 9415 } else if (cellDim == 2 && numCorners == 6) { 9416 /* Quadratic triangle (I hate this) */ 9417 /* Edges are determined by the first 2 vertices (corners of edges) */ 9418 const PetscInt faceSizeTri = 3; 9419 PetscInt sortedIndices[3], i, iFace; 9420 PetscBool found = PETSC_FALSE; 9421 PetscInt faceVerticesTriSorted[9] = { 9422 0, 3, 4, /* bottom */ 9423 1, 4, 5, /* right */ 9424 2, 3, 5, /* left */ 9425 }; 9426 PetscInt faceVerticesTri[9] = { 9427 0, 3, 4, /* bottom */ 9428 1, 4, 5, /* right */ 9429 2, 5, 3, /* left */ 9430 }; 9431 9432 faceSize = faceSizeTri; 9433 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 9434 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 9435 for (iFace = 0; iFace < 3; ++iFace) { 9436 const PetscInt ii = iFace*faceSizeTri; 9437 PetscInt fVertex, cVertex; 9438 9439 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 9440 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 9441 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 9442 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 9443 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 9444 faceVertices[fVertex] = origVertices[cVertex]; 9445 break; 9446 } 9447 } 9448 } 9449 found = PETSC_TRUE; 9450 break; 9451 } 9452 } 9453 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 9454 if (posOriented) {*posOriented = PETSC_TRUE;} 9455 PetscFunctionReturn(0); 9456 } else if (cellDim == 2 && numCorners == 9) { 9457 /* Quadratic quad (I hate this) */ 9458 /* Edges are determined by the first 2 vertices (corners of edges) */ 9459 const PetscInt faceSizeQuad = 3; 9460 PetscInt sortedIndices[3], i, iFace; 9461 PetscBool found = PETSC_FALSE; 9462 PetscInt faceVerticesQuadSorted[12] = { 9463 0, 1, 4, /* bottom */ 9464 1, 2, 5, /* right */ 9465 2, 3, 6, /* top */ 9466 0, 3, 7, /* left */ 9467 }; 9468 PetscInt faceVerticesQuad[12] = { 9469 0, 1, 4, /* bottom */ 9470 1, 2, 5, /* right */ 9471 2, 3, 6, /* top */ 9472 3, 0, 7, /* left */ 9473 }; 9474 9475 faceSize = faceSizeQuad; 9476 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 9477 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 9478 for (iFace = 0; iFace < 4; ++iFace) { 9479 const PetscInt ii = iFace*faceSizeQuad; 9480 PetscInt fVertex, cVertex; 9481 9482 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 9483 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 9484 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 9485 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 9486 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 9487 faceVertices[fVertex] = origVertices[cVertex]; 9488 break; 9489 } 9490 } 9491 } 9492 found = PETSC_TRUE; 9493 break; 9494 } 9495 } 9496 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 9497 if (posOriented) {*posOriented = PETSC_TRUE;} 9498 PetscFunctionReturn(0); 9499 } else if (cellDim == 3 && numCorners == 8) { 9500 /* Hexes 9501 A hex is two oriented quads with the normal of the first 9502 pointing up at the second. 9503 9504 7---6 9505 /| /| 9506 4---5 | 9507 | 3-|-2 9508 |/ |/ 9509 0---1 9510 9511 Faces are determined by the first 4 vertices (corners of faces) */ 9512 const PetscInt faceSizeHex = 4; 9513 PetscInt sortedIndices[4], i, iFace; 9514 PetscBool found = PETSC_FALSE; 9515 PetscInt faceVerticesHexSorted[24] = { 9516 0, 1, 2, 3, /* bottom */ 9517 4, 5, 6, 7, /* top */ 9518 0, 1, 4, 5, /* front */ 9519 1, 2, 5, 6, /* right */ 9520 2, 3, 6, 7, /* back */ 9521 0, 3, 4, 7, /* left */ 9522 }; 9523 PetscInt faceVerticesHex[24] = { 9524 3, 2, 1, 0, /* bottom */ 9525 4, 5, 6, 7, /* top */ 9526 0, 1, 5, 4, /* front */ 9527 1, 2, 6, 5, /* right */ 9528 2, 3, 7, 6, /* back */ 9529 3, 0, 4, 7, /* left */ 9530 }; 9531 9532 faceSize = faceSizeHex; 9533 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 9534 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 9535 for (iFace = 0; iFace < 6; ++iFace) { 9536 const PetscInt ii = iFace*faceSizeHex; 9537 PetscInt fVertex, cVertex; 9538 9539 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 9540 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 9541 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 9542 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 9543 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 9544 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 9545 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 9546 faceVertices[fVertex] = origVertices[cVertex]; 9547 break; 9548 } 9549 } 9550 } 9551 found = PETSC_TRUE; 9552 break; 9553 } 9554 } 9555 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9556 if (posOriented) {*posOriented = PETSC_TRUE;} 9557 PetscFunctionReturn(0); 9558 } else if (cellDim == 3 && numCorners == 10) { 9559 /* Quadratic tet */ 9560 /* Faces are determined by the first 3 vertices (corners of faces) */ 9561 const PetscInt faceSizeTet = 6; 9562 PetscInt sortedIndices[6], i, iFace; 9563 PetscBool found = PETSC_FALSE; 9564 PetscInt faceVerticesTetSorted[24] = { 9565 0, 1, 2, 6, 7, 8, /* bottom */ 9566 0, 3, 4, 6, 7, 9, /* front */ 9567 1, 4, 5, 7, 8, 9, /* right */ 9568 2, 3, 5, 6, 8, 9, /* left */ 9569 }; 9570 PetscInt faceVerticesTet[24] = { 9571 0, 1, 2, 6, 7, 8, /* bottom */ 9572 0, 4, 3, 6, 7, 9, /* front */ 9573 1, 5, 4, 7, 8, 9, /* right */ 9574 2, 3, 5, 8, 6, 9, /* left */ 9575 }; 9576 9577 faceSize = faceSizeTet; 9578 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 9579 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 9580 for (iFace=0; iFace < 4; ++iFace) { 9581 const PetscInt ii = iFace*faceSizeTet; 9582 PetscInt fVertex, cVertex; 9583 9584 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 9585 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 9586 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 9587 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 9588 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 9589 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 9590 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 9591 faceVertices[fVertex] = origVertices[cVertex]; 9592 break; 9593 } 9594 } 9595 } 9596 found = PETSC_TRUE; 9597 break; 9598 } 9599 } 9600 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 9601 if (posOriented) {*posOriented = PETSC_TRUE;} 9602 PetscFunctionReturn(0); 9603 } else if (cellDim == 3 && numCorners == 27) { 9604 /* Quadratic hexes (I hate this) 9605 A hex is two oriented quads with the normal of the first 9606 pointing up at the second. 9607 9608 7---6 9609 /| /| 9610 4---5 | 9611 | 3-|-2 9612 |/ |/ 9613 0---1 9614 9615 Faces are determined by the first 4 vertices (corners of faces) */ 9616 const PetscInt faceSizeQuadHex = 9; 9617 PetscInt sortedIndices[9], i, iFace; 9618 PetscBool found = PETSC_FALSE; 9619 PetscInt faceVerticesQuadHexSorted[54] = { 9620 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 9621 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9622 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 9623 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 9624 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 9625 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 9626 }; 9627 PetscInt faceVerticesQuadHex[54] = { 9628 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 9629 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 9630 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 9631 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 9632 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 9633 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 9634 }; 9635 9636 faceSize = faceSizeQuadHex; 9637 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 9638 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 9639 for (iFace = 0; iFace < 6; ++iFace) { 9640 const PetscInt ii = iFace*faceSizeQuadHex; 9641 PetscInt fVertex, cVertex; 9642 9643 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 9644 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 9645 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 9646 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 9647 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 9648 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 9649 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 9650 faceVertices[fVertex] = origVertices[cVertex]; 9651 break; 9652 } 9653 } 9654 } 9655 found = PETSC_TRUE; 9656 break; 9657 } 9658 } 9659 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 9660 if (posOriented) {*posOriented = PETSC_TRUE;} 9661 PetscFunctionReturn(0); 9662 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 9663 if (!posOrient) { 9664 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 9665 for (f = 0; f < faceSize; ++f) { 9666 faceVertices[f] = origVertices[faceSize-1 - f]; 9667 } 9668 } else { 9669 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 9670 for (f = 0; f < faceSize; ++f) { 9671 faceVertices[f] = origVertices[f]; 9672 } 9673 } 9674 if (posOriented) {*posOriented = posOrient;} 9675 PetscFunctionReturn(0); 9676 } 9677 9678 #undef __FUNCT__ 9679 #define __FUNCT__ "DMPlexGetOrientedFace" 9680 /* 9681 Given a cell and a face, as a set of vertices, 9682 return the oriented face, as a set of vertices, in faceVertices 9683 The orientation is such that the face normal points out of the cell 9684 */ 9685 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 9686 { 9687 const PetscInt *cone = PETSC_NULL; 9688 PetscInt coneSize, v, f, v2; 9689 PetscInt oppositeVertex = -1; 9690 PetscErrorCode ierr; 9691 9692 PetscFunctionBegin; 9693 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 9694 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 9695 for (v = 0, v2 = 0; v < coneSize; ++v) { 9696 PetscBool found = PETSC_FALSE; 9697 9698 for (f = 0; f < faceSize; ++f) { 9699 if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 9700 } 9701 if (found) { 9702 indices[v2] = v; 9703 origVertices[v2] = cone[v]; 9704 ++v2; 9705 } else { 9706 oppositeVertex = v; 9707 } 9708 } 9709 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 9710 PetscFunctionReturn(0); 9711 } 9712 9713 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 9714 { 9715 switch (i) { 9716 case 0: 9717 switch (j) { 9718 case 0: return 0; 9719 case 1: 9720 switch (k) { 9721 case 0: return 0; 9722 case 1: return 0; 9723 case 2: return 1; 9724 } 9725 case 2: 9726 switch (k) { 9727 case 0: return 0; 9728 case 1: return -1; 9729 case 2: return 0; 9730 } 9731 } 9732 case 1: 9733 switch (j) { 9734 case 0: 9735 switch (k) { 9736 case 0: return 0; 9737 case 1: return 0; 9738 case 2: return -1; 9739 } 9740 case 1: return 0; 9741 case 2: 9742 switch (k) { 9743 case 0: return 1; 9744 case 1: return 0; 9745 case 2: return 0; 9746 } 9747 } 9748 case 2: 9749 switch (j) { 9750 case 0: 9751 switch (k) { 9752 case 0: return 0; 9753 case 1: return 1; 9754 case 2: return 0; 9755 } 9756 case 1: 9757 switch (k) { 9758 case 0: return -1; 9759 case 1: return 0; 9760 case 2: return 0; 9761 } 9762 case 2: return 0; 9763 } 9764 } 9765 return 0; 9766 } 9767 9768 #undef __FUNCT__ 9769 #define __FUNCT__ "DMPlexCreateRigidBody" 9770 /*@C 9771 DMPlexCreateRigidBody - create rigid body modes from coordinates 9772 9773 Collective on DM 9774 9775 Input Arguments: 9776 + dm - the DM 9777 . section - the local section associated with the rigid field, or PETSC_NULL for the default section 9778 - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 9779 9780 Output Argument: 9781 . sp - the null space 9782 9783 Note: This is necessary to take account of Dirichlet conditions on the displacements 9784 9785 Level: advanced 9786 9787 .seealso: MatNullSpaceCreate() 9788 @*/ 9789 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 9790 { 9791 MPI_Comm comm = ((PetscObject) dm)->comm; 9792 Vec coordinates, localMode, mode[6]; 9793 PetscSection coordSection; 9794 PetscScalar *coords; 9795 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 9796 PetscErrorCode ierr; 9797 9798 PetscFunctionBegin; 9799 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9800 if (dim == 1) { 9801 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 9802 PetscFunctionReturn(0); 9803 } 9804 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 9805 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 9806 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 9807 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9808 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9809 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9810 m = (dim*(dim+1))/2; 9811 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 9812 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 9813 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 9814 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 9815 /* Assume P1 */ 9816 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 9817 for (d = 0; d < dim; ++d) { 9818 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9819 9820 values[d] = 1.0; 9821 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9822 for (v = vStart; v < vEnd; ++v) { 9823 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9824 } 9825 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9826 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9827 } 9828 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9829 for (d = dim; d < dim*(dim+1)/2; ++d) { 9830 PetscInt i, j, k = dim > 2 ? d - dim : d; 9831 9832 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 9833 for (v = vStart; v < vEnd; ++v) { 9834 PetscScalar values[3] = {0.0, 0.0, 0.0}; 9835 PetscInt off; 9836 9837 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 9838 for (i = 0; i < dim; ++i) { 9839 for (j = 0; j < dim; ++j) { 9840 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 9841 } 9842 } 9843 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 9844 } 9845 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9846 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 9847 } 9848 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9849 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 9850 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 9851 /* Orthonormalize system */ 9852 for (i = dim; i < m; ++i) { 9853 PetscScalar dots[6]; 9854 9855 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 9856 for (j = 0; j < i; ++j) dots[j] *= -1.0; 9857 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 9858 ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 9859 } 9860 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 9861 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 9862 PetscFunctionReturn(0); 9863 } 9864 9865 #undef __FUNCT__ 9866 #define __FUNCT__ "DMPlexGetHybridBounds" 9867 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 9868 { 9869 DM_Plex *mesh = (DM_Plex *) dm->data; 9870 PetscInt dim; 9871 PetscErrorCode ierr; 9872 9873 PetscFunctionBegin; 9874 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9875 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9876 if (cMax) *cMax = mesh->hybridPointMax[dim]; 9877 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 9878 if (eMax) *eMax = mesh->hybridPointMax[1]; 9879 if (vMax) *vMax = mesh->hybridPointMax[0]; 9880 PetscFunctionReturn(0); 9881 } 9882 9883 #undef __FUNCT__ 9884 #define __FUNCT__ "DMPlexSetHybridBounds" 9885 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 9886 { 9887 DM_Plex *mesh = (DM_Plex *) dm->data; 9888 PetscInt dim; 9889 PetscErrorCode ierr; 9890 9891 PetscFunctionBegin; 9892 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9893 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9894 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 9895 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 9896 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 9897 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 9898 PetscFunctionReturn(0); 9899 } 9900 9901 #undef __FUNCT__ 9902 #define __FUNCT__ "DMPlexGetVTKCellHeight" 9903 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 9904 { 9905 DM_Plex *mesh = (DM_Plex *) dm->data; 9906 9907 PetscFunctionBegin; 9908 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9909 PetscValidPointer(cellHeight, 2); 9910 *cellHeight = mesh->vtkCellHeight; 9911 PetscFunctionReturn(0); 9912 } 9913 9914 #undef __FUNCT__ 9915 #define __FUNCT__ "DMPlexSetVTKCellHeight" 9916 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 9917 { 9918 DM_Plex *mesh = (DM_Plex *) dm->data; 9919 9920 PetscFunctionBegin; 9921 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9922 mesh->vtkCellHeight = cellHeight; 9923 PetscFunctionReturn(0); 9924 } 9925 9926 #undef __FUNCT__ 9927 #define __FUNCT__ "DMPlexInsertFace_Private" 9928 /* 9929 DMPlexInsertFace_Private - Puts a face into the mesh 9930 9931 Not collective 9932 9933 Input Parameters: 9934 + dm - The DMPlex 9935 . numFaceVertex - The number of vertices in the face 9936 . faceVertices - The vertices in the face for dm 9937 . subfaceVertices - The vertices in the face for subdm 9938 . numCorners - The number of vertices in the cell 9939 . cell - A cell in dm containing the face 9940 . subcell - A cell in subdm containing the face 9941 . firstFace - First face in the mesh 9942 - newFacePoint - Next face in the mesh 9943 9944 Output Parameters: 9945 . newFacePoint - Contains next face point number on input, updated on output 9946 9947 Level: developer 9948 */ 9949 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) 9950 { 9951 MPI_Comm comm = ((PetscObject) dm)->comm; 9952 DM_Plex *submesh = (DM_Plex *) subdm->data; 9953 const PetscInt *faces; 9954 PetscInt numFaces, coneSize; 9955 PetscErrorCode ierr; 9956 9957 PetscFunctionBegin; 9958 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 9959 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 9960 #if 0 9961 /* Cannot use this because support() has not been constructed yet */ 9962 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 9963 #else 9964 { 9965 PetscInt f; 9966 9967 numFaces = 0; 9968 ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 9969 for (f = firstFace; f < *newFacePoint; ++f) { 9970 PetscInt dof, off, d; 9971 9972 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 9973 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 9974 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 9975 for (d = 0; d < dof; ++d) { 9976 const PetscInt p = submesh->cones[off+d]; 9977 PetscInt v; 9978 9979 for (v = 0; v < numFaceVertices; ++v) { 9980 if (subfaceVertices[v] == p) break; 9981 } 9982 if (v == numFaceVertices) break; 9983 } 9984 if (d == dof) { 9985 numFaces = 1; 9986 ((PetscInt *) faces)[0] = f; 9987 } 9988 } 9989 } 9990 #endif 9991 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 9992 else if (numFaces == 1) { 9993 /* Add the other cell neighbor for this face */ 9994 ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 9995 } else { 9996 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 9997 PetscBool posOriented; 9998 9999 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10000 origVertices = &orientedVertices[numFaceVertices]; 10001 indices = &orientedVertices[numFaceVertices*2]; 10002 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 10003 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 10004 /* TODO: I know that routine should return a permutation, not the indices */ 10005 for (v = 0; v < numFaceVertices; ++v) { 10006 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 10007 for (ov = 0; ov < numFaceVertices; ++ov) { 10008 if (orientedVertices[ov] == vertex) { 10009 orientedSubVertices[ov] = subvertex; 10010 break; 10011 } 10012 } 10013 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 10014 } 10015 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 10016 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 10017 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 10018 ++(*newFacePoint); 10019 } 10020 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 10021 PetscFunctionReturn(0); 10022 } 10023 10024 #undef __FUNCT__ 10025 #define __FUNCT__ "DMPlexCreateSubmesh" 10026 PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 10027 { 10028 MPI_Comm comm = ((PetscObject) dm)->comm; 10029 DM_Plex *submesh; 10030 PetscBool boundaryFaces = PETSC_FALSE; 10031 PetscSection coordSection, subCoordSection; 10032 Vec coordinates, subCoordinates; 10033 PetscScalar *coords, *subCoords; 10034 IS labelIS; 10035 const PetscInt *subVertices; 10036 PetscInt *subVerticesActive, *tmpPoints; 10037 PetscInt *subCells = PETSC_NULL; 10038 PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 10039 PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 10040 PetscInt dim; /* Right now, do not specify dimension */ 10041 PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 10042 PetscErrorCode ierr; 10043 10044 PetscFunctionBegin; 10045 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10046 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10047 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10048 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 10049 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10050 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 10051 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 10052 ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10053 subface = &face[maxConeSize]; 10054 ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 10055 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 10056 ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 10057 ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 10058 ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 10059 ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 10060 maxSubCells = numSubVertices; 10061 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 10062 ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 10063 ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 10064 for (v = 0; v < numSubVertices; ++v) { 10065 const PetscInt vertex = subVertices[v]; 10066 PetscInt *star = PETSC_NULL; 10067 PetscInt starSize, numCells = 0; 10068 10069 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10070 for (p = 0; p < starSize*2; p += 2) { 10071 const PetscInt point = star[p]; 10072 if ((point >= cStart) && (point < cEnd)) { 10073 star[numCells++] = point; 10074 } 10075 } 10076 numOldSubCells = numSubCells; 10077 for (c = 0; c < numCells; ++c) { 10078 const PetscInt cell = star[c]; 10079 PetscInt *closure = PETSC_NULL; 10080 PetscInt closureSize, numCorners = 0, faceSize = 0; 10081 PetscInt cellLoc; 10082 10083 ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 10084 if (cellLoc >= 0) continue; 10085 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10086 for (p = 0; p < closureSize*2; p += 2) { 10087 const PetscInt point = closure[p]; 10088 if ((point >= vStart) && (point < vEnd)) { 10089 closure[numCorners++] = point; 10090 } 10091 } 10092 if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 10093 for (corner = 0; corner < numCorners; ++corner) { 10094 const PetscInt cellVertex = closure[corner]; 10095 PetscInt subVertex; 10096 10097 ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 10098 if (subVertex >= 0) { /* contains submesh vertex */ 10099 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 10100 if (i == faceSize) { 10101 if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 10102 face[faceSize] = cellVertex; 10103 subface[faceSize] = subVertex; 10104 ++faceSize; 10105 } 10106 } 10107 } 10108 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10109 if (faceSize >= nFV) { 10110 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10111 if (numSubCells >= maxSubCells) { 10112 PetscInt *tmpCells; 10113 maxSubCells *= 2; 10114 ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 10115 ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 10116 ierr = PetscFree(subCells);CHKERRQ(ierr); 10117 subCells = tmpCells; 10118 } 10119 /* TOOD: Maybe overestimate then squeeze out empty faces */ 10120 if (faceSize > nFV) { 10121 /* TODO: This is tricky. Maybe just add all faces */ 10122 numSubFaces++; 10123 } else { 10124 numSubFaces++; 10125 } 10126 for (f = 0; f < faceSize; ++f) { 10127 subVerticesActive[subface[f]] = 1; 10128 } 10129 subCells[numSubCells++] = cell; 10130 } 10131 } 10132 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10133 ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 10134 } 10135 /* Pick out active subvertices */ 10136 for (v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 10137 if (subVerticesActive[v]) { 10138 subVerticesActive[numSubVerticesActive++] = subVertices[v]; 10139 } 10140 } 10141 ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 10142 /* Set cone sizes */ 10143 firstSubVertex = numSubCells; 10144 firstSubFace = numSubCells+numSubVerticesActive; 10145 newFacePoint = firstSubFace; 10146 for (c = 0; c < numSubCells; ++c) { 10147 ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 10148 } 10149 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 10150 ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 10151 } 10152 ierr = DMSetUp(*subdm);CHKERRQ(ierr); 10153 /* Create face cones */ 10154 for (c = 0; c < numSubCells; ++c) { 10155 const PetscInt cell = subCells[c]; 10156 PetscInt *closure = PETSC_NULL; 10157 PetscInt closureSize, numCorners = 0, faceSize = 0; 10158 10159 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10160 for (p = 0; p < closureSize*2; p += 2) { 10161 const PetscInt point = closure[p]; 10162 if ((point >= vStart) && (point < vEnd)) { 10163 closure[numCorners++] = point; 10164 } 10165 } 10166 for (corner = 0; corner < numCorners; ++corner) { 10167 const PetscInt cellVertex = closure[corner]; 10168 PetscInt subVertex; 10169 10170 ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 10171 if (subVertex >= 0) { /* contains submesh vertex */ 10172 for (i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 10173 if (i == faceSize) { 10174 face[faceSize] = cellVertex; 10175 subface[faceSize] = numSubCells+subVertex; 10176 ++faceSize; 10177 } 10178 } 10179 } 10180 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 10181 if (faceSize >= nFV) { 10182 if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 10183 /* Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) */ 10184 /* We have to take all the faces, and discard those in the interior */ 10185 /* We check the join of the face vertices, which produces 2 cells if in the interior */ 10186 #if 0 10187 /* This object just calls insert on each face that comes from subsets() */ 10188 /* In fact, we can just always acll subsets(), since when we pass a single face it is a single call */ 10189 FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 10190 PointArray faceVec(face->begin(), face->end()); 10191 10192 subsets(faceVec, nFV, inserter); 10193 #endif 10194 ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 10195 } 10196 } 10197 ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 10198 ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 10199 /* Build coordinates */ 10200 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 10201 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10202 ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 10203 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 10204 for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 10205 ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 10206 } 10207 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 10208 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 10209 ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 10210 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 10211 ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 10212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 10213 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10214 for (v = 0; v < numSubVerticesActive; ++v) { 10215 const PetscInt vertex = subVerticesActive[v]; 10216 const PetscInt subVertex = firstSubVertex+v; 10217 PetscInt dof, off, sdof, soff; 10218 10219 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 10220 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 10221 ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 10222 ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 10223 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 10224 for (d = 0; d < dof; ++d) { 10225 subCoords[soff+d] = coords[off+d]; 10226 } 10227 } 10228 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 10229 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 10230 ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 10231 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 10232 10233 ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 10234 /* Create map from submesh points to original mesh points */ 10235 submesh = (DM_Plex *) (*subdm)->data; 10236 ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 10237 for (c = 0; c < numSubCells; ++c) { 10238 tmpPoints[c] = subCells[c]; 10239 } 10240 for (v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 10241 tmpPoints[v] = subVerticesActive[v-numSubCells]; 10242 } 10243 ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 10244 10245 ierr = PetscFree(subCells);CHKERRQ(ierr); 10246 ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 10247 ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 10248 ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 10249 ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 10250 PetscFunctionReturn(0); 10251 } 10252 10253 #undef __FUNCT__ 10254 #define __FUNCT__ "DMPlexCreateNumbering_Private" 10255 /* We can easily have a form that takes an IS instead */ 10256 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 10257 { 10258 PetscSection section, globalSection; 10259 PetscInt *numbers, p; 10260 PetscErrorCode ierr; 10261 10262 PetscFunctionBegin; 10263 ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 10264 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 10265 for (p = pStart; p < pEnd; ++p) { 10266 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 10267 } 10268 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 10269 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 10270 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 10271 for (p = pStart; p < pEnd; ++p) { 10272 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 10273 } 10274 ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 10275 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 10276 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 10277 PetscFunctionReturn(0); 10278 } 10279 10280 #undef __FUNCT__ 10281 #define __FUNCT__ "DMPlexGetCellNumbering" 10282 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 10283 { 10284 DM_Plex *mesh = (DM_Plex *) dm->data; 10285 PetscInt cellHeight, cStart, cEnd, cMax; 10286 PetscErrorCode ierr; 10287 10288 PetscFunctionBegin; 10289 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10290 if (!mesh->globalCellNumbers) { 10291 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10292 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 10293 ierr = DMPlexGetHybridBounds(dm, &cMax, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 10294 if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 10295 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 10296 } 10297 *globalCellNumbers = mesh->globalCellNumbers; 10298 PetscFunctionReturn(0); 10299 } 10300 10301 #undef __FUNCT__ 10302 #define __FUNCT__ "DMPlexGetVertexNumbering" 10303 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 10304 { 10305 DM_Plex *mesh = (DM_Plex *) dm->data; 10306 PetscInt vStart, vEnd, vMax; 10307 PetscErrorCode ierr; 10308 10309 PetscFunctionBegin; 10310 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10311 if (!mesh->globalVertexNumbers) { 10312 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10313 ierr = DMPlexGetHybridBounds(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vMax);CHKERRQ(ierr); 10314 if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 10315 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 10316 } 10317 *globalVertexNumbers = mesh->globalVertexNumbers; 10318 PetscFunctionReturn(0); 10319 } 10320 10321 #undef __FUNCT__ 10322 #define __FUNCT__ "DMPlexGetSubpointMap" 10323 PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 10324 { 10325 DM_Plex *mesh = (DM_Plex *) dm->data; 10326 10327 PetscFunctionBegin; 10328 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10329 PetscValidPointer(subpointMap, 2); 10330 *subpointMap = mesh->subpointMap; 10331 PetscFunctionReturn(0); 10332 } 10333 10334 #undef __FUNCT__ 10335 #define __FUNCT__ "DMPlexSetSubpointMap" 10336 /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 10337 PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 10338 { 10339 DM_Plex *mesh = (DM_Plex *) dm->data; 10340 10341 PetscFunctionBegin; 10342 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10343 PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 10344 mesh->subpointMap = subpointMap; 10345 PetscFunctionReturn(0); 10346 } 10347 10348 #undef __FUNCT__ 10349 #define __FUNCT__ "DMPlexGetScale" 10350 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10351 { 10352 DM_Plex *mesh = (DM_Plex *) dm->data; 10353 10354 PetscFunctionBegin; 10355 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10356 PetscValidPointer(scale, 3); 10357 *scale = mesh->scale[unit]; 10358 PetscFunctionReturn(0); 10359 } 10360 10361 #undef __FUNCT__ 10362 #define __FUNCT__ "DMPlexSetScale" 10363 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 10364 { 10365 DM_Plex *mesh = (DM_Plex *) dm->data; 10366 10367 PetscFunctionBegin; 10368 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10369 mesh->scale[unit] = scale; 10370 PetscFunctionReturn(0); 10371 } 10372 10373 10374 /******************************************************************************* 10375 This should be in a separate Discretization object, but I am not sure how to lay 10376 it out yet, so I am stuffing things here while I experiment. 10377 *******************************************************************************/ 10378 #undef __FUNCT__ 10379 #define __FUNCT__ "DMPlexSetFEMIntegration" 10380 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 10381 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10382 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10383 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10384 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10385 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 10386 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10387 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10388 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10389 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10390 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 10391 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 10392 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 10393 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10394 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10395 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 10396 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 10397 { 10398 DM_Plex *mesh = (DM_Plex *) dm->data; 10399 10400 PetscFunctionBegin; 10401 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10402 mesh->integrateResidualFEM = integrateResidualFEM; 10403 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 10404 mesh->integrateJacobianFEM = integrateJacobianFEM; 10405 PetscFunctionReturn(0); 10406 } 10407 10408 #undef __FUNCT__ 10409 #define __FUNCT__ "DMPlexProjectFunctionLocal" 10410 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 10411 { 10412 Vec coordinates; 10413 PetscSection section, cSection; 10414 PetscInt dim, vStart, vEnd, v, c, d; 10415 PetscScalar *values, *cArray; 10416 PetscReal *coords; 10417 PetscErrorCode ierr; 10418 10419 PetscFunctionBegin; 10420 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10421 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10422 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 10423 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 10424 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10425 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 10426 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 10427 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 10428 for (v = vStart; v < vEnd; ++v) { 10429 PetscInt dof, off; 10430 10431 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 10432 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 10433 if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 10434 for (d = 0; d < dof; ++d) { 10435 coords[d] = PetscRealPart(cArray[off+d]); 10436 } 10437 for (c = 0; c < numComp; ++c) { 10438 values[c] = (*funcs[c])(coords); 10439 } 10440 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 10441 } 10442 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 10443 /* Temporary, must be replaced by a projection on the finite element basis */ 10444 { 10445 PetscInt eStart = 0, eEnd = 0, e, depth; 10446 10447 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 10448 --depth; 10449 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 10450 for (e = eStart; e < eEnd; ++e) { 10451 const PetscInt *cone = PETSC_NULL; 10452 PetscInt coneSize, d; 10453 PetscScalar *coordsA, *coordsB; 10454 10455 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 10456 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 10457 if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 10458 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 10459 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 10460 for (d = 0; d < dim; ++d) { 10461 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 10462 } 10463 for (c = 0; c < numComp; ++c) { 10464 values[c] = (*funcs[c])(coords); 10465 } 10466 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 10467 } 10468 } 10469 10470 ierr = PetscFree(coords);CHKERRQ(ierr); 10471 ierr = PetscFree(values);CHKERRQ(ierr); 10472 #if 0 10473 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 10474 PetscReal detJ; 10475 10476 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 10477 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 10478 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 10479 10480 for (PetscInt c = cStart; c < cEnd; ++c) { 10481 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 10482 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 10483 const int oSize = pV.getSize(); 10484 int v = 0; 10485 10486 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 10487 for (PetscInt cl = 0; cl < oSize; ++cl) { 10488 const PetscInt fDim; 10489 10490 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 10491 if (pointDim) { 10492 for (PetscInt d = 0; d < fDim; ++d, ++v) { 10493 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 10494 } 10495 } 10496 } 10497 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 10498 pV.clear(); 10499 } 10500 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 10501 ierr = PetscFree(values);CHKERRQ(ierr); 10502 #endif 10503 PetscFunctionReturn(0); 10504 } 10505 10506 #undef __FUNCT__ 10507 #define __FUNCT__ "DMPlexProjectFunction" 10508 /*@C 10509 DMPlexProjectFunction - This projects the given function into the function space provided. 10510 10511 Input Parameters: 10512 + dm - The DM 10513 . numComp - The number of components (functions) 10514 . funcs - The coordinate functions to evaluate 10515 - mode - The insertion mode for values 10516 10517 Output Parameter: 10518 . X - vector 10519 10520 Level: developer 10521 10522 Note: 10523 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 10524 We will eventually fix it. 10525 10526 ,seealso: DMPlexComputeL2Diff() 10527 */ 10528 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 10529 { 10530 Vec localX; 10531 PetscErrorCode ierr; 10532 10533 PetscFunctionBegin; 10534 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10535 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 10536 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 10537 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 10538 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10539 PetscFunctionReturn(0); 10540 } 10541 10542 #undef __FUNCT__ 10543 #define __FUNCT__ "DMPlexComputeL2Diff" 10544 /*@C 10545 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 10546 10547 Input Parameters: 10548 + dm - The DM 10549 . quad - The PetscQuadrature object for each field 10550 . funcs - The functions to evaluate for each field component 10551 - X - The coefficient vector u_h 10552 10553 Output Parameter: 10554 . diff - The diff ||u - u_h||_2 10555 10556 Level: developer 10557 10558 .seealso: DMPlexProjectFunction() 10559 */ 10560 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 10561 { 10562 const PetscInt debug = 0; 10563 PetscSection section; 10564 Vec localX; 10565 PetscReal *coords, *v0, *J, *invJ, detJ; 10566 PetscReal localDiff = 0.0; 10567 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 10568 PetscErrorCode ierr; 10569 10570 PetscFunctionBegin; 10571 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10572 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10573 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10574 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 10575 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10576 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 10577 for (field = 0; field < numFields; ++field) { 10578 numComponents += quad[field].numComponents; 10579 } 10580 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 10581 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 10582 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10583 for (c = cStart; c < cEnd; ++c) { 10584 const PetscScalar *x; 10585 PetscReal elemDiff = 0.0; 10586 10587 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 10588 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 10589 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10590 10591 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 10592 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10593 const PetscReal *quadPoints = quad[field].quadPoints; 10594 const PetscReal *quadWeights = quad[field].quadWeights; 10595 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10596 const PetscInt numBasisComps = quad[field].numComponents; 10597 const PetscReal *basis = quad[field].basis; 10598 PetscInt q, d, e, fc, f; 10599 10600 if (debug) { 10601 char title[1024]; 10602 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 10603 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 10604 } 10605 for (q = 0; q < numQuadPoints; ++q) { 10606 for (d = 0; d < dim; d++) { 10607 coords[d] = v0[d]; 10608 for (e = 0; e < dim; e++) { 10609 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 10610 } 10611 } 10612 for (fc = 0; fc < numBasisComps; ++fc) { 10613 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 10614 PetscReal interpolant = 0.0; 10615 for (f = 0; f < numBasisFuncs; ++f) { 10616 const PetscInt fidx = f*numBasisComps+fc; 10617 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 10618 } 10619 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 10620 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 10621 } 10622 } 10623 comp += numBasisComps; 10624 fieldOffset += numBasisFuncs*numBasisComps; 10625 } 10626 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 10627 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 10628 localDiff += elemDiff; 10629 } 10630 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 10631 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 10632 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 10633 *diff = PetscSqrtReal(*diff); 10634 PetscFunctionReturn(0); 10635 } 10636 10637 #undef __FUNCT__ 10638 #define __FUNCT__ "DMPlexComputeResidualFEM" 10639 /*@ 10640 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 10641 10642 Input Parameters: 10643 + dm - The mesh 10644 . X - Local input vector 10645 - user - The user context 10646 10647 Output Parameter: 10648 . F - Local output vector 10649 10650 Note: 10651 The second member of the user context must be an FEMContext. 10652 10653 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10654 like a GPU, or vectorize on a multicore machine. 10655 10656 .seealso: DMPlexComputeJacobianActionFEM() 10657 */ 10658 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 10659 { 10660 DM_Plex *mesh = (DM_Plex *) dm->data; 10661 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10662 PetscQuadrature *quad = fem->quad; 10663 PetscSection section; 10664 PetscReal *v0, *J, *invJ, *detJ; 10665 PetscScalar *elemVec, *u; 10666 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10667 PetscInt cellDof = 0, numComponents = 0; 10668 PetscErrorCode ierr; 10669 10670 PetscFunctionBegin; 10671 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10672 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10673 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10674 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10675 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10676 numCells = cEnd - cStart; 10677 for (field = 0; field < numFields; ++field) { 10678 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10679 numComponents += quad[field].numComponents; 10680 } 10681 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10682 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10683 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); 10684 for (c = cStart; c < cEnd; ++c) { 10685 const PetscScalar *x; 10686 PetscInt i; 10687 10688 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10689 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10690 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10691 10692 for (i = 0; i < cellDof; ++i) { 10693 u[c*cellDof+i] = x[i]; 10694 } 10695 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10696 } 10697 for (field = 0; field < numFields; ++field) { 10698 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10699 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10700 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 10701 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 10702 /* Conforming batches */ 10703 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10704 PetscInt numBlocks = 1; 10705 PetscInt batchSize = numBlocks * blockSize; 10706 PetscInt numBatches = numBatchesTmp; 10707 PetscInt numChunks = numCells / (numBatches*batchSize); 10708 /* Remainder */ 10709 PetscInt numRemainder = numCells % (numBatches * batchSize); 10710 PetscInt offset = numCells - numRemainder; 10711 10712 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 10713 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10714 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10715 } 10716 for (c = cStart; c < cEnd; ++c) { 10717 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10718 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10719 } 10720 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10721 if (mesh->printFEM) { 10722 PetscMPIInt rank, numProcs; 10723 PetscInt p; 10724 10725 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10726 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10727 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 10728 for (p = 0; p < numProcs; ++p) { 10729 if (p == rank) { 10730 Vec f; 10731 10732 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 10733 ierr = VecCopy(F, f);CHKERRQ(ierr); 10734 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 10735 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10736 ierr = VecDestroy(&f);CHKERRQ(ierr); 10737 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 10738 } 10739 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10740 } 10741 } 10742 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10743 PetscFunctionReturn(0); 10744 } 10745 10746 #undef __FUNCT__ 10747 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 10748 /*@C 10749 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 10750 10751 Input Parameters: 10752 + dm - The mesh 10753 . J - The Jacobian shell matrix 10754 . X - Local input vector 10755 - user - The user context 10756 10757 Output Parameter: 10758 . F - Local output vector 10759 10760 Note: 10761 The second member of the user context must be an FEMContext. 10762 10763 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10764 like a GPU, or vectorize on a multicore machine. 10765 10766 .seealso: DMPlexComputeResidualFEM() 10767 */ 10768 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 10769 { 10770 DM_Plex *mesh = (DM_Plex *) dm->data; 10771 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10772 PetscQuadrature *quad = fem->quad; 10773 PetscSection section; 10774 JacActionCtx *jctx; 10775 PetscReal *v0, *J, *invJ, *detJ; 10776 PetscScalar *elemVec, *u, *a; 10777 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10778 PetscInt cellDof = 0; 10779 PetscErrorCode ierr; 10780 10781 PetscFunctionBegin; 10782 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10783 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10784 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10785 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10786 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10787 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10788 numCells = cEnd - cStart; 10789 for (field = 0; field < numFields; ++field) { 10790 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10791 } 10792 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10793 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); 10794 for (c = cStart; c < cEnd; ++c) { 10795 const PetscScalar *x; 10796 PetscInt i; 10797 10798 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10799 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10800 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10801 for (i = 0; i < cellDof; ++i) { 10802 u[c*cellDof+i] = x[i]; 10803 } 10804 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 10805 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10806 for (i = 0; i < cellDof; ++i) { 10807 a[c*cellDof+i] = x[i]; 10808 } 10809 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10810 } 10811 for (field = 0; field < numFields; ++field) { 10812 const PetscInt numQuadPoints = quad[field].numQuadPoints; 10813 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 10814 /* Conforming batches */ 10815 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10816 PetscInt numBlocks = 1; 10817 PetscInt batchSize = numBlocks * blockSize; 10818 PetscInt numBatches = numBatchesTmp; 10819 PetscInt numChunks = numCells / (numBatches*batchSize); 10820 /* Remainder */ 10821 PetscInt numRemainder = numCells % (numBatches * batchSize); 10822 PetscInt offset = numCells - numRemainder; 10823 10824 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); 10825 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], 10826 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 10827 } 10828 for (c = cStart; c < cEnd; ++c) { 10829 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 10830 ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 10831 } 10832 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 10833 if (mesh->printFEM) { 10834 PetscMPIInt rank, numProcs; 10835 PetscInt p; 10836 10837 ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 10838 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 10839 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 10840 for (p = 0; p < numProcs; ++p) { 10841 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 10842 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 10843 } 10844 } 10845 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10846 PetscFunctionReturn(0); 10847 } 10848 10849 #undef __FUNCT__ 10850 #define __FUNCT__ "DMPlexComputeJacobianFEM" 10851 /*@ 10852 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 10853 10854 Input Parameters: 10855 + dm - The mesh 10856 . X - Local input vector 10857 - user - The user context 10858 10859 Output Parameter: 10860 . Jac - Jacobian matrix 10861 10862 Note: 10863 The second member of the user context must be an FEMContext. 10864 10865 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 10866 like a GPU, or vectorize on a multicore machine. 10867 10868 .seealso: FormFunctionLocal() 10869 */ 10870 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 10871 { 10872 DM_Plex *mesh = (DM_Plex *) dm->data; 10873 PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 10874 PetscQuadrature *quad = fem->quad; 10875 PetscSection section; 10876 PetscReal *v0, *J, *invJ, *detJ; 10877 PetscScalar *elemMat, *u; 10878 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 10879 PetscInt cellDof = 0, numComponents = 0; 10880 PetscBool isShell; 10881 PetscErrorCode ierr; 10882 10883 PetscFunctionBegin; 10884 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10885 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 10886 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10887 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10888 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10889 numCells = cEnd - cStart; 10890 for (field = 0; field < numFields; ++field) { 10891 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 10892 numComponents += quad[field].numComponents; 10893 } 10894 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 10895 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 10896 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); 10897 for (c = cStart; c < cEnd; ++c) { 10898 const PetscScalar *x; 10899 PetscInt i; 10900 10901 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10902 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10903 ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10904 10905 for (i = 0; i < cellDof; ++i) { 10906 u[c*cellDof+i] = x[i]; 10907 } 10908 ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 10909 } 10910 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 10911 for (fieldI = 0; fieldI < numFields; ++fieldI) { 10912 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 10913 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 10914 PetscInt fieldJ; 10915 10916 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 10917 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 10918 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 10919 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 10920 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 10921 /* Conforming batches */ 10922 PetscInt blockSize = numBasisFuncs*numQuadPoints; 10923 PetscInt numBlocks = 1; 10924 PetscInt batchSize = numBlocks * blockSize; 10925 PetscInt numBatches = numBatchesTmp; 10926 PetscInt numChunks = numCells / (numBatches*batchSize); 10927 /* Remainder */ 10928 PetscInt numRemainder = numCells % (numBatches * batchSize); 10929 PetscInt offset = numCells - numRemainder; 10930 10931 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 10932 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 10933 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 10934 } 10935 } 10936 for (c = cStart; c < cEnd; ++c) { 10937 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 10938 ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 10939 } 10940 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 10941 10942 /* Assemble matrix, using the 2-step process: 10943 MatAssemblyBegin(), MatAssemblyEnd(). */ 10944 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10945 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10946 10947 if (mesh->printFEM) { 10948 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 10949 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 10950 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 10951 } 10952 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 10953 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 10954 if (isShell) { 10955 JacActionCtx *jctx; 10956 10957 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 10958 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 10959 } 10960 *str = SAME_NONZERO_PATTERN; 10961 PetscFunctionReturn(0); 10962 } 10963 10964 10965 #undef __FUNCT__ 10966 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 10967 /*@C 10968 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 10969 the local section and an SF describing the section point overlap. 10970 10971 Input Parameters: 10972 + s - The PetscSection for the local field layout 10973 . sf - The SF describing parallel layout of the section points 10974 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 10975 . label - The label specifying the points 10976 - labelValue - The label stratum specifying the points 10977 10978 Output Parameter: 10979 . gsection - The PetscSection for the global field layout 10980 10981 Note: This gives negative sizes and offsets to points not owned by this process 10982 10983 Level: developer 10984 10985 .seealso: PetscSectionCreate() 10986 @*/ 10987 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 10988 { 10989 PetscInt *neg; 10990 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 10991 PetscErrorCode ierr; 10992 10993 PetscFunctionBegin; 10994 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 10995 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 10996 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 10997 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 10998 /* Mark ghost points with negative dof */ 10999 for (p = pStart; p < pEnd; ++p) { 11000 PetscInt value; 11001 11002 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 11003 if (value != labelValue) continue; 11004 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 11005 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 11006 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 11007 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 11008 neg[p-pStart] = -(dof+1); 11009 } 11010 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 11011 ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 11012 if (nroots >= 0) { 11013 if (nroots > pEnd - pStart) { 11014 PetscInt *tmpDof; 11015 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11016 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 11017 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11018 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 11019 for (p = pStart; p < pEnd; ++p) { 11020 if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 11021 } 11022 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 11023 } else { 11024 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11025 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 11026 } 11027 } 11028 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 11029 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11030 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 11031 (*gsection)->atlasOff[p] = off; 11032 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 11033 } 11034 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 11035 globalOff -= off; 11036 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 11037 (*gsection)->atlasOff[p] += globalOff; 11038 neg[p] = -((*gsection)->atlasOff[p]+1); 11039 } 11040 /* Put in negative offsets for ghost points */ 11041 if (nroots >= 0) { 11042 if (nroots > pEnd - pStart) { 11043 PetscInt *tmpOff; 11044 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 11045 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 11046 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11047 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 11048 for (p = pStart; p < pEnd; ++p) { 11049 if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 11050 } 11051 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 11052 } else { 11053 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11054 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 11055 } 11056 } 11057 ierr = PetscFree(neg);CHKERRQ(ierr); 11058 PetscFunctionReturn(0); 11059 } 11060