1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/vecimpl.h> 4 #include <petsc-private/isimpl.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 8 9 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "VecView_Plex_Local" 14 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 15 { 16 DM dm; 17 PetscBool isvtk; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 22 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 23 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 24 if (isvtk) { 25 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 26 PetscSection section; 27 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 28 29 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 30 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 33 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 34 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 35 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 36 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 37 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 38 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 39 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 40 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 41 } else if (cdof && vdof) { 42 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 43 } else if (cdof) { 44 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 45 * vector or just happens to have the same number of dofs as the dimension. */ 46 if (cdof == dim) { 47 ft = PETSC_VTK_CELL_VECTOR_FIELD; 48 } else { 49 ft = PETSC_VTK_CELL_FIELD; 50 } 51 } else if (vdof) { 52 if (vdof == dim) { 53 ft = PETSC_VTK_POINT_VECTOR_FIELD; 54 } else { 55 ft = PETSC_VTK_POINT_FIELD; 56 } 57 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 58 59 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 61 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 62 } else { 63 PetscBool isseq; 64 65 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 66 if (isseq) { 67 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 68 } else { 69 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "VecView_Plex" 77 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 78 { 79 DM dm; 80 PetscBool isvtk; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 85 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 86 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 87 if (isvtk) { 88 Vec locv; 89 const char *name; 90 91 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 92 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 93 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 96 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 97 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 98 } else { 99 PetscBool isseq; 100 101 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 102 if (isseq) { 103 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 104 } else { 105 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexView_Ascii" 113 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 114 { 115 DM_Plex *mesh = (DM_Plex*) dm->data; 116 DM cdm; 117 DMLabel markers; 118 PetscSection coordSection; 119 Vec coordinates; 120 PetscViewerFormat format; 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 125 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 126 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 127 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 128 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 129 const char *name; 130 PetscInt maxConeSize, maxSupportSize; 131 PetscInt pStart, pEnd, p; 132 PetscMPIInt rank, size; 133 134 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 135 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 136 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 137 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 138 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 143 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 144 for (p = pStart; p < pEnd; ++p) { 145 PetscInt dof, off, s; 146 147 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 148 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 149 for (s = off; s < off+dof; ++s) { 150 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 151 } 152 } 153 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 154 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 155 for (p = pStart; p < pEnd; ++p) { 156 PetscInt dof, off, c; 157 158 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 159 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 160 for (c = off; c < off+dof; ++c) { 161 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 162 } 163 } 164 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 165 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 166 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 167 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 168 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 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(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &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(PetscObjectComm((PetscObject)dm), 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 = 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; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscMPIInt size; 282 283 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 284 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 285 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 286 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 287 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 288 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 289 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 290 if (depth == 1) { 291 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 292 pEnd = pEnd - pStart; 293 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 294 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 295 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 296 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 297 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 298 pEnd = pEnd - pStart; 299 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 300 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 301 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 302 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 303 } else { 304 for (d = 0; d <= dim; d++) { 305 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 306 pEnd = pEnd - pStart; 307 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 308 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 309 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 310 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 311 } 312 } 313 ierr = PetscFree(sizes);CHKERRQ(ierr); 314 } 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "DMView_Plex" 320 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 321 { 322 PetscBool iascii, isbinary; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 327 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 328 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 330 if (iascii) { 331 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 332 #if 0 333 } else if (isbinary) { 334 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 335 #endif 336 } 337 PetscFunctionReturn(0); 338 } 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "DMDestroy_Plex" 342 PetscErrorCode DMDestroy_Plex(DM dm) 343 { 344 DM_Plex *mesh = (DM_Plex*) dm->data; 345 DMLabel next = mesh->labels; 346 PetscErrorCode ierr; 347 348 PetscFunctionBegin; 349 if (--mesh->refct > 0) PetscFunctionReturn(0); 350 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 351 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 352 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 353 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 354 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 355 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 356 while (next) { 357 DMLabel tmp = next->next; 358 359 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 360 next = tmp; 361 } 362 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 363 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 364 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 365 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 366 ierr = PetscFree(mesh);CHKERRQ(ierr); 367 PetscFunctionReturn(0); 368 } 369 370 #undef __FUNCT__ 371 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 372 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 373 { 374 const PetscInt *support = NULL; 375 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 376 PetscErrorCode ierr; 377 378 PetscFunctionBegin; 379 if (useClosure) { 380 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 381 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 382 for (s = 0; s < supportSize; ++s) { 383 const PetscInt *cone = NULL; 384 PetscInt coneSize, c, q; 385 386 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 387 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 388 for (c = 0; c < coneSize; ++c) { 389 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 390 if (cone[c] == adj[q]) break; 391 } 392 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 393 } 394 } 395 } else { 396 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 397 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 398 for (s = 0; s < supportSize; ++s) { 399 const PetscInt *cone = NULL; 400 PetscInt coneSize, c, q; 401 402 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 403 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 404 for (c = 0; c < coneSize; ++c) { 405 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 406 if (cone[c] == adj[q]) break; 407 } 408 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 409 } 410 } 411 } 412 *adjSize = numAdj; 413 PetscFunctionReturn(0); 414 } 415 416 #undef __FUNCT__ 417 #define __FUNCT__ "DMPlexGetAdjacency_Private" 418 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 419 { 420 const PetscInt *star = tmpClosure; 421 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 422 PetscErrorCode ierr; 423 424 PetscFunctionBegin; 425 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 426 for (s = 2; s < starSize*2; s += 2) { 427 const PetscInt *closure = NULL; 428 PetscInt closureSize, c, q; 429 430 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 431 for (c = 0; c < closureSize*2; c += 2) { 432 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 433 if (closure[c] == adj[q]) break; 434 } 435 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 436 } 437 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 438 } 439 *adjSize = numAdj; 440 PetscFunctionReturn(0); 441 } 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 445 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 446 { 447 DM_Plex *mesh = (DM_Plex*) dm->data; 448 449 PetscFunctionBegin; 450 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 451 mesh->preallocCenterDim = preallocCenterDim; 452 PetscFunctionReturn(0); 453 } 454 455 #undef __FUNCT__ 456 #define __FUNCT__ "DMPlexPreallocateOperator" 457 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 458 { 459 DM_Plex *mesh = (DM_Plex*) dm->data; 460 MPI_Comm comm; 461 PetscSF sf, sfDof, sfAdj; 462 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 463 PetscInt nleaves, l, p; 464 const PetscInt *leaves; 465 const PetscSFNode *remotes; 466 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 467 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 468 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 469 PetscLayout rLayout; 470 PetscInt locRows, rStart, rEnd, r; 471 PetscMPIInt size; 472 PetscBool useClosure, debug = PETSC_FALSE; 473 PetscErrorCode ierr; 474 475 PetscFunctionBegin; 476 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 477 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 478 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 479 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 480 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 481 /* Create dof SF based on point SF */ 482 if (debug) { 483 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 484 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 485 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 486 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 487 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 488 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 489 } 490 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 491 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 492 if (debug) { 493 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 494 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 495 } 496 /* Create section for dof adjacency (dof ==> # adj dof) */ 497 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 498 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 499 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 500 if (mesh->preallocCenterDim == dim) { 501 useClosure = PETSC_FALSE; 502 } else if (mesh->preallocCenterDim == 0) { 503 useClosure = PETSC_TRUE; 504 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 505 506 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 507 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 508 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 509 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 510 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 511 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 512 /* Fill in the ghost dofs on the interface */ 513 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 514 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 515 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 516 517 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 518 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 519 520 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 521 522 /* 523 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 524 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 525 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 526 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 527 Create sfAdj connecting rootSectionAdj and leafSectionAdj 528 3. Visit unowned points on interface, write adjacencies to adj 529 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 530 4. Visit owned points on interface, write adjacencies to rootAdj 531 Remove redundancy in rootAdj 532 ** The last two traversals use transitive closure 533 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 534 Allocate memory addressed by sectionAdj (cols) 535 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 536 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 537 */ 538 539 for (l = 0; l < nleaves; ++l) { 540 PetscInt dof, off, d, q; 541 PetscInt p = leaves[l], numAdj = maxAdjSize; 542 543 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 544 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 545 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 546 for (q = 0; q < numAdj; ++q) { 547 const PetscInt padj = tmpAdj[q]; 548 PetscInt ndof, ncdof; 549 550 if ((padj < pStart) || (padj >= pEnd)) continue; 551 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 552 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 553 for (d = off; d < off+dof; ++d) { 554 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 555 } 556 } 557 } 558 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 559 if (debug) { 560 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 561 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 562 } 563 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 564 if (size > 1) { 565 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 566 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 567 } 568 if (debug) { 569 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 570 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 571 } 572 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 573 for (p = pStart; p < pEnd; ++p) { 574 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 575 576 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 577 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 578 if (!dof) continue; 579 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 580 if (adof <= 0) continue; 581 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 582 for (q = 0; q < numAdj; ++q) { 583 const PetscInt padj = tmpAdj[q]; 584 PetscInt ndof, ncdof; 585 586 if ((padj < pStart) || (padj >= pEnd)) continue; 587 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 588 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 589 for (d = off; d < off+dof; ++d) { 590 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 591 } 592 } 593 } 594 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 595 if (debug) { 596 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 597 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 598 } 599 /* Create adj SF based on dof SF */ 600 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 601 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 602 if (debug) { 603 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 604 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 605 } 606 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 607 /* Create leaf adjacency */ 608 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 609 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 610 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 611 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 612 for (l = 0; l < nleaves; ++l) { 613 PetscInt dof, off, d, q; 614 PetscInt p = leaves[l], numAdj = maxAdjSize; 615 616 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 617 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 618 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 619 for (d = off; d < off+dof; ++d) { 620 PetscInt aoff, i = 0; 621 622 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 623 for (q = 0; q < numAdj; ++q) { 624 const PetscInt padj = tmpAdj[q]; 625 PetscInt ndof, ncdof, ngoff, nd; 626 627 if ((padj < pStart) || (padj >= pEnd)) continue; 628 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 629 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 630 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 631 for (nd = 0; nd < ndof-ncdof; ++nd) { 632 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 633 ++i; 634 } 635 } 636 } 637 } 638 /* Debugging */ 639 if (debug) { 640 IS tmp; 641 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 642 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 643 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 644 } 645 /* Gather adjacenct indices to root */ 646 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 647 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 648 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 649 if (size > 1) { 650 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 651 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 652 } 653 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 654 ierr = PetscFree(adj);CHKERRQ(ierr); 655 /* Debugging */ 656 if (debug) { 657 IS tmp; 658 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 659 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 660 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 661 } 662 /* Add in local adjacency indices for owned dofs on interface (roots) */ 663 for (p = pStart; p < pEnd; ++p) { 664 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 665 666 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 667 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 668 if (!dof) continue; 669 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 670 if (adof <= 0) continue; 671 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 672 for (d = off; d < off+dof; ++d) { 673 PetscInt adof, aoff, i; 674 675 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 676 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 677 i = adof-1; 678 for (q = 0; q < numAdj; ++q) { 679 const PetscInt padj = tmpAdj[q]; 680 PetscInt ndof, ncdof, ngoff, nd; 681 682 if ((padj < pStart) || (padj >= pEnd)) continue; 683 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 684 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 685 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 686 for (nd = 0; nd < ndof-ncdof; ++nd) { 687 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 688 --i; 689 } 690 } 691 } 692 } 693 /* Debugging */ 694 if (debug) { 695 IS tmp; 696 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 697 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 698 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 699 } 700 /* Compress indices */ 701 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 702 for (p = pStart; p < pEnd; ++p) { 703 PetscInt dof, cdof, off, d; 704 PetscInt adof, aoff; 705 706 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 707 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 708 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 709 if (!dof) continue; 710 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 711 if (adof <= 0) continue; 712 for (d = off; d < off+dof-cdof; ++d) { 713 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 714 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 715 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 716 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 717 } 718 } 719 /* Debugging */ 720 if (debug) { 721 IS tmp; 722 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 723 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 724 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 725 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 726 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 727 } 728 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 729 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 730 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 731 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 732 for (p = pStart; p < pEnd; ++p) { 733 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 734 PetscBool found = PETSC_TRUE; 735 736 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 737 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 738 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 739 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 740 for (d = 0; d < dof-cdof; ++d) { 741 PetscInt ldof, rdof; 742 743 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 744 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 745 if (ldof > 0) { 746 /* We do not own this point */ 747 } else if (rdof > 0) { 748 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 749 } else { 750 found = PETSC_FALSE; 751 } 752 } 753 if (found) continue; 754 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 755 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 756 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 757 for (q = 0; q < numAdj; ++q) { 758 const PetscInt padj = tmpAdj[q]; 759 PetscInt ndof, ncdof, noff; 760 761 if ((padj < pStart) || (padj >= pEnd)) continue; 762 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 763 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 764 ierr = PetscSectionGetOffset(section, padj, &noff);CHKERRQ(ierr); 765 for (d = goff; d < goff+dof-cdof; ++d) { 766 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 767 } 768 } 769 } 770 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 771 if (debug) { 772 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 773 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 774 } 775 /* Get adjacent indices */ 776 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 777 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 778 for (p = pStart; p < pEnd; ++p) { 779 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 780 PetscBool found = PETSC_TRUE; 781 782 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 783 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 784 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 785 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 786 for (d = 0; d < dof-cdof; ++d) { 787 PetscInt ldof, rdof; 788 789 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 790 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 791 if (ldof > 0) { 792 /* We do not own this point */ 793 } else if (rdof > 0) { 794 PetscInt aoff, roff; 795 796 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 797 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 798 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 799 } else { 800 found = PETSC_FALSE; 801 } 802 } 803 if (found) continue; 804 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 805 for (d = goff; d < goff+dof-cdof; ++d) { 806 PetscInt adof, aoff, i = 0; 807 808 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 809 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 810 for (q = 0; q < numAdj; ++q) { 811 const PetscInt padj = tmpAdj[q]; 812 PetscInt ndof, ncdof, ngoff, nd; 813 const PetscInt *ncind; 814 815 /* Adjacent points may not be in the section chart */ 816 if ((padj < pStart) || (padj >= pEnd)) continue; 817 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 818 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 819 ierr = PetscSectionGetConstraintIndices(section, padj, &ncind);CHKERRQ(ierr); 820 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 821 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 822 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 823 } 824 } 825 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); 826 } 827 } 828 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 829 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 830 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 831 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 832 /* Debugging */ 833 if (debug) { 834 IS tmp; 835 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 836 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 837 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 838 } 839 /* Create allocation vectors from adjacency graph */ 840 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 841 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr); 842 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 843 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 844 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 845 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 846 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 847 /* Only loop over blocks of rows */ 848 if (rStart%bs || rEnd%bs) SETERRQ3(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 849 for (r = rStart/bs; r < rEnd/bs; ++r) { 850 const PetscInt row = r*bs; 851 PetscInt numCols, cStart, c; 852 853 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 854 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 855 for (c = cStart; c < cStart+numCols; ++c) { 856 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 857 ++dnz[r-rStart]; 858 if (cols[c] >= row) ++dnzu[r-rStart]; 859 } else { 860 ++onz[r-rStart]; 861 if (cols[c] >= row) ++onzu[r-rStart]; 862 } 863 } 864 } 865 if (bs > 1) { 866 for (r = 0; r < locRows/bs; ++r) { 867 dnz[r] /= bs; 868 onz[r] /= bs; 869 dnzu[r] /= bs; 870 onzu[r] /= bs; 871 } 872 } 873 /* Set matrix pattern */ 874 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 875 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 876 /* Fill matrix with zeros */ 877 if (fillMatrix) { 878 PetscScalar *values; 879 PetscInt maxRowLen = 0; 880 881 for (r = rStart; r < rEnd; ++r) { 882 PetscInt len; 883 884 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 885 maxRowLen = PetscMax(maxRowLen, len); 886 } 887 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 888 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 889 for (r = rStart; r < rEnd; ++r) { 890 PetscInt numCols, cStart; 891 892 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 893 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 894 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 895 } 896 ierr = PetscFree(values);CHKERRQ(ierr); 897 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 898 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 899 } 900 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 901 ierr = PetscFree(cols);CHKERRQ(ierr); 902 PetscFunctionReturn(0); 903 } 904 905 #if 0 906 #undef __FUNCT__ 907 #define __FUNCT__ "DMPlexPreallocateOperator_2" 908 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 909 { 910 PetscInt *tmpClosure,*tmpAdj,*visits; 911 PetscInt c,cStart,cEnd,pStart,pEnd; 912 PetscErrorCode ierr; 913 914 PetscFunctionBegin; 915 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 916 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 917 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 918 919 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 920 921 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 922 npoints = pEnd - pStart; 923 924 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 925 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 926 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 927 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 928 for (c=cStart; c<cEnd; c++) { 929 PetscInt *support = tmpClosure; 930 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 931 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 932 } 933 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 934 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 935 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 936 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 937 938 ierr = PetscSFGetRanks();CHKERRQ(ierr); 939 940 941 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 942 for (c=cStart; c<cEnd; c++) { 943 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 944 /* 945 Depth-first walk of transitive closure. 946 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. 947 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 948 */ 949 } 950 951 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 952 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 953 PetscFunctionReturn(0); 954 } 955 #endif 956 957 #undef __FUNCT__ 958 #define __FUNCT__ "DMCreateMatrix_Plex" 959 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 960 { 961 PetscSection section, sectionGlobal; 962 PetscInt bs = -1; 963 PetscInt localSize; 964 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 965 PetscErrorCode ierr; 966 967 PetscFunctionBegin; 968 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 969 ierr = MatInitializePackage(NULL);CHKERRQ(ierr); 970 #endif 971 if (!mtype) mtype = MATAIJ; 972 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 973 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 974 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 975 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 976 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 977 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 978 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 979 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 980 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 981 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 982 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 983 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 984 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 985 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 986 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 987 /* Check for symmetric storage */ 988 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 989 if (isSymmetric) { 990 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 991 } 992 if (!isShell) { 993 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 994 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 995 996 if (bs < 0) { 997 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 998 PetscInt pStart, pEnd, p, dof, cdof; 999 1000 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1001 for (p = pStart; p < pEnd; ++p) { 1002 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1003 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 1004 if (dof-cdof) { 1005 if (bs < 0) { 1006 bs = dof-cdof; 1007 } else if (bs != dof-cdof) { 1008 /* Layout does not admit a pointwise block size */ 1009 bs = 1; 1010 break; 1011 } 1012 } 1013 } 1014 /* Must have same blocksize on all procs (some might have no points) */ 1015 bsLocal = bs; 1016 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1017 bsLocal = bs < 0 ? bsMax : bs; 1018 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1019 if (bsMin != bsMax) { 1020 bs = 1; 1021 } else { 1022 bs = bsMax; 1023 } 1024 } else { 1025 bs = 1; 1026 } 1027 } 1028 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1029 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1030 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1031 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1032 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1033 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1034 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1035 } 1036 PetscFunctionReturn(0); 1037 } 1038 1039 #undef __FUNCT__ 1040 #define __FUNCT__ "DMPlexGetDimension" 1041 /*@ 1042 DMPlexGetDimension - Return the topological mesh dimension 1043 1044 Not collective 1045 1046 Input Parameter: 1047 . mesh - The DMPlex 1048 1049 Output Parameter: 1050 . dim - The topological mesh dimension 1051 1052 Level: beginner 1053 1054 .seealso: DMPlexCreate() 1055 @*/ 1056 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1057 { 1058 DM_Plex *mesh = (DM_Plex*) dm->data; 1059 1060 PetscFunctionBegin; 1061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1062 PetscValidPointer(dim, 2); 1063 *dim = mesh->dim; 1064 PetscFunctionReturn(0); 1065 } 1066 1067 #undef __FUNCT__ 1068 #define __FUNCT__ "DMPlexSetDimension" 1069 /*@ 1070 DMPlexSetDimension - Set the topological mesh dimension 1071 1072 Collective on mesh 1073 1074 Input Parameters: 1075 + mesh - The DMPlex 1076 - dim - The topological mesh dimension 1077 1078 Level: beginner 1079 1080 .seealso: DMPlexCreate() 1081 @*/ 1082 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1083 { 1084 DM_Plex *mesh = (DM_Plex*) dm->data; 1085 1086 PetscFunctionBegin; 1087 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1088 PetscValidLogicalCollectiveInt(dm, dim, 2); 1089 mesh->dim = dim; 1090 mesh->preallocCenterDim = dim; 1091 PetscFunctionReturn(0); 1092 } 1093 1094 #undef __FUNCT__ 1095 #define __FUNCT__ "DMPlexGetChart" 1096 /*@ 1097 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1098 1099 Not collective 1100 1101 Input Parameter: 1102 . mesh - The DMPlex 1103 1104 Output Parameters: 1105 + pStart - The first mesh point 1106 - pEnd - The upper bound for mesh points 1107 1108 Level: beginner 1109 1110 .seealso: DMPlexCreate(), DMPlexSetChart() 1111 @*/ 1112 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1113 { 1114 DM_Plex *mesh = (DM_Plex*) dm->data; 1115 PetscErrorCode ierr; 1116 1117 PetscFunctionBegin; 1118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1119 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1120 PetscFunctionReturn(0); 1121 } 1122 1123 #undef __FUNCT__ 1124 #define __FUNCT__ "DMPlexSetChart" 1125 /*@ 1126 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1127 1128 Not collective 1129 1130 Input Parameters: 1131 + mesh - The DMPlex 1132 . pStart - The first mesh point 1133 - pEnd - The upper bound for mesh points 1134 1135 Output Parameters: 1136 1137 Level: beginner 1138 1139 .seealso: DMPlexCreate(), DMPlexGetChart() 1140 @*/ 1141 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1142 { 1143 DM_Plex *mesh = (DM_Plex*) dm->data; 1144 PetscErrorCode ierr; 1145 1146 PetscFunctionBegin; 1147 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1148 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1149 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1150 PetscFunctionReturn(0); 1151 } 1152 1153 #undef __FUNCT__ 1154 #define __FUNCT__ "DMPlexGetConeSize" 1155 /*@ 1156 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1157 1158 Not collective 1159 1160 Input Parameters: 1161 + mesh - The DMPlex 1162 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1163 1164 Output Parameter: 1165 . size - The cone size for point p 1166 1167 Level: beginner 1168 1169 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1170 @*/ 1171 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1172 { 1173 DM_Plex *mesh = (DM_Plex*) dm->data; 1174 PetscErrorCode ierr; 1175 1176 PetscFunctionBegin; 1177 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1178 PetscValidPointer(size, 3); 1179 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1180 PetscFunctionReturn(0); 1181 } 1182 1183 #undef __FUNCT__ 1184 #define __FUNCT__ "DMPlexSetConeSize" 1185 /*@ 1186 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1187 1188 Not collective 1189 1190 Input Parameters: 1191 + mesh - The DMPlex 1192 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1193 - size - The cone size for point p 1194 1195 Output Parameter: 1196 1197 Note: 1198 This should be called after DMPlexSetChart(). 1199 1200 Level: beginner 1201 1202 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1203 @*/ 1204 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1205 { 1206 DM_Plex *mesh = (DM_Plex*) dm->data; 1207 PetscErrorCode ierr; 1208 1209 PetscFunctionBegin; 1210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1211 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1212 1213 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1214 PetscFunctionReturn(0); 1215 } 1216 1217 #undef __FUNCT__ 1218 #define __FUNCT__ "DMPlexGetCone" 1219 /*@C 1220 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1221 1222 Not collective 1223 1224 Input Parameters: 1225 + mesh - The DMPlex 1226 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1227 1228 Output Parameter: 1229 . cone - An array of points which are on the in-edges for point p 1230 1231 Level: beginner 1232 1233 Note: 1234 This routine is not available in Fortran. 1235 1236 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1237 @*/ 1238 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1239 { 1240 DM_Plex *mesh = (DM_Plex*) dm->data; 1241 PetscInt off; 1242 PetscErrorCode ierr; 1243 1244 PetscFunctionBegin; 1245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1246 PetscValidPointer(cone, 3); 1247 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1248 *cone = &mesh->cones[off]; 1249 PetscFunctionReturn(0); 1250 } 1251 1252 #undef __FUNCT__ 1253 #define __FUNCT__ "DMPlexSetCone" 1254 /*@ 1255 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1256 1257 Not collective 1258 1259 Input Parameters: 1260 + mesh - The DMPlex 1261 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1262 - cone - An array of points which are on the in-edges for point p 1263 1264 Output Parameter: 1265 1266 Note: 1267 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1268 1269 Level: beginner 1270 1271 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1272 @*/ 1273 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1274 { 1275 DM_Plex *mesh = (DM_Plex*) dm->data; 1276 PetscInt pStart, pEnd; 1277 PetscInt dof, off, c; 1278 PetscErrorCode ierr; 1279 1280 PetscFunctionBegin; 1281 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1282 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1283 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1284 if (dof) PetscValidPointer(cone, 3); 1285 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1286 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1287 for (c = 0; c < dof; ++c) { 1288 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1289 mesh->cones[off+c] = cone[c]; 1290 } 1291 PetscFunctionReturn(0); 1292 } 1293 1294 #undef __FUNCT__ 1295 #define __FUNCT__ "DMPlexGetConeOrientation" 1296 /*@C 1297 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1298 1299 Not collective 1300 1301 Input Parameters: 1302 + mesh - The DMPlex 1303 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1304 1305 Output Parameter: 1306 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1307 integer giving the prescription for cone traversal. If it is negative, the cone is 1308 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1309 the index of the cone point on which to start. 1310 1311 Level: beginner 1312 1313 Note: 1314 This routine is not available in Fortran. 1315 1316 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1317 @*/ 1318 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1319 { 1320 DM_Plex *mesh = (DM_Plex*) dm->data; 1321 PetscInt off; 1322 PetscErrorCode ierr; 1323 1324 PetscFunctionBegin; 1325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1326 #if defined(PETSC_USE_DEBUG) 1327 { 1328 PetscInt dof; 1329 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1330 if (dof) PetscValidPointer(coneOrientation, 3); 1331 } 1332 #endif 1333 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1334 1335 *coneOrientation = &mesh->coneOrientations[off]; 1336 PetscFunctionReturn(0); 1337 } 1338 1339 #undef __FUNCT__ 1340 #define __FUNCT__ "DMPlexSetConeOrientation" 1341 /*@ 1342 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1343 1344 Not collective 1345 1346 Input Parameters: 1347 + mesh - The DMPlex 1348 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1349 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1350 integer giving the prescription for cone traversal. If it is negative, the cone is 1351 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1352 the index of the cone point on which to start. 1353 1354 Output Parameter: 1355 1356 Note: 1357 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1358 1359 Level: beginner 1360 1361 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1362 @*/ 1363 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1364 { 1365 DM_Plex *mesh = (DM_Plex*) dm->data; 1366 PetscInt pStart, pEnd; 1367 PetscInt dof, off, c; 1368 PetscErrorCode ierr; 1369 1370 PetscFunctionBegin; 1371 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1372 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1373 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1374 if (dof) PetscValidPointer(coneOrientation, 3); 1375 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1376 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1377 for (c = 0; c < dof; ++c) { 1378 PetscInt cdof, o = coneOrientation[c]; 1379 1380 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1381 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1382 mesh->coneOrientations[off+c] = o; 1383 } 1384 PetscFunctionReturn(0); 1385 } 1386 1387 #undef __FUNCT__ 1388 #define __FUNCT__ "DMPlexInsertCone" 1389 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1390 { 1391 DM_Plex *mesh = (DM_Plex*) dm->data; 1392 PetscInt pStart, pEnd; 1393 PetscInt dof, off; 1394 PetscErrorCode ierr; 1395 1396 PetscFunctionBegin; 1397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1398 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1399 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1400 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1401 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1402 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1403 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1404 mesh->cones[off+conePos] = conePoint; 1405 PetscFunctionReturn(0); 1406 } 1407 1408 #undef __FUNCT__ 1409 #define __FUNCT__ "DMPlexInsertConeOrientation" 1410 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 1411 { 1412 DM_Plex *mesh = (DM_Plex*) dm->data; 1413 PetscInt pStart, pEnd; 1414 PetscInt dof, off; 1415 PetscErrorCode ierr; 1416 1417 PetscFunctionBegin; 1418 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1419 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1420 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1421 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1422 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1423 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1424 mesh->coneOrientations[off+conePos] = coneOrientation; 1425 PetscFunctionReturn(0); 1426 } 1427 1428 #undef __FUNCT__ 1429 #define __FUNCT__ "DMPlexGetSupportSize" 1430 /*@ 1431 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1432 1433 Not collective 1434 1435 Input Parameters: 1436 + mesh - The DMPlex 1437 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1438 1439 Output Parameter: 1440 . size - The support size for point p 1441 1442 Level: beginner 1443 1444 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1445 @*/ 1446 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1447 { 1448 DM_Plex *mesh = (DM_Plex*) dm->data; 1449 PetscErrorCode ierr; 1450 1451 PetscFunctionBegin; 1452 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1453 PetscValidPointer(size, 3); 1454 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1455 PetscFunctionReturn(0); 1456 } 1457 1458 #undef __FUNCT__ 1459 #define __FUNCT__ "DMPlexSetSupportSize" 1460 /*@ 1461 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1462 1463 Not collective 1464 1465 Input Parameters: 1466 + mesh - The DMPlex 1467 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1468 - size - The support size for point p 1469 1470 Output Parameter: 1471 1472 Note: 1473 This should be called after DMPlexSetChart(). 1474 1475 Level: beginner 1476 1477 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1478 @*/ 1479 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1480 { 1481 DM_Plex *mesh = (DM_Plex*) dm->data; 1482 PetscErrorCode ierr; 1483 1484 PetscFunctionBegin; 1485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1486 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1487 1488 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1489 PetscFunctionReturn(0); 1490 } 1491 1492 #undef __FUNCT__ 1493 #define __FUNCT__ "DMPlexGetSupport" 1494 /*@C 1495 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1496 1497 Not collective 1498 1499 Input Parameters: 1500 + mesh - The DMPlex 1501 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1502 1503 Output Parameter: 1504 . support - An array of points which are on the out-edges for point p 1505 1506 Level: beginner 1507 1508 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1509 @*/ 1510 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1511 { 1512 DM_Plex *mesh = (DM_Plex*) dm->data; 1513 PetscInt off; 1514 PetscErrorCode ierr; 1515 1516 PetscFunctionBegin; 1517 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1518 PetscValidPointer(support, 3); 1519 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1520 *support = &mesh->supports[off]; 1521 PetscFunctionReturn(0); 1522 } 1523 1524 #undef __FUNCT__ 1525 #define __FUNCT__ "DMPlexSetSupport" 1526 /*@ 1527 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1528 1529 Not collective 1530 1531 Input Parameters: 1532 + mesh - The DMPlex 1533 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1534 - support - An array of points which are on the in-edges for point p 1535 1536 Output Parameter: 1537 1538 Note: 1539 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1540 1541 Level: beginner 1542 1543 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1544 @*/ 1545 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1546 { 1547 DM_Plex *mesh = (DM_Plex*) dm->data; 1548 PetscInt pStart, pEnd; 1549 PetscInt dof, off, c; 1550 PetscErrorCode ierr; 1551 1552 PetscFunctionBegin; 1553 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1554 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1555 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1556 if (dof) PetscValidPointer(support, 3); 1557 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1558 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1559 for (c = 0; c < dof; ++c) { 1560 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1561 mesh->supports[off+c] = support[c]; 1562 } 1563 PetscFunctionReturn(0); 1564 } 1565 1566 #undef __FUNCT__ 1567 #define __FUNCT__ "DMPlexInsertSupport" 1568 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1569 { 1570 DM_Plex *mesh = (DM_Plex*) dm->data; 1571 PetscInt pStart, pEnd; 1572 PetscInt dof, off; 1573 PetscErrorCode ierr; 1574 1575 PetscFunctionBegin; 1576 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1577 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1578 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1579 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1580 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1581 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1582 if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1583 mesh->supports[off+supportPos] = supportPoint; 1584 PetscFunctionReturn(0); 1585 } 1586 1587 #undef __FUNCT__ 1588 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1589 /*@C 1590 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1591 1592 Not collective 1593 1594 Input Parameters: 1595 + mesh - The DMPlex 1596 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1597 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1598 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1599 1600 Output Parameters: 1601 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1602 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1603 1604 Note: 1605 If using internal storage (points is NULL on input), each call overwrites the last output. 1606 1607 Level: beginner 1608 1609 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1610 @*/ 1611 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1612 { 1613 DM_Plex *mesh = (DM_Plex*) dm->data; 1614 PetscInt *closure, *fifo; 1615 const PetscInt *tmp = NULL, *tmpO = NULL; 1616 PetscInt tmpSize, t; 1617 PetscInt depth = 0, maxSize; 1618 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1619 PetscErrorCode ierr; 1620 1621 PetscFunctionBegin; 1622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1623 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1624 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1625 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1626 if (*points) { 1627 closure = *points; 1628 } else { 1629 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1630 } 1631 closure[0] = p; closure[1] = 0; 1632 /* This is only 1-level */ 1633 if (useCone) { 1634 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1635 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1636 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1637 } else { 1638 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1639 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1640 } 1641 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1642 const PetscInt cp = tmp[t]; 1643 const PetscInt co = tmpO ? tmpO[t] : 0; 1644 1645 closure[closureSize] = cp; 1646 closure[closureSize+1] = co; 1647 fifo[fifoSize] = cp; 1648 fifo[fifoSize+1] = co; 1649 } 1650 while (fifoSize - fifoStart) { 1651 const PetscInt q = fifo[fifoStart]; 1652 const PetscInt o = fifo[fifoStart+1]; 1653 const PetscInt rev = o >= 0 ? 0 : 1; 1654 const PetscInt off = rev ? -(o+1) : o; 1655 1656 if (useCone) { 1657 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1658 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1659 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1660 } else { 1661 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1662 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1663 tmpO = NULL; 1664 } 1665 for (t = 0; t < tmpSize; ++t) { 1666 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1667 const PetscInt cp = tmp[i]; 1668 /* Must propogate orientation */ 1669 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1670 PetscInt c; 1671 1672 /* Check for duplicate */ 1673 for (c = 0; c < closureSize; c += 2) { 1674 if (closure[c] == cp) break; 1675 } 1676 if (c == closureSize) { 1677 closure[closureSize] = cp; 1678 closure[closureSize+1] = co; 1679 fifo[fifoSize] = cp; 1680 fifo[fifoSize+1] = co; 1681 closureSize += 2; 1682 fifoSize += 2; 1683 } 1684 } 1685 fifoStart += 2; 1686 } 1687 if (numPoints) *numPoints = closureSize/2; 1688 if (points) *points = closure; 1689 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1690 PetscFunctionReturn(0); 1691 } 1692 1693 #undef __FUNCT__ 1694 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1695 /*@C 1696 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1697 1698 Not collective 1699 1700 Input Parameters: 1701 + mesh - The DMPlex 1702 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1703 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1704 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1705 1706 Output Parameters: 1707 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1708 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1709 1710 Note: 1711 If not using internal storage (points is not NULL on input), this call is unnecessary 1712 1713 Level: beginner 1714 1715 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1716 @*/ 1717 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1718 { 1719 PetscErrorCode ierr; 1720 1721 PetscFunctionBegin; 1722 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1723 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1724 PetscFunctionReturn(0); 1725 } 1726 1727 #undef __FUNCT__ 1728 #define __FUNCT__ "DMPlexGetMaxSizes" 1729 /*@ 1730 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1731 1732 Not collective 1733 1734 Input Parameter: 1735 . mesh - The DMPlex 1736 1737 Output Parameters: 1738 + maxConeSize - The maximum number of in-edges 1739 - maxSupportSize - The maximum number of out-edges 1740 1741 Level: beginner 1742 1743 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1744 @*/ 1745 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1746 { 1747 DM_Plex *mesh = (DM_Plex*) dm->data; 1748 1749 PetscFunctionBegin; 1750 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1751 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1752 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1753 PetscFunctionReturn(0); 1754 } 1755 1756 #undef __FUNCT__ 1757 #define __FUNCT__ "DMSetUp_Plex" 1758 PetscErrorCode DMSetUp_Plex(DM dm) 1759 { 1760 DM_Plex *mesh = (DM_Plex*) dm->data; 1761 PetscInt size; 1762 PetscErrorCode ierr; 1763 1764 PetscFunctionBegin; 1765 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1766 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1767 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1768 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1769 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1770 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1771 if (mesh->maxSupportSize) { 1772 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1773 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1774 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1775 } 1776 PetscFunctionReturn(0); 1777 } 1778 1779 #undef __FUNCT__ 1780 #define __FUNCT__ "DMCreateSubDM_Plex" 1781 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1782 { 1783 PetscSection section, sectionGlobal; 1784 PetscInt *subIndices; 1785 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1786 PetscErrorCode ierr; 1787 1788 PetscFunctionBegin; 1789 if (!numFields) PetscFunctionReturn(0); 1790 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1791 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1792 if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1793 if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1794 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1795 if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1796 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1797 for (p = pStart; p < pEnd; ++p) { 1798 PetscInt gdof; 1799 1800 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1801 if (gdof > 0) { 1802 for (f = 0; f < numFields; ++f) { 1803 PetscInt fdof, fcdof; 1804 1805 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1806 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1807 subSize += fdof-fcdof; 1808 } 1809 } 1810 } 1811 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1812 for (p = pStart; p < pEnd; ++p) { 1813 PetscInt gdof, goff; 1814 1815 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1816 if (gdof > 0) { 1817 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1818 for (f = 0; f < numFields; ++f) { 1819 PetscInt fdof, fcdof, fc, f2, poff = 0; 1820 1821 /* Can get rid of this loop by storing field information in the global section */ 1822 for (f2 = 0; f2 < fields[f]; ++f2) { 1823 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1824 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1825 poff += fdof-fcdof; 1826 } 1827 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1828 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1829 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1830 subIndices[subOff] = goff+poff+fc; 1831 } 1832 } 1833 } 1834 } 1835 if (is) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1836 if (subdm) { 1837 PetscSection subsection; 1838 PetscBool haveNull = PETSC_FALSE; 1839 PetscInt f, nf = 0; 1840 1841 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1842 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1843 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1844 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 1845 for (f = 0; f < numFields; ++f) { 1846 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1847 if ((*subdm)->nullspaceConstructors[f]) { 1848 haveNull = PETSC_TRUE; 1849 nf = f; 1850 } 1851 } 1852 if (haveNull) { 1853 MatNullSpace nullSpace; 1854 1855 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1856 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1857 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1858 } 1859 if (dm->fields) { 1860 if (nF != dm->numFields) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1861 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1862 for (f = 0; f < numFields; ++f) { 1863 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1864 } 1865 if (numFields == 1) { 1866 MatNullSpace space; 1867 Mat pmat; 1868 1869 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1870 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1871 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1872 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1873 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1874 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1875 } 1876 } 1877 } 1878 PetscFunctionReturn(0); 1879 } 1880 1881 #undef __FUNCT__ 1882 #define __FUNCT__ "DMPlexSymmetrize" 1883 /*@ 1884 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1885 1886 Not collective 1887 1888 Input Parameter: 1889 . mesh - The DMPlex 1890 1891 Output Parameter: 1892 1893 Note: 1894 This should be called after all calls to DMPlexSetCone() 1895 1896 Level: beginner 1897 1898 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1899 @*/ 1900 PetscErrorCode DMPlexSymmetrize(DM dm) 1901 { 1902 DM_Plex *mesh = (DM_Plex*) dm->data; 1903 PetscInt *offsets; 1904 PetscInt supportSize; 1905 PetscInt pStart, pEnd, p; 1906 PetscErrorCode ierr; 1907 1908 PetscFunctionBegin; 1909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1910 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1911 /* Calculate support sizes */ 1912 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1913 for (p = pStart; p < pEnd; ++p) { 1914 PetscInt dof, off, c; 1915 1916 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1917 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1918 for (c = off; c < off+dof; ++c) { 1919 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1920 } 1921 } 1922 for (p = pStart; p < pEnd; ++p) { 1923 PetscInt dof; 1924 1925 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1926 1927 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1928 } 1929 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1930 /* Calculate supports */ 1931 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1932 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1933 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1934 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1935 for (p = pStart; p < pEnd; ++p) { 1936 PetscInt dof, off, c; 1937 1938 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1939 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1940 for (c = off; c < off+dof; ++c) { 1941 const PetscInt q = mesh->cones[c]; 1942 PetscInt offS; 1943 1944 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1945 1946 mesh->supports[offS+offsets[q]] = p; 1947 ++offsets[q]; 1948 } 1949 } 1950 ierr = PetscFree(offsets);CHKERRQ(ierr); 1951 PetscFunctionReturn(0); 1952 } 1953 1954 #undef __FUNCT__ 1955 #define __FUNCT__ "DMPlexSetDepth_Private" 1956 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1957 { 1958 PetscInt d; 1959 PetscErrorCode ierr; 1960 1961 PetscFunctionBegin; 1962 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1963 if (d < 0) { 1964 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1965 const PetscInt *cone = NULL; 1966 PetscInt dCone; 1967 1968 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1969 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1970 d = dCone+1; 1971 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1972 } 1973 *depth = d; 1974 PetscFunctionReturn(0); 1975 } 1976 1977 #undef __FUNCT__ 1978 #define __FUNCT__ "DMPlexStratify" 1979 /*@ 1980 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 1981 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 1982 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 1983 the DAG. 1984 1985 Not collective 1986 1987 Input Parameter: 1988 . mesh - The DMPlex 1989 1990 Output Parameter: 1991 1992 Notes: 1993 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 1994 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 1995 1996 This should be called after all calls to DMPlexSymmetrize() 1997 1998 Level: beginner 1999 2000 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2001 @*/ 2002 PetscErrorCode DMPlexStratify(DM dm) 2003 { 2004 DM_Plex *mesh = (DM_Plex*) dm->data; 2005 PetscInt pStart, pEnd, p; 2006 PetscInt numRoots = 0, numLeaves = 0; 2007 PetscErrorCode ierr; 2008 2009 PetscFunctionBegin; 2010 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2011 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2012 /* Calculate depth */ 2013 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2014 /* Initialize roots and count leaves */ 2015 for (p = pStart; p < pEnd; ++p) { 2016 PetscInt coneSize, supportSize; 2017 2018 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2019 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2020 if (!coneSize && supportSize) { 2021 ++numRoots; 2022 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2023 } else if (!supportSize && coneSize) { 2024 ++numLeaves; 2025 } else if (!supportSize && !coneSize) { 2026 /* Isolated points */ 2027 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2028 } 2029 } 2030 if (numRoots + numLeaves == (pEnd - pStart)) { 2031 for (p = pStart; p < pEnd; ++p) { 2032 PetscInt coneSize, supportSize; 2033 2034 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2035 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2036 if (!supportSize && coneSize) { 2037 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2038 } 2039 } 2040 } else { 2041 /* This might be slow since lookup is not fast */ 2042 for (p = pStart; p < pEnd; ++p) { 2043 PetscInt depth; 2044 2045 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2046 } 2047 } 2048 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2049 PetscFunctionReturn(0); 2050 } 2051 2052 #undef __FUNCT__ 2053 #define __FUNCT__ "DMPlexGetJoin" 2054 /*@C 2055 DMPlexGetJoin - Get an array for the join of the set of points 2056 2057 Not Collective 2058 2059 Input Parameters: 2060 + dm - The DMPlex object 2061 . numPoints - The number of input points for the join 2062 - points - The input points 2063 2064 Output Parameters: 2065 + numCoveredPoints - The number of points in the join 2066 - coveredPoints - The points in the join 2067 2068 Level: intermediate 2069 2070 Note: Currently, this is restricted to a single level join 2071 2072 .keywords: mesh 2073 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2074 @*/ 2075 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2076 { 2077 DM_Plex *mesh = (DM_Plex*) dm->data; 2078 PetscInt *join[2]; 2079 PetscInt joinSize, i = 0; 2080 PetscInt dof, off, p, c, m; 2081 PetscErrorCode ierr; 2082 2083 PetscFunctionBegin; 2084 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2085 PetscValidPointer(points, 2); 2086 PetscValidPointer(numCoveredPoints, 3); 2087 PetscValidPointer(coveredPoints, 4); 2088 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2089 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2090 /* Copy in support of first point */ 2091 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2092 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2093 for (joinSize = 0; joinSize < dof; ++joinSize) { 2094 join[i][joinSize] = mesh->supports[off+joinSize]; 2095 } 2096 /* Check each successive support */ 2097 for (p = 1; p < numPoints; ++p) { 2098 PetscInt newJoinSize = 0; 2099 2100 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2101 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2102 for (c = 0; c < dof; ++c) { 2103 const PetscInt point = mesh->supports[off+c]; 2104 2105 for (m = 0; m < joinSize; ++m) { 2106 if (point == join[i][m]) { 2107 join[1-i][newJoinSize++] = point; 2108 break; 2109 } 2110 } 2111 } 2112 joinSize = newJoinSize; 2113 i = 1-i; 2114 } 2115 *numCoveredPoints = joinSize; 2116 *coveredPoints = join[i]; 2117 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2118 PetscFunctionReturn(0); 2119 } 2120 2121 #undef __FUNCT__ 2122 #define __FUNCT__ "DMPlexRestoreJoin" 2123 /*@C 2124 DMPlexRestoreJoin - Restore an array for the join of the set of points 2125 2126 Not Collective 2127 2128 Input Parameters: 2129 + dm - The DMPlex object 2130 . numPoints - The number of input points for the join 2131 - points - The input points 2132 2133 Output Parameters: 2134 + numCoveredPoints - The number of points in the join 2135 - coveredPoints - The points in the join 2136 2137 Level: intermediate 2138 2139 .keywords: mesh 2140 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2141 @*/ 2142 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2143 { 2144 PetscErrorCode ierr; 2145 2146 PetscFunctionBegin; 2147 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2148 PetscValidPointer(coveredPoints, 4); 2149 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2150 PetscFunctionReturn(0); 2151 } 2152 2153 #undef __FUNCT__ 2154 #define __FUNCT__ "DMPlexGetFullJoin" 2155 /*@C 2156 DMPlexGetFullJoin - Get an array for the join of the set of points 2157 2158 Not Collective 2159 2160 Input Parameters: 2161 + dm - The DMPlex object 2162 . numPoints - The number of input points for the join 2163 - points - The input points 2164 2165 Output Parameters: 2166 + numCoveredPoints - The number of points in the join 2167 - coveredPoints - The points in the join 2168 2169 Level: intermediate 2170 2171 .keywords: mesh 2172 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2173 @*/ 2174 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2175 { 2176 DM_Plex *mesh = (DM_Plex*) dm->data; 2177 PetscInt *offsets, **closures; 2178 PetscInt *join[2]; 2179 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2180 PetscInt p, d, c, m; 2181 PetscErrorCode ierr; 2182 2183 PetscFunctionBegin; 2184 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2185 PetscValidPointer(points, 2); 2186 PetscValidPointer(numCoveredPoints, 3); 2187 PetscValidPointer(coveredPoints, 4); 2188 2189 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2190 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2191 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2192 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2193 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2194 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2195 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2196 2197 for (p = 0; p < numPoints; ++p) { 2198 PetscInt closureSize; 2199 2200 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2201 2202 offsets[p*(depth+2)+0] = 0; 2203 for (d = 0; d < depth+1; ++d) { 2204 PetscInt pStart, pEnd, i; 2205 2206 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2207 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2208 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2209 offsets[p*(depth+2)+d+1] = i; 2210 break; 2211 } 2212 } 2213 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2214 } 2215 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2216 } 2217 for (d = 0; d < depth+1; ++d) { 2218 PetscInt dof; 2219 2220 /* Copy in support of first point */ 2221 dof = offsets[d+1] - offsets[d]; 2222 for (joinSize = 0; joinSize < dof; ++joinSize) { 2223 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2224 } 2225 /* Check each successive cone */ 2226 for (p = 1; p < numPoints && joinSize; ++p) { 2227 PetscInt newJoinSize = 0; 2228 2229 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2230 for (c = 0; c < dof; ++c) { 2231 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2232 2233 for (m = 0; m < joinSize; ++m) { 2234 if (point == join[i][m]) { 2235 join[1-i][newJoinSize++] = point; 2236 break; 2237 } 2238 } 2239 } 2240 joinSize = newJoinSize; 2241 i = 1-i; 2242 } 2243 if (joinSize) break; 2244 } 2245 *numCoveredPoints = joinSize; 2246 *coveredPoints = join[i]; 2247 for (p = 0; p < numPoints; ++p) { 2248 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2249 } 2250 ierr = PetscFree(closures);CHKERRQ(ierr); 2251 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2252 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2253 PetscFunctionReturn(0); 2254 } 2255 2256 #undef __FUNCT__ 2257 #define __FUNCT__ "DMPlexGetMeet" 2258 /*@C 2259 DMPlexGetMeet - Get an array for the meet of the set of points 2260 2261 Not Collective 2262 2263 Input Parameters: 2264 + dm - The DMPlex object 2265 . numPoints - The number of input points for the meet 2266 - points - The input points 2267 2268 Output Parameters: 2269 + numCoveredPoints - The number of points in the meet 2270 - coveredPoints - The points in the meet 2271 2272 Level: intermediate 2273 2274 Note: Currently, this is restricted to a single level meet 2275 2276 .keywords: mesh 2277 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2278 @*/ 2279 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2280 { 2281 DM_Plex *mesh = (DM_Plex*) dm->data; 2282 PetscInt *meet[2]; 2283 PetscInt meetSize, i = 0; 2284 PetscInt dof, off, p, c, m; 2285 PetscErrorCode ierr; 2286 2287 PetscFunctionBegin; 2288 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2289 PetscValidPointer(points, 2); 2290 PetscValidPointer(numCoveringPoints, 3); 2291 PetscValidPointer(coveringPoints, 4); 2292 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2293 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2294 /* Copy in cone of first point */ 2295 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2296 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2297 for (meetSize = 0; meetSize < dof; ++meetSize) { 2298 meet[i][meetSize] = mesh->cones[off+meetSize]; 2299 } 2300 /* Check each successive cone */ 2301 for (p = 1; p < numPoints; ++p) { 2302 PetscInt newMeetSize = 0; 2303 2304 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2305 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2306 for (c = 0; c < dof; ++c) { 2307 const PetscInt point = mesh->cones[off+c]; 2308 2309 for (m = 0; m < meetSize; ++m) { 2310 if (point == meet[i][m]) { 2311 meet[1-i][newMeetSize++] = point; 2312 break; 2313 } 2314 } 2315 } 2316 meetSize = newMeetSize; 2317 i = 1-i; 2318 } 2319 *numCoveringPoints = meetSize; 2320 *coveringPoints = meet[i]; 2321 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2322 PetscFunctionReturn(0); 2323 } 2324 2325 #undef __FUNCT__ 2326 #define __FUNCT__ "DMPlexRestoreMeet" 2327 /*@C 2328 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2329 2330 Not Collective 2331 2332 Input Parameters: 2333 + dm - The DMPlex object 2334 . numPoints - The number of input points for the meet 2335 - points - The input points 2336 2337 Output Parameters: 2338 + numCoveredPoints - The number of points in the meet 2339 - coveredPoints - The points in the meet 2340 2341 Level: intermediate 2342 2343 .keywords: mesh 2344 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2345 @*/ 2346 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2347 { 2348 PetscErrorCode ierr; 2349 2350 PetscFunctionBegin; 2351 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2352 PetscValidPointer(coveredPoints, 4); 2353 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2354 PetscFunctionReturn(0); 2355 } 2356 2357 #undef __FUNCT__ 2358 #define __FUNCT__ "DMPlexGetFullMeet" 2359 /*@C 2360 DMPlexGetFullMeet - Get an array for the meet of the set of points 2361 2362 Not Collective 2363 2364 Input Parameters: 2365 + dm - The DMPlex object 2366 . numPoints - The number of input points for the meet 2367 - points - The input points 2368 2369 Output Parameters: 2370 + numCoveredPoints - The number of points in the meet 2371 - coveredPoints - The points in the meet 2372 2373 Level: intermediate 2374 2375 .keywords: mesh 2376 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2377 @*/ 2378 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2379 { 2380 DM_Plex *mesh = (DM_Plex*) dm->data; 2381 PetscInt *offsets, **closures; 2382 PetscInt *meet[2]; 2383 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2384 PetscInt p, h, c, m; 2385 PetscErrorCode ierr; 2386 2387 PetscFunctionBegin; 2388 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2389 PetscValidPointer(points, 2); 2390 PetscValidPointer(numCoveredPoints, 3); 2391 PetscValidPointer(coveredPoints, 4); 2392 2393 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2394 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2395 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2396 maxSize = PetscPowInt(mesh->maxConeSize,height); 2397 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2398 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2399 2400 for (p = 0; p < numPoints; ++p) { 2401 PetscInt closureSize; 2402 2403 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2404 2405 offsets[p*(height+2)+0] = 0; 2406 for (h = 0; h < height+1; ++h) { 2407 PetscInt pStart, pEnd, i; 2408 2409 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2410 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2411 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2412 offsets[p*(height+2)+h+1] = i; 2413 break; 2414 } 2415 } 2416 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2417 } 2418 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2419 } 2420 for (h = 0; h < height+1; ++h) { 2421 PetscInt dof; 2422 2423 /* Copy in cone of first point */ 2424 dof = offsets[h+1] - offsets[h]; 2425 for (meetSize = 0; meetSize < dof; ++meetSize) { 2426 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2427 } 2428 /* Check each successive cone */ 2429 for (p = 1; p < numPoints && meetSize; ++p) { 2430 PetscInt newMeetSize = 0; 2431 2432 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2433 for (c = 0; c < dof; ++c) { 2434 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2435 2436 for (m = 0; m < meetSize; ++m) { 2437 if (point == meet[i][m]) { 2438 meet[1-i][newMeetSize++] = point; 2439 break; 2440 } 2441 } 2442 } 2443 meetSize = newMeetSize; 2444 i = 1-i; 2445 } 2446 if (meetSize) break; 2447 } 2448 *numCoveredPoints = meetSize; 2449 *coveredPoints = meet[i]; 2450 for (p = 0; p < numPoints; ++p) { 2451 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2452 } 2453 ierr = PetscFree(closures);CHKERRQ(ierr); 2454 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2455 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2456 PetscFunctionReturn(0); 2457 } 2458 2459 #undef __FUNCT__ 2460 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2461 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2462 { 2463 MPI_Comm comm; 2464 PetscErrorCode ierr; 2465 2466 PetscFunctionBegin; 2467 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2468 PetscValidPointer(numFaceVertices,3); 2469 switch (cellDim) { 2470 case 0: 2471 *numFaceVertices = 0; 2472 break; 2473 case 1: 2474 *numFaceVertices = 1; 2475 break; 2476 case 2: 2477 switch (numCorners) { 2478 case 3: /* triangle */ 2479 *numFaceVertices = 2; /* Edge has 2 vertices */ 2480 break; 2481 case 4: /* quadrilateral */ 2482 *numFaceVertices = 2; /* Edge has 2 vertices */ 2483 break; 2484 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2485 *numFaceVertices = 3; /* Edge has 3 vertices */ 2486 break; 2487 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2488 *numFaceVertices = 3; /* Edge has 3 vertices */ 2489 break; 2490 default: 2491 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2492 } 2493 break; 2494 case 3: 2495 switch (numCorners) { 2496 case 4: /* tetradehdron */ 2497 *numFaceVertices = 3; /* Face has 3 vertices */ 2498 break; 2499 case 6: /* tet cohesive cells */ 2500 *numFaceVertices = 4; /* Face has 4 vertices */ 2501 break; 2502 case 8: /* hexahedron */ 2503 *numFaceVertices = 4; /* Face has 4 vertices */ 2504 break; 2505 case 9: /* tet cohesive Lagrange cells */ 2506 *numFaceVertices = 6; /* Face has 6 vertices */ 2507 break; 2508 case 10: /* quadratic tetrahedron */ 2509 *numFaceVertices = 6; /* Face has 6 vertices */ 2510 break; 2511 case 12: /* hex cohesive Lagrange cells */ 2512 *numFaceVertices = 6; /* Face has 6 vertices */ 2513 break; 2514 case 18: /* quadratic tet cohesive Lagrange cells */ 2515 *numFaceVertices = 6; /* Face has 6 vertices */ 2516 break; 2517 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2518 *numFaceVertices = 9; /* Face has 9 vertices */ 2519 break; 2520 default: 2521 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2522 } 2523 break; 2524 default: 2525 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2526 } 2527 PetscFunctionReturn(0); 2528 } 2529 2530 #undef __FUNCT__ 2531 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2532 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2533 { 2534 const PetscInt maxFaceCases = 30; 2535 PetscInt numFaceCases = 0; 2536 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2537 PetscInt *off, *adj; 2538 PetscInt *neighborCells, *tmpClosure; 2539 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2540 PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 2541 PetscErrorCode ierr; 2542 2543 PetscFunctionBegin; 2544 /* For parallel partitioning, I think you have to communicate supports */ 2545 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2546 cellDim = dim - cellHeight; 2547 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2548 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 2549 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2550 if (cEnd - cStart == 0) { 2551 if (numVertices) *numVertices = 0; 2552 if (offsets) *offsets = NULL; 2553 if (adjacency) *adjacency = NULL; 2554 PetscFunctionReturn(0); 2555 } 2556 numCells = cEnd - cStart; 2557 faceDepth = depth - cellHeight; 2558 /* Setup face recognition */ 2559 if (faceDepth == 1) { 2560 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 */ 2561 2562 for (c = cStart; c < cEnd; ++c) { 2563 PetscInt corners; 2564 2565 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2566 if (!cornersSeen[corners]) { 2567 PetscInt nFV; 2568 2569 if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2570 cornersSeen[corners] = 1; 2571 2572 ierr = DMPlexGetNumFaceVertices_Internal(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 2573 2574 numFaceVertices[numFaceCases++] = nFV; 2575 } 2576 } 2577 } 2578 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2579 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2580 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2581 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2582 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2583 /* Count neighboring cells */ 2584 for (cell = cStart; cell < cEnd; ++cell) { 2585 PetscInt numNeighbors = maxNeighbors, n; 2586 2587 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2588 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2589 for (n = 0; n < numNeighbors; ++n) { 2590 PetscInt cellPair[2]; 2591 PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 2592 PetscInt meetSize = 0; 2593 const PetscInt *meet = NULL; 2594 2595 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2596 if (cellPair[0] == cellPair[1]) continue; 2597 if (!found) { 2598 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2599 if (meetSize) { 2600 PetscInt f; 2601 2602 for (f = 0; f < numFaceCases; ++f) { 2603 if (numFaceVertices[f] == meetSize) { 2604 found = PETSC_TRUE; 2605 break; 2606 } 2607 } 2608 } 2609 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2610 } 2611 if (found) ++off[cell-cStart+1]; 2612 } 2613 } 2614 /* Prefix sum */ 2615 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2616 2617 if (adjacency) { 2618 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2619 /* Get neighboring cells */ 2620 for (cell = cStart; cell < cEnd; ++cell) { 2621 PetscInt numNeighbors = maxNeighbors, n; 2622 PetscInt cellOffset = 0; 2623 2624 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2625 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2626 for (n = 0; n < numNeighbors; ++n) { 2627 PetscInt cellPair[2]; 2628 PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 2629 PetscInt meetSize = 0; 2630 const PetscInt *meet = NULL; 2631 2632 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2633 if (cellPair[0] == cellPair[1]) continue; 2634 if (!found) { 2635 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2636 if (meetSize) { 2637 PetscInt f; 2638 2639 for (f = 0; f < numFaceCases; ++f) { 2640 if (numFaceVertices[f] == meetSize) { 2641 found = PETSC_TRUE; 2642 break; 2643 } 2644 } 2645 } 2646 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2647 } 2648 if (found) { 2649 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2650 ++cellOffset; 2651 } 2652 } 2653 } 2654 } 2655 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2656 if (numVertices) *numVertices = numCells; 2657 if (offsets) *offsets = off; 2658 if (adjacency) *adjacency = adj; 2659 PetscFunctionReturn(0); 2660 } 2661 2662 #if defined(PETSC_HAVE_CHACO) 2663 #if defined(PETSC_HAVE_UNISTD_H) 2664 #include <unistd.h> 2665 #endif 2666 /* Chaco does not have an include file */ 2667 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2668 float *ewgts, float *x, float *y, float *z, char *outassignname, 2669 char *outfilename, short *assignment, int architecture, int ndims_tot, 2670 int mesh_dims[3], double *goal, int global_method, int local_method, 2671 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2672 2673 extern int FREE_GRAPH; 2674 2675 #undef __FUNCT__ 2676 #define __FUNCT__ "DMPlexPartition_Chaco" 2677 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2678 { 2679 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2680 MPI_Comm comm; 2681 int nvtxs = numVertices; /* number of vertices in full graph */ 2682 int *vwgts = NULL; /* weights for all vertices */ 2683 float *ewgts = NULL; /* weights for all edges */ 2684 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2685 char *outassignname = NULL; /* name of assignment output file */ 2686 char *outfilename = NULL; /* output file name */ 2687 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2688 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2689 int mesh_dims[3]; /* dimensions of mesh of processors */ 2690 double *goal = NULL; /* desired set sizes for each set */ 2691 int global_method = 1; /* global partitioning algorithm */ 2692 int local_method = 1; /* local partitioning algorithm */ 2693 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2694 int vmax = 200; /* how many vertices to coarsen down to? */ 2695 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2696 double eigtol = 0.001; /* tolerance on eigenvectors */ 2697 long seed = 123636512; /* for random graph mutations */ 2698 short int *assignment; /* Output partition */ 2699 int fd_stdout, fd_pipe[2]; 2700 PetscInt *points; 2701 PetscMPIInt commSize; 2702 int i, v, p; 2703 PetscErrorCode ierr; 2704 2705 PetscFunctionBegin; 2706 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2707 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2708 if (!numVertices) { 2709 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2710 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2711 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2712 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2713 PetscFunctionReturn(0); 2714 } 2715 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2716 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2717 2718 if (global_method == INERTIAL_METHOD) { 2719 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2720 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2721 } 2722 mesh_dims[0] = commSize; 2723 mesh_dims[1] = 1; 2724 mesh_dims[2] = 1; 2725 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2726 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2727 /* TODO: check error codes for UNIX calls */ 2728 #if defined(PETSC_HAVE_UNISTD_H) 2729 { 2730 int piperet; 2731 piperet = pipe(fd_pipe); 2732 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2733 fd_stdout = dup(1); 2734 close(1); 2735 dup2(fd_pipe[1], 1); 2736 } 2737 #endif 2738 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2739 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2740 vmax, ndims, eigtol, seed); 2741 #if defined(PETSC_HAVE_UNISTD_H) 2742 { 2743 char msgLog[10000]; 2744 int count; 2745 2746 fflush(stdout); 2747 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2748 if (count < 0) count = 0; 2749 msgLog[count] = 0; 2750 close(1); 2751 dup2(fd_stdout, 1); 2752 close(fd_stdout); 2753 close(fd_pipe[0]); 2754 close(fd_pipe[1]); 2755 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2756 } 2757 #endif 2758 /* Convert to PetscSection+IS */ 2759 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2760 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2761 for (v = 0; v < nvtxs; ++v) { 2762 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2763 } 2764 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2765 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2766 for (p = 0, i = 0; p < commSize; ++p) { 2767 for (v = 0; v < nvtxs; ++v) { 2768 if (assignment[v] == p) points[i++] = v; 2769 } 2770 } 2771 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2772 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2773 if (global_method == INERTIAL_METHOD) { 2774 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2775 } 2776 ierr = PetscFree(assignment);CHKERRQ(ierr); 2777 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2778 PetscFunctionReturn(0); 2779 } 2780 #endif 2781 2782 #if defined(PETSC_HAVE_PARMETIS) 2783 #undef __FUNCT__ 2784 #define __FUNCT__ "DMPlexPartition_ParMetis" 2785 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2786 { 2787 PetscFunctionBegin; 2788 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ParMetis not yet supported"); 2789 PetscFunctionReturn(0); 2790 } 2791 #endif 2792 2793 #undef __FUNCT__ 2794 #define __FUNCT__ "DMPlexEnlargePartition" 2795 /* Expand the partition by BFS on the adjacency graph */ 2796 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2797 { 2798 PetscHashI h; 2799 const PetscInt *points; 2800 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2801 PetscInt pStart, pEnd, part, q; 2802 PetscErrorCode ierr; 2803 2804 PetscFunctionBegin; 2805 PetscHashICreate(h); 2806 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2807 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2808 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2809 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2810 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2811 for (part = pStart; part < pEnd; ++part) { 2812 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2813 2814 PetscHashIClear(h); 2815 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2816 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2817 /* Add all existing points to h */ 2818 for (p = 0; p < numPoints; ++p) { 2819 const PetscInt point = points[off+p]; 2820 PetscHashIAdd(h, point, 1); 2821 } 2822 PetscHashISize(h, nP); 2823 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2824 /* Add all points in next BFS level */ 2825 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2826 for (p = 0; p < numPoints; ++p) { 2827 const PetscInt point = points[off+p]; 2828 PetscInt s = start[point], e = start[point+1], a; 2829 2830 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2831 } 2832 PetscHashISize(h, numNewPoints); 2833 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2834 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2835 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2836 totPoints += numNewPoints; 2837 } 2838 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2839 PetscHashIDestroy(h); 2840 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2841 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2842 for (part = pStart, q = 0; part < pEnd; ++part) { 2843 PetscInt numPoints, p; 2844 2845 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2846 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2847 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2848 } 2849 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2850 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2851 PetscFunctionReturn(0); 2852 } 2853 2854 #undef __FUNCT__ 2855 #define __FUNCT__ "DMPlexCreatePartition" 2856 /* 2857 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2858 2859 Collective on DM 2860 2861 Input Parameters: 2862 + dm - The DM 2863 . height - The height for points in the partition 2864 - enlarge - Expand each partition with neighbors 2865 2866 Output Parameters: 2867 + partSection - The PetscSection giving the division of points by partition 2868 . partition - The list of points by partition 2869 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2870 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2871 2872 Level: developer 2873 2874 .seealso DMPlexDistribute() 2875 */ 2876 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2877 { 2878 PetscMPIInt size; 2879 PetscErrorCode ierr; 2880 2881 PetscFunctionBegin; 2882 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2883 2884 *origPartSection = NULL; 2885 *origPartition = NULL; 2886 if (size == 1) { 2887 PetscInt *points; 2888 PetscInt cStart, cEnd, c; 2889 2890 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2891 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2892 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2893 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2894 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2895 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2896 for (c = cStart; c < cEnd; ++c) points[c] = c; 2897 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2898 PetscFunctionReturn(0); 2899 } 2900 if (height == 0) { 2901 PetscInt numVertices; 2902 PetscInt *start = NULL; 2903 PetscInt *adjacency = NULL; 2904 2905 ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2906 if (1) { 2907 #if defined(PETSC_HAVE_CHACO) 2908 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2909 #endif 2910 } else { 2911 #if defined(PETSC_HAVE_PARMETIS) 2912 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2913 #endif 2914 } 2915 if (enlarge) { 2916 *origPartSection = *partSection; 2917 *origPartition = *partition; 2918 2919 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2920 } 2921 ierr = PetscFree(start);CHKERRQ(ierr); 2922 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2923 # if 0 2924 } else if (height == 1) { 2925 /* Build the dual graph for faces and partition the hypergraph */ 2926 PetscInt numEdges; 2927 2928 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2929 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2930 destroyCSR(numEdges, start, adjacency); 2931 #endif 2932 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2933 PetscFunctionReturn(0); 2934 } 2935 2936 #undef __FUNCT__ 2937 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2938 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2939 { 2940 /* const PetscInt height = 0; */ 2941 const PetscInt *partArray; 2942 PetscInt *allPoints, *partPoints = NULL; 2943 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2944 PetscErrorCode ierr; 2945 2946 PetscFunctionBegin; 2947 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2948 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2949 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2950 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2951 for (rank = rStart; rank < rEnd; ++rank) { 2952 PetscInt partSize = 0; 2953 PetscInt numPoints, offset, p; 2954 2955 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2956 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2957 for (p = 0; p < numPoints; ++p) { 2958 PetscInt point = partArray[offset+p], closureSize, c; 2959 PetscInt *closure = NULL; 2960 2961 /* TODO Include support for height > 0 case */ 2962 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2963 /* Merge into existing points */ 2964 if (partSize+closureSize > maxPartSize) { 2965 PetscInt *tmpPoints; 2966 2967 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2968 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2969 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2970 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2971 2972 partPoints = tmpPoints; 2973 } 2974 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 2975 partSize += closureSize; 2976 2977 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 2978 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2979 } 2980 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 2981 } 2982 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2983 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 2984 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 2985 2986 for (rank = rStart; rank < rEnd; ++rank) { 2987 PetscInt partSize = 0, newOffset; 2988 PetscInt numPoints, offset, p; 2989 2990 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2991 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2992 for (p = 0; p < numPoints; ++p) { 2993 PetscInt point = partArray[offset+p], closureSize, c; 2994 PetscInt *closure = NULL; 2995 2996 /* TODO Include support for height > 0 case */ 2997 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2998 /* Merge into existing points */ 2999 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3000 partSize += closureSize; 3001 3002 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3003 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3004 } 3005 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3006 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3007 } 3008 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3009 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3010 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3011 PetscFunctionReturn(0); 3012 } 3013 3014 #undef __FUNCT__ 3015 #define __FUNCT__ "DMPlexDistributeField" 3016 /* 3017 Input Parameters: 3018 . originalSection 3019 , originalVec 3020 3021 Output Parameters: 3022 . newSection 3023 . newVec 3024 */ 3025 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3026 { 3027 PetscSF fieldSF; 3028 PetscInt *remoteOffsets, fieldSize; 3029 PetscScalar *originalValues, *newValues; 3030 PetscErrorCode ierr; 3031 3032 PetscFunctionBegin; 3033 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3034 3035 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3036 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3037 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3038 3039 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3040 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3041 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3042 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3043 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3044 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3045 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3046 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3047 PetscFunctionReturn(0); 3048 } 3049 3050 #undef __FUNCT__ 3051 #define __FUNCT__ "DMPlexDistribute" 3052 /*@C 3053 DMPlexDistribute - Distributes the mesh and any associated sections. 3054 3055 Not Collective 3056 3057 Input Parameter: 3058 + dm - The original DMPlex object 3059 . partitioner - The partitioning package, or NULL for the default 3060 - overlap - The overlap of partitions, 0 is the default 3061 3062 Output Parameter: 3063 . parallelMesh - The distributed DMPlex object, or NULL 3064 3065 Note: If the mesh was not distributed, the return value is NULL 3066 3067 Level: intermediate 3068 3069 .keywords: mesh, elements 3070 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3071 @*/ 3072 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3073 { 3074 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3075 MPI_Comm comm; 3076 const PetscInt height = 0; 3077 PetscInt dim, numRemoteRanks; 3078 IS origCellPart, cellPart, part; 3079 PetscSection origCellPartSection, cellPartSection, partSection; 3080 PetscSFNode *remoteRanks; 3081 PetscSF partSF, pointSF, coneSF; 3082 ISLocalToGlobalMapping renumbering; 3083 PetscSection originalConeSection, newConeSection; 3084 PetscInt *remoteOffsets; 3085 PetscInt *cones, *newCones, newConesSize; 3086 PetscBool flg; 3087 PetscMPIInt rank, numProcs, p; 3088 PetscErrorCode ierr; 3089 3090 PetscFunctionBegin; 3091 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3092 PetscValidPointer(dmParallel,4); 3093 3094 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3095 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3096 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3097 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3098 3099 *dmParallel = NULL; 3100 if (numProcs == 1) PetscFunctionReturn(0); 3101 3102 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3103 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3104 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3105 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3106 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3107 if (!rank) numRemoteRanks = numProcs; 3108 else numRemoteRanks = 0; 3109 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3110 for (p = 0; p < numRemoteRanks; ++p) { 3111 remoteRanks[p].rank = p; 3112 remoteRanks[p].index = 0; 3113 } 3114 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3115 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3116 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3117 if (flg) { 3118 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3119 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3120 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3121 if (origCellPart) { 3122 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3123 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3124 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3125 } 3126 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3127 } 3128 /* Close the partition over the mesh */ 3129 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3130 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3131 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3132 /* Create new mesh */ 3133 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3134 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3135 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3136 pmesh = (DM_Plex*) (*dmParallel)->data; 3137 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3138 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3139 if (flg) { 3140 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3141 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3142 ierr = ISView(part, NULL);CHKERRQ(ierr); 3143 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3144 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3145 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3146 } 3147 /* Distribute cone section */ 3148 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3149 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3150 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3151 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3152 { 3153 PetscInt pStart, pEnd, p; 3154 3155 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3156 for (p = pStart; p < pEnd; ++p) { 3157 PetscInt coneSize; 3158 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3159 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3160 } 3161 } 3162 /* Communicate and renumber cones */ 3163 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3164 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3165 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3166 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3167 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3168 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3169 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3170 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3171 if (flg) { 3172 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3173 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3174 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3175 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3176 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3177 } 3178 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3179 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3180 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3181 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3182 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3183 /* Create supports and stratify sieve */ 3184 { 3185 PetscInt pStart, pEnd; 3186 3187 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3188 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3189 } 3190 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3191 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3192 /* Distribute Coordinates */ 3193 { 3194 PetscSection originalCoordSection, newCoordSection; 3195 Vec originalCoordinates, newCoordinates; 3196 const char *name; 3197 3198 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3199 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3200 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3201 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3202 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3203 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3204 3205 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3206 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3207 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3208 } 3209 /* Distribute labels */ 3210 { 3211 DMLabel next = mesh->labels, newNext = pmesh->labels; 3212 PetscInt numLabels = 0, l; 3213 3214 /* Bcast number of labels */ 3215 while (next) { 3216 ++numLabels; next = next->next; 3217 } 3218 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3219 next = mesh->labels; 3220 for (l = 0; l < numLabels; ++l) { 3221 DMLabel newLabel; 3222 const PetscInt *partArray; 3223 char *name; 3224 PetscInt *stratumSizes = NULL, *points = NULL; 3225 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3226 PetscInt nameSize, s, p; 3227 PetscBool isdepth; 3228 size_t len = 0; 3229 3230 /* Bcast name (could filter for no points) */ 3231 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3232 nameSize = len; 3233 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3234 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3235 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3236 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3237 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3238 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3239 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3240 newLabel->name = name; 3241 /* Bcast numStrata (could filter for no points in stratum) */ 3242 if (!rank) newLabel->numStrata = next->numStrata; 3243 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3244 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3245 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3246 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3247 /* Bcast stratumValues (could filter for no points in stratum) */ 3248 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3249 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3250 /* Find size on each process and Scatter */ 3251 if (!rank) { 3252 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3253 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3254 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3255 for (s = 0; s < next->numStrata; ++s) { 3256 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3257 const PetscInt point = next->points[p]; 3258 PetscInt proc; 3259 3260 for (proc = 0; proc < numProcs; ++proc) { 3261 PetscInt dof, off, pPart; 3262 3263 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3264 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3265 for (pPart = off; pPart < off+dof; ++pPart) { 3266 if (partArray[pPart] == point) { 3267 ++stratumSizes[proc*next->numStrata+s]; 3268 break; 3269 } 3270 } 3271 } 3272 } 3273 } 3274 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3275 } 3276 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3277 /* Calculate stratumOffsets */ 3278 newLabel->stratumOffsets[0] = 0; 3279 for (s = 0; s < newLabel->numStrata; ++s) { 3280 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3281 } 3282 /* Pack points and Scatter */ 3283 if (!rank) { 3284 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3285 displs[0] = 0; 3286 for (p = 0; p < numProcs; ++p) { 3287 sendcnts[p] = 0; 3288 for (s = 0; s < next->numStrata; ++s) { 3289 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3290 } 3291 offsets[p] = displs[p]; 3292 displs[p+1] = displs[p] + sendcnts[p]; 3293 } 3294 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3295 for (s = 0; s < next->numStrata; ++s) { 3296 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3297 const PetscInt point = next->points[p]; 3298 PetscInt proc; 3299 3300 for (proc = 0; proc < numProcs; ++proc) { 3301 PetscInt dof, off, pPart; 3302 3303 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3304 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3305 for (pPart = off; pPart < off+dof; ++pPart) { 3306 if (partArray[pPart] == point) { 3307 points[offsets[proc]++] = point; 3308 break; 3309 } 3310 } 3311 } 3312 } 3313 } 3314 } 3315 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3316 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3317 ierr = PetscFree(points);CHKERRQ(ierr); 3318 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3319 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3320 /* Renumber points */ 3321 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3322 /* Sort points */ 3323 for (s = 0; s < newLabel->numStrata; ++s) { 3324 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3325 } 3326 /* Insert into list */ 3327 if (newNext) newNext->next = newLabel; 3328 else pmesh->labels = newLabel; 3329 newNext = newLabel; 3330 if (!rank) next = next->next; 3331 } 3332 } 3333 /* Cleanup Partition */ 3334 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3335 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3336 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3337 ierr = ISDestroy(&part);CHKERRQ(ierr); 3338 /* Create point SF for parallel mesh */ 3339 { 3340 const PetscInt *leaves; 3341 PetscSFNode *remotePoints, *rowners, *lowners; 3342 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3343 PetscInt pStart, pEnd; 3344 3345 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3346 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3347 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3348 for (p=0; p<numRoots; p++) { 3349 rowners[p].rank = -1; 3350 rowners[p].index = -1; 3351 } 3352 if (origCellPart) { 3353 /* Make sure cells in the original partition are not assigned to other procs */ 3354 const PetscInt *origCells; 3355 3356 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3357 for (p = 0; p < numProcs; ++p) { 3358 PetscInt dof, off, d; 3359 3360 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3361 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3362 for (d = off; d < off+dof; ++d) { 3363 rowners[origCells[d]].rank = p; 3364 } 3365 } 3366 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3367 } 3368 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3369 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3370 3371 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3372 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3373 for (p = 0; p < numLeaves; ++p) { 3374 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3375 lowners[p].rank = rank; 3376 lowners[p].index = leaves ? leaves[p] : p; 3377 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3378 lowners[p].rank = -2; 3379 lowners[p].index = -2; 3380 } 3381 } 3382 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3383 rowners[p].rank = -3; 3384 rowners[p].index = -3; 3385 } 3386 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3387 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3388 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3389 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3390 for (p = 0; p < numLeaves; ++p) { 3391 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3392 if (lowners[p].rank != rank) ++numGhostPoints; 3393 } 3394 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3395 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3396 for (p = 0, gp = 0; p < numLeaves; ++p) { 3397 if (lowners[p].rank != rank) { 3398 ghostPoints[gp] = leaves ? leaves[p] : p; 3399 remotePoints[gp].rank = lowners[p].rank; 3400 remotePoints[gp].index = lowners[p].index; 3401 ++gp; 3402 } 3403 } 3404 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3405 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3406 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3407 } 3408 /* Cleanup */ 3409 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3410 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3411 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3412 PetscFunctionReturn(0); 3413 } 3414 3415 #undef __FUNCT__ 3416 #define __FUNCT__ "DMPlexRenumber_Private" 3417 /* 3418 Reasons to renumber: 3419 3420 1) Permute points, e.g. bandwidth reduction (Renumber) 3421 3422 a) Must not mix strata 3423 3424 2) Shift numbers for point insertion (Shift) 3425 3426 a) Want operation brken into parts so that insertion can be interleaved 3427 3428 renumbering - An IS which provides the new numbering 3429 */ 3430 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3431 { 3432 PetscFunctionBegin; 3433 PetscFunctionReturn(0); 3434 } 3435 3436 #undef __FUNCT__ 3437 #define __FUNCT__ "DMPlexShiftPoint_Private" 3438 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3439 { 3440 if (depth < 0) return p; 3441 /* Cells */ if (p < depthEnd[depth]) return p; 3442 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3443 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3444 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3445 } 3446 3447 #undef __FUNCT__ 3448 #define __FUNCT__ "DMPlexShiftSizes_Private" 3449 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3450 { 3451 PetscInt *depthEnd; 3452 PetscInt depth = 0, d, pStart, pEnd, p; 3453 PetscErrorCode ierr; 3454 3455 PetscFunctionBegin; 3456 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3457 if (depth < 0) PetscFunctionReturn(0); 3458 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3459 /* Step 1: Expand chart */ 3460 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3461 for (d = 0; d <= depth; ++d) { 3462 pEnd += depthShift[d]; 3463 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3464 } 3465 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3466 /* Step 2: Set cone and support sizes */ 3467 for (d = 0; d <= depth; ++d) { 3468 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3469 for (p = pStart; p < pEnd; ++p) { 3470 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3471 PetscInt size; 3472 3473 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3474 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3475 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3476 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3477 } 3478 } 3479 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3480 PetscFunctionReturn(0); 3481 } 3482 3483 #undef __FUNCT__ 3484 #define __FUNCT__ "DMPlexShiftPoints_Private" 3485 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3486 { 3487 PetscInt *depthEnd, *newpoints; 3488 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3489 PetscErrorCode ierr; 3490 3491 PetscFunctionBegin; 3492 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3493 if (depth < 0) PetscFunctionReturn(0); 3494 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3495 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3496 for (d = 0; d <= depth; ++d) { 3497 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3498 } 3499 /* Step 5: Set cones and supports */ 3500 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3501 for (p = pStart; p < pEnd; ++p) { 3502 const PetscInt *points = NULL, *orientations = NULL; 3503 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3504 3505 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3506 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3507 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3508 for (i = 0; i < size; ++i) { 3509 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3510 } 3511 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3512 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3513 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3514 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3515 for (i = 0; i < size; ++i) { 3516 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3517 } 3518 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3519 } 3520 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3521 PetscFunctionReturn(0); 3522 } 3523 3524 #undef __FUNCT__ 3525 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3526 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3527 { 3528 PetscSection coordSection, newCoordSection; 3529 Vec coordinates, newCoordinates; 3530 PetscScalar *coords, *newCoords; 3531 PetscInt *depthEnd, coordSize; 3532 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3533 PetscErrorCode ierr; 3534 3535 PetscFunctionBegin; 3536 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3537 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3538 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3539 for (d = 0; d <= depth; ++d) { 3540 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3541 } 3542 /* Step 8: Convert coordinates */ 3543 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3544 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3545 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3546 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);CHKERRQ(ierr); 3547 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3548 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3549 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3550 for (v = vStartNew; v < vEndNew; ++v) { 3551 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3552 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3553 } 3554 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3555 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3556 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3557 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &newCoordinates);CHKERRQ(ierr); 3558 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3559 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3560 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3561 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3562 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3563 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3564 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3565 for (v = vStart; v < vEnd; ++v) { 3566 PetscInt dof, off, noff, d; 3567 3568 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3569 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3570 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3571 for (d = 0; d < dof; ++d) { 3572 newCoords[noff+d] = coords[off+d]; 3573 } 3574 } 3575 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3576 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3577 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3578 ierr = PetscSectionDestroy(&newCoordSection);CHKERRQ(ierr); 3579 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3580 PetscFunctionReturn(0); 3581 } 3582 3583 #undef __FUNCT__ 3584 #define __FUNCT__ "DMPlexShiftSF_Private" 3585 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3586 { 3587 PetscInt *depthEnd; 3588 PetscInt depth = 0, d; 3589 PetscSF sfPoint, sfPointNew; 3590 const PetscSFNode *remotePoints; 3591 PetscSFNode *gremotePoints; 3592 const PetscInt *localPoints; 3593 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3594 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3595 PetscMPIInt numProcs; 3596 PetscErrorCode ierr; 3597 3598 PetscFunctionBegin; 3599 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3600 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3601 for (d = 0; d <= depth; ++d) { 3602 totShift += depthShift[d]; 3603 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3604 } 3605 /* Step 9: Convert pointSF */ 3606 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 3607 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3608 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3609 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3610 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3611 if (numRoots >= 0) { 3612 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3613 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3614 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3615 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3616 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3617 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3618 for (l = 0; l < numLeaves; ++l) { 3619 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3620 gremotePoints[l].rank = remotePoints[l].rank; 3621 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3622 } 3623 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3624 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3625 } 3626 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3627 PetscFunctionReturn(0); 3628 } 3629 3630 #undef __FUNCT__ 3631 #define __FUNCT__ "DMPlexShiftLabels_Private" 3632 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3633 { 3634 PetscSF sfPoint; 3635 DMLabel vtkLabel, ghostLabel; 3636 PetscInt *depthEnd; 3637 const PetscSFNode *leafRemote; 3638 const PetscInt *leafLocal; 3639 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3640 PetscMPIInt rank; 3641 PetscErrorCode ierr; 3642 3643 PetscFunctionBegin; 3644 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3645 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3646 for (d = 0; d <= depth; ++d) { 3647 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3648 } 3649 /* Step 10: Convert labels */ 3650 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3651 for (l = 0; l < numLabels; ++l) { 3652 DMLabel label, newlabel; 3653 const char *lname; 3654 PetscBool isDepth; 3655 IS valueIS; 3656 const PetscInt *values; 3657 PetscInt numValues, val; 3658 3659 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3660 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3661 if (isDepth) continue; 3662 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3663 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3664 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3665 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3666 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3667 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3668 for (val = 0; val < numValues; ++val) { 3669 IS pointIS; 3670 const PetscInt *points; 3671 PetscInt numPoints, p; 3672 3673 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3674 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3675 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3676 for (p = 0; p < numPoints; ++p) { 3677 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3678 3679 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3680 } 3681 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3682 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3683 } 3684 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3685 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3686 } 3687 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3688 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3689 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 3690 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3691 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3692 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3693 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3694 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3695 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3696 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3697 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3698 for (; c < leafLocal[l] && c < cEnd; ++c) { 3699 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3700 } 3701 if (leafLocal[l] >= cEnd) break; 3702 if (leafRemote[l].rank == rank) { 3703 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3704 } else { 3705 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3706 } 3707 } 3708 for (; c < cEnd; ++c) { 3709 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3710 } 3711 if (0) { 3712 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3713 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3714 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3715 } 3716 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3717 for (f = fStart; f < fEnd; ++f) { 3718 PetscInt numCells; 3719 3720 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3721 if (numCells < 2) { 3722 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3723 } else { 3724 const PetscInt *cells = NULL; 3725 PetscInt vA, vB; 3726 3727 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3728 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3729 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3730 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3731 } 3732 } 3733 if (0) { 3734 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3735 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3736 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3737 } 3738 PetscFunctionReturn(0); 3739 } 3740 3741 #undef __FUNCT__ 3742 #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3743 PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3744 { 3745 DMLabel label; 3746 IS valueIS; 3747 const PetscInt *values; 3748 PetscInt *depthShift; 3749 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3750 PetscErrorCode ierr; 3751 3752 PetscFunctionBegin; 3753 /* Count ghost cells */ 3754 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3755 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3756 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3757 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3758 3759 *numGhostCells = 0; 3760 for (fs = 0; fs < numFS; ++fs) { 3761 PetscInt numBdFaces; 3762 3763 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3764 3765 *numGhostCells += numBdFaces; 3766 } 3767 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3768 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3769 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3770 if (depth >= 0) depthShift[depth] = *numGhostCells; 3771 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3772 /* Step 3: Set cone/support sizes for new points */ 3773 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3774 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3775 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3776 } 3777 for (fs = 0; fs < numFS; ++fs) { 3778 IS faceIS; 3779 const PetscInt *faces; 3780 PetscInt numFaces, f; 3781 3782 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3783 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3784 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3785 for (f = 0; f < numFaces; ++f) { 3786 PetscInt size; 3787 3788 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3789 if (size != 1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3790 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3791 } 3792 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3793 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3794 } 3795 /* Step 4: Setup ghosted DM */ 3796 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3797 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3798 /* Step 6: Set cones and supports for new points */ 3799 ghostCell = cEnd; 3800 for (fs = 0; fs < numFS; ++fs) { 3801 IS faceIS; 3802 const PetscInt *faces; 3803 PetscInt numFaces, f; 3804 3805 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3806 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3807 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3808 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3809 PetscInt newFace = faces[f] + *numGhostCells; 3810 3811 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3812 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3813 } 3814 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3815 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3816 } 3817 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3818 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3819 /* Step 7: Stratify */ 3820 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3821 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3822 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3823 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3824 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3825 PetscFunctionReturn(0); 3826 } 3827 3828 #undef __FUNCT__ 3829 #define __FUNCT__ "DMPlexConstructGhostCells" 3830 /*@C 3831 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3832 3833 Collective on dm 3834 3835 Input Parameters: 3836 + dm - The original DM 3837 - labelName - The label specifying the boundary faces (this could be auto-generated) 3838 3839 Output Parameters: 3840 + numGhostCells - The number of ghost cells added to the DM 3841 - dmGhosted - The new DM 3842 3843 Level: developer 3844 3845 .seealso: DMCreate() 3846 */ 3847 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3848 { 3849 DM gdm; 3850 PetscInt dim; 3851 PetscErrorCode ierr; 3852 3853 PetscFunctionBegin; 3854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3855 PetscValidPointer(numGhostCells, 3); 3856 PetscValidPointer(dmGhosted, 4); 3857 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &gdm);CHKERRQ(ierr); 3858 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3859 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3860 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3861 switch (dim) { 3862 case 2: 3863 ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3864 break; 3865 default: 3866 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3867 } 3868 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3869 *dmGhosted = gdm; 3870 PetscFunctionReturn(0); 3871 } 3872 3873 #undef __FUNCT__ 3874 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3875 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3876 { 3877 MPI_Comm comm; 3878 IS valueIS, *pointIS; 3879 const PetscInt *values, **splitPoints; 3880 PetscSection coordSection; 3881 Vec coordinates; 3882 PetscScalar *coords; 3883 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3884 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3885 PetscErrorCode ierr; 3886 3887 PetscFunctionBegin; 3888 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3889 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3890 /* Count split points and add cohesive cells */ 3891 if (label) { 3892 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3893 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3894 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3895 } 3896 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3897 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3898 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3899 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3900 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3901 for (d = 0; d <= depth; ++d) { 3902 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3903 numSplitPoints[d] = 0; 3904 splitPoints[d] = NULL; 3905 pointIS[d] = NULL; 3906 } 3907 for (sp = 0; sp < numSP; ++sp) { 3908 const PetscInt dep = values[sp]; 3909 3910 if ((dep < 0) || (dep > depth)) continue; 3911 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3912 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3913 if (pointIS[dep]) { 3914 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3915 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3916 } 3917 } 3918 if (depth >= 0) { 3919 /* Calculate number of additional points */ 3920 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3921 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3922 /* Calculate hybrid bound for each dimension */ 3923 pMaxNew[0] += depthShift[depth]; 3924 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3925 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3926 3927 /* Calculate point offset for each dimension */ 3928 depthOffset[depth] = 0; 3929 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3930 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3931 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3932 } 3933 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3934 /* Step 3: Set cone/support sizes for new points */ 3935 for (dep = 0; dep <= depth; ++dep) { 3936 for (p = 0; p < numSplitPoints[dep]; ++p) { 3937 const PetscInt oldp = splitPoints[dep][p]; 3938 const PetscInt newp = depthOffset[dep] + oldp; 3939 const PetscInt splitp = pMaxNew[dep] + p; 3940 const PetscInt *support; 3941 PetscInt coneSize, supportSize, q, e; 3942 3943 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3944 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3945 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3946 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3947 if (dep == depth-1) { 3948 const PetscInt ccell = pMaxNew[depth] + p; 3949 /* Add cohesive cells, they are prisms */ 3950 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3951 } else if (dep == 0) { 3952 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3953 3954 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3955 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3956 for (e = 0, q = 0; e < supportSize; ++e) { 3957 PetscInt val; 3958 3959 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3960 if ((val == 1) || (val == (shift + 1))) ++q; 3961 } 3962 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3963 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3964 for (e = 0, q = 0; e < supportSize; ++e) { 3965 PetscInt val; 3966 3967 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3968 if ((val == 1) || (val == -(shift + 1))) ++q; 3969 } 3970 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3971 /* Add cohesive edges */ 3972 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3973 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3974 } else if (dep == dim-2) { 3975 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3976 /* Split old edge: Faces in positive side cells and old split faces */ 3977 for (e = 0, q = 0; e < supportSize; ++e) { 3978 PetscInt val; 3979 3980 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3981 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 3982 } 3983 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 3984 /* Split new edge: Faces in negative side cells and new split faces */ 3985 for (e = 0, q = 0; e < supportSize; ++e) { 3986 PetscInt val; 3987 3988 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3989 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 3990 } 3991 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 3992 } 3993 } 3994 } 3995 /* Step 4: Setup split DM */ 3996 ierr = DMSetUp(sdm);CHKERRQ(ierr); 3997 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3998 /* Step 6: Set cones and supports for new points */ 3999 for (dep = 0; dep <= depth; ++dep) { 4000 for (p = 0; p < numSplitPoints[dep]; ++p) { 4001 const PetscInt oldp = splitPoints[dep][p]; 4002 const PetscInt newp = depthOffset[dep] + oldp; 4003 const PetscInt splitp = pMaxNew[dep] + p; 4004 const PetscInt *cone, *support, *ornt; 4005 PetscInt coneSize, supportSize, q, v, e, s; 4006 4007 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4008 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4009 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4010 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4011 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4012 if (dep == depth-1) { 4013 const PetscInt ccell = pMaxNew[depth] + p; 4014 const PetscInt *supportF; 4015 4016 /* Split face: copy in old face to new face to start */ 4017 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4018 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4019 /* Split old face: old vertices/edges in cone so no change */ 4020 /* Split new face: new vertices/edges in cone */ 4021 for (q = 0; q < coneSize; ++q) { 4022 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4023 4024 coneNew[2+q] = pMaxNew[dim-2] + v; 4025 } 4026 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4027 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4028 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4029 coneNew[0] = newp; 4030 coneNew[1] = splitp; 4031 for (q = 0; q < coneSize; ++q) { 4032 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4033 } 4034 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4035 4036 4037 for (s = 0; s < supportSize; ++s) { 4038 PetscInt val; 4039 4040 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4041 if (val < 0) { 4042 /* Split old face: Replace negative side cell with cohesive cell */ 4043 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4044 } else { 4045 /* Split new face: Replace positive side cell with cohesive cell */ 4046 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4047 } 4048 } 4049 } else if (dep == 0) { 4050 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4051 4052 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4053 for (e = 0, q = 0; e < supportSize; ++e) { 4054 PetscInt val; 4055 4056 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4057 if ((val == 1) || (val == (shift + 1))) { 4058 supportNew[q++] = depthOffset[1] + support[e]; 4059 } 4060 } 4061 supportNew[q] = cedge; 4062 4063 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4064 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4065 for (e = 0, q = 0; e < supportSize; ++e) { 4066 PetscInt val, edge; 4067 4068 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4069 if (val == 1) { 4070 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4071 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4072 supportNew[q++] = pMaxNew[1] + edge; 4073 } else if (val == -(shift + 1)) { 4074 supportNew[q++] = depthOffset[1] + support[e]; 4075 } 4076 } 4077 supportNew[q] = cedge; 4078 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4079 /* Cohesive edge: Old and new split vertex, punting on support */ 4080 coneNew[0] = newp; 4081 coneNew[1] = splitp; 4082 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4083 } else if (dep == dim-2) { 4084 /* Split old edge: old vertices in cone so no change */ 4085 /* Split new edge: new vertices in cone */ 4086 for (q = 0; q < coneSize; ++q) { 4087 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4088 4089 coneNew[q] = pMaxNew[dim-3] + v; 4090 } 4091 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4092 /* Split old edge: Faces in positive side cells and old split faces */ 4093 for (e = 0, q = 0; e < supportSize; ++e) { 4094 PetscInt val; 4095 4096 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4097 if ((val == dim-1) || (val == (shift + dim-1))) { 4098 supportNew[q++] = depthOffset[dim-1] + support[e]; 4099 } 4100 } 4101 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4102 /* Split new edge: Faces in negative side cells and new split faces */ 4103 for (e = 0, q = 0; e < supportSize; ++e) { 4104 PetscInt val, face; 4105 4106 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4107 if (val == dim-1) { 4108 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4109 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4110 supportNew[q++] = pMaxNew[dim-1] + face; 4111 } else if (val == -(shift + dim-1)) { 4112 supportNew[q++] = depthOffset[dim-1] + support[e]; 4113 } 4114 } 4115 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4116 } 4117 } 4118 } 4119 /* Step 6b: Replace split points in negative side cones */ 4120 for (sp = 0; sp < numSP; ++sp) { 4121 PetscInt dep = values[sp]; 4122 IS pIS; 4123 PetscInt numPoints; 4124 const PetscInt *points; 4125 4126 if (dep >= 0) continue; 4127 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4128 if (!pIS) continue; 4129 dep = -dep - shift; 4130 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4131 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4132 for (p = 0; p < numPoints; ++p) { 4133 const PetscInt oldp = points[p]; 4134 const PetscInt newp = depthOffset[dep] + oldp; 4135 const PetscInt *cone; 4136 PetscInt coneSize, c; 4137 PetscBool replaced = PETSC_FALSE; 4138 4139 /* Negative edge: replace split vertex */ 4140 /* Negative cell: replace split face */ 4141 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4142 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4143 for (c = 0; c < coneSize; ++c) { 4144 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4145 PetscInt csplitp, cp, val; 4146 4147 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4148 if (val == dep-1) { 4149 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4150 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4151 csplitp = pMaxNew[dep-1] + cp; 4152 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4153 replaced = PETSC_TRUE; 4154 } 4155 } 4156 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4157 } 4158 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4159 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4160 } 4161 /* Step 7: Stratify */ 4162 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4163 /* Step 8: Coordinates */ 4164 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4165 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4166 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4167 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4168 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4169 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4170 const PetscInt splitp = pMaxNew[0] + v; 4171 PetscInt dof, off, soff, d; 4172 4173 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4174 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4175 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4176 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4177 } 4178 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4179 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4180 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4181 /* Step 10: Labels */ 4182 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4183 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4184 for (dep = 0; dep <= depth; ++dep) { 4185 for (p = 0; p < numSplitPoints[dep]; ++p) { 4186 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4187 const PetscInt splitp = pMaxNew[dep] + p; 4188 PetscInt l; 4189 4190 for (l = 0; l < numLabels; ++l) { 4191 DMLabel mlabel; 4192 const char *lname; 4193 PetscInt val; 4194 4195 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4196 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4197 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4198 if (val >= 0) { 4199 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4200 if (dep == 0) { 4201 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4202 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4203 } 4204 } 4205 } 4206 } 4207 } 4208 for (sp = 0; sp < numSP; ++sp) { 4209 const PetscInt dep = values[sp]; 4210 4211 if ((dep < 0) || (dep > depth)) continue; 4212 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4213 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4214 } 4215 if (label) { 4216 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4217 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4218 } 4219 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4220 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4221 PetscFunctionReturn(0); 4222 } 4223 4224 #undef __FUNCT__ 4225 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4226 /*@C 4227 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4228 4229 Collective on dm 4230 4231 Input Parameters: 4232 + dm - The original DM 4233 - labelName - The label specifying the boundary faces (this could be auto-generated) 4234 4235 Output Parameters: 4236 - dmSplit - The new DM 4237 4238 Level: developer 4239 4240 .seealso: DMCreate() 4241 */ 4242 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4243 { 4244 DM sdm; 4245 PetscInt dim; 4246 PetscErrorCode ierr; 4247 4248 PetscFunctionBegin; 4249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4250 PetscValidPointer(dmSplit, 4); 4251 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 4252 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4253 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4254 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4255 switch (dim) { 4256 case 2: 4257 case 3: 4258 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4259 break; 4260 default: 4261 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4262 } 4263 *dmSplit = sdm; 4264 PetscFunctionReturn(0); 4265 } 4266 4267 #undef __FUNCT__ 4268 #define __FUNCT__ "DMLabelCohesiveComplete" 4269 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4270 { 4271 IS dimIS; 4272 const PetscInt *points; 4273 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4274 PetscErrorCode ierr; 4275 4276 PetscFunctionBegin; 4277 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4278 /* Cell orientation for face gives the side of the fault */ 4279 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4280 if (!dimIS) PetscFunctionReturn(0); 4281 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4282 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4283 for (p = 0; p < numPoints; ++p) { 4284 const PetscInt *support; 4285 PetscInt supportSize, s; 4286 4287 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4288 if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4289 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4290 for (s = 0; s < supportSize; ++s) { 4291 const PetscInt *cone, *ornt; 4292 PetscInt coneSize, c; 4293 PetscBool pos = PETSC_TRUE; 4294 4295 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4296 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4297 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4298 for (c = 0; c < coneSize; ++c) { 4299 if (cone[c] == points[p]) { 4300 if (ornt[c] >= 0) { 4301 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4302 } else { 4303 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4304 pos = PETSC_FALSE; 4305 } 4306 break; 4307 } 4308 } 4309 if (c == coneSize) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]); 4310 /* Put faces touching the fault in the label */ 4311 for (c = 0; c < coneSize; ++c) { 4312 const PetscInt point = cone[c]; 4313 4314 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4315 if (val == -1) { 4316 PetscInt *closure = NULL; 4317 PetscInt closureSize, cl; 4318 4319 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4320 for (cl = 0; cl < closureSize*2; cl += 2) { 4321 const PetscInt clp = closure[cl]; 4322 4323 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4324 if ((val >= 0) && (val < dim-1)) { 4325 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4326 break; 4327 } 4328 } 4329 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4330 } 4331 } 4332 } 4333 } 4334 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4335 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4336 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4337 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4338 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4339 if (!dimIS) PetscFunctionReturn(0); 4340 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4341 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4342 for (p = 0; p < numPoints; ++p) { 4343 PetscInt *star = NULL; 4344 PetscInt starSize, s; 4345 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4346 4347 /* First mark cells connected to the fault */ 4348 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4349 while (again) { 4350 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4351 again = 0; 4352 for (s = 0; s < starSize*2; s += 2) { 4353 const PetscInt point = star[s]; 4354 const PetscInt *cone; 4355 PetscInt coneSize, c; 4356 4357 if ((point < cStart) || (point >= cEnd)) continue; 4358 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4359 if (val != -1) continue; 4360 again = 2; 4361 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4362 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4363 for (c = 0; c < coneSize; ++c) { 4364 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4365 if (val != -1) { 4366 if (abs(val) < shift) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 4367 if (val > 0) { 4368 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4369 } else { 4370 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4371 } 4372 again = 1; 4373 break; 4374 } 4375 } 4376 } 4377 } 4378 /* Classify the rest by cell membership */ 4379 for (s = 0; s < starSize*2; s += 2) { 4380 const PetscInt point = star[s]; 4381 4382 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4383 if (val == -1) { 4384 PetscInt *sstar = NULL; 4385 PetscInt sstarSize, ss; 4386 PetscBool marked = PETSC_FALSE; 4387 4388 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4389 for (ss = 0; ss < sstarSize*2; ss += 2) { 4390 const PetscInt spoint = sstar[ss]; 4391 4392 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4393 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4394 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4395 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4396 if (val > 0) { 4397 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4398 } else { 4399 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4400 } 4401 marked = PETSC_TRUE; 4402 break; 4403 } 4404 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4405 if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 4406 } 4407 } 4408 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4409 } 4410 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4411 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4412 PetscFunctionReturn(0); 4413 } 4414 4415 #if defined(PETSC_HAVE_TRIANGLE) 4416 #include <triangle.h> 4417 4418 #undef __FUNCT__ 4419 #define __FUNCT__ "InitInput_Triangle" 4420 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4421 { 4422 PetscFunctionBegin; 4423 inputCtx->numberofpoints = 0; 4424 inputCtx->numberofpointattributes = 0; 4425 inputCtx->pointlist = NULL; 4426 inputCtx->pointattributelist = NULL; 4427 inputCtx->pointmarkerlist = NULL; 4428 inputCtx->numberofsegments = 0; 4429 inputCtx->segmentlist = NULL; 4430 inputCtx->segmentmarkerlist = NULL; 4431 inputCtx->numberoftriangleattributes = 0; 4432 inputCtx->trianglelist = NULL; 4433 inputCtx->numberofholes = 0; 4434 inputCtx->holelist = NULL; 4435 inputCtx->numberofregions = 0; 4436 inputCtx->regionlist = NULL; 4437 PetscFunctionReturn(0); 4438 } 4439 4440 #undef __FUNCT__ 4441 #define __FUNCT__ "InitOutput_Triangle" 4442 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4443 { 4444 PetscFunctionBegin; 4445 outputCtx->numberofpoints = 0; 4446 outputCtx->pointlist = NULL; 4447 outputCtx->pointattributelist = NULL; 4448 outputCtx->pointmarkerlist = NULL; 4449 outputCtx->numberoftriangles = 0; 4450 outputCtx->trianglelist = NULL; 4451 outputCtx->triangleattributelist = NULL; 4452 outputCtx->neighborlist = NULL; 4453 outputCtx->segmentlist = NULL; 4454 outputCtx->segmentmarkerlist = NULL; 4455 outputCtx->numberofedges = 0; 4456 outputCtx->edgelist = NULL; 4457 outputCtx->edgemarkerlist = NULL; 4458 PetscFunctionReturn(0); 4459 } 4460 4461 #undef __FUNCT__ 4462 #define __FUNCT__ "FiniOutput_Triangle" 4463 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4464 { 4465 PetscFunctionBegin; 4466 free(outputCtx->pointmarkerlist); 4467 free(outputCtx->edgelist); 4468 free(outputCtx->edgemarkerlist); 4469 free(outputCtx->trianglelist); 4470 free(outputCtx->neighborlist); 4471 PetscFunctionReturn(0); 4472 } 4473 4474 #undef __FUNCT__ 4475 #define __FUNCT__ "DMPlexGenerate_Triangle" 4476 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4477 { 4478 MPI_Comm comm; 4479 PetscInt dim = 2; 4480 const PetscBool createConvexHull = PETSC_FALSE; 4481 const PetscBool constrained = PETSC_FALSE; 4482 struct triangulateio in; 4483 struct triangulateio out; 4484 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4485 PetscMPIInt rank; 4486 PetscErrorCode ierr; 4487 4488 PetscFunctionBegin; 4489 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4490 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4491 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4492 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4493 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4494 4495 in.numberofpoints = vEnd - vStart; 4496 if (in.numberofpoints > 0) { 4497 PetscSection coordSection; 4498 Vec coordinates; 4499 PetscScalar *array; 4500 4501 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4502 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4503 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4504 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4505 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4506 for (v = vStart; v < vEnd; ++v) { 4507 const PetscInt idx = v - vStart; 4508 PetscInt off, d; 4509 4510 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4511 for (d = 0; d < dim; ++d) { 4512 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4513 } 4514 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4515 } 4516 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4517 } 4518 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4519 in.numberofsegments = eEnd - eStart; 4520 if (in.numberofsegments > 0) { 4521 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4522 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4523 for (e = eStart; e < eEnd; ++e) { 4524 const PetscInt idx = e - eStart; 4525 const PetscInt *cone; 4526 4527 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4528 4529 in.segmentlist[idx*2+0] = cone[0] - vStart; 4530 in.segmentlist[idx*2+1] = cone[1] - vStart; 4531 4532 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4533 } 4534 } 4535 #if 0 /* Do not currently support holes */ 4536 PetscReal *holeCoords; 4537 PetscInt h, d; 4538 4539 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4540 if (in.numberofholes > 0) { 4541 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4542 for (h = 0; h < in.numberofholes; ++h) { 4543 for (d = 0; d < dim; ++d) { 4544 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4545 } 4546 } 4547 } 4548 #endif 4549 if (!rank) { 4550 char args[32]; 4551 4552 /* Take away 'Q' for verbose output */ 4553 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4554 if (createConvexHull) { 4555 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4556 } 4557 if (constrained) { 4558 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4559 } 4560 triangulate(args, &in, &out, NULL); 4561 } 4562 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4563 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4564 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4565 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4566 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4567 4568 { 4569 const PetscInt numCorners = 3; 4570 const PetscInt numCells = out.numberoftriangles; 4571 const PetscInt numVertices = out.numberofpoints; 4572 const int *cells = out.trianglelist; 4573 const double *meshCoords = out.pointlist; 4574 4575 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4576 /* Set labels */ 4577 for (v = 0; v < numVertices; ++v) { 4578 if (out.pointmarkerlist[v]) { 4579 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4580 } 4581 } 4582 if (interpolate) { 4583 for (e = 0; e < out.numberofedges; e++) { 4584 if (out.edgemarkerlist[e]) { 4585 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4586 const PetscInt *edges; 4587 PetscInt numEdges; 4588 4589 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4590 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4591 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4592 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4593 } 4594 } 4595 } 4596 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4597 } 4598 #if 0 /* Do not currently support holes */ 4599 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4600 #endif 4601 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4602 PetscFunctionReturn(0); 4603 } 4604 4605 #undef __FUNCT__ 4606 #define __FUNCT__ "DMPlexRefine_Triangle" 4607 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4608 { 4609 MPI_Comm comm; 4610 PetscInt dim = 2; 4611 struct triangulateio in; 4612 struct triangulateio out; 4613 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4614 PetscMPIInt rank; 4615 PetscErrorCode ierr; 4616 4617 PetscFunctionBegin; 4618 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4619 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4620 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4621 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4622 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4623 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4624 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4625 4626 in.numberofpoints = vEnd - vStart; 4627 if (in.numberofpoints > 0) { 4628 PetscSection coordSection; 4629 Vec coordinates; 4630 PetscScalar *array; 4631 4632 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4633 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4634 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4635 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4636 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4637 for (v = vStart; v < vEnd; ++v) { 4638 const PetscInt idx = v - vStart; 4639 PetscInt off, d; 4640 4641 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4642 for (d = 0; d < dim; ++d) { 4643 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4644 } 4645 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4646 } 4647 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4648 } 4649 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4650 4651 in.numberofcorners = 3; 4652 in.numberoftriangles = cEnd - cStart; 4653 4654 in.trianglearealist = (double*) maxVolumes; 4655 if (in.numberoftriangles > 0) { 4656 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4657 for (c = cStart; c < cEnd; ++c) { 4658 const PetscInt idx = c - cStart; 4659 PetscInt *closure = NULL; 4660 PetscInt closureSize; 4661 4662 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4663 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4664 for (v = 0; v < 3; ++v) { 4665 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4666 } 4667 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4668 } 4669 } 4670 /* TODO: Segment markers are missing on input */ 4671 #if 0 /* Do not currently support holes */ 4672 PetscReal *holeCoords; 4673 PetscInt h, d; 4674 4675 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4676 if (in.numberofholes > 0) { 4677 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4678 for (h = 0; h < in.numberofholes; ++h) { 4679 for (d = 0; d < dim; ++d) { 4680 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4681 } 4682 } 4683 } 4684 #endif 4685 if (!rank) { 4686 char args[32]; 4687 4688 /* Take away 'Q' for verbose output */ 4689 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4690 triangulate(args, &in, &out, NULL); 4691 } 4692 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4693 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4694 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4695 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4696 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4697 4698 { 4699 const PetscInt numCorners = 3; 4700 const PetscInt numCells = out.numberoftriangles; 4701 const PetscInt numVertices = out.numberofpoints; 4702 const int *cells = out.trianglelist; 4703 const double *meshCoords = out.pointlist; 4704 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4705 4706 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4707 /* Set labels */ 4708 for (v = 0; v < numVertices; ++v) { 4709 if (out.pointmarkerlist[v]) { 4710 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4711 } 4712 } 4713 if (interpolate) { 4714 PetscInt e; 4715 4716 for (e = 0; e < out.numberofedges; e++) { 4717 if (out.edgemarkerlist[e]) { 4718 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4719 const PetscInt *edges; 4720 PetscInt numEdges; 4721 4722 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4723 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4724 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4725 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4726 } 4727 } 4728 } 4729 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4730 } 4731 #if 0 /* Do not currently support holes */ 4732 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4733 #endif 4734 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4735 PetscFunctionReturn(0); 4736 } 4737 #endif 4738 4739 #if defined(PETSC_HAVE_TETGEN) 4740 #include <tetgen.h> 4741 #undef __FUNCT__ 4742 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4743 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4744 { 4745 MPI_Comm comm; 4746 const PetscInt dim = 3; 4747 ::tetgenio in; 4748 ::tetgenio out; 4749 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4750 PetscMPIInt rank; 4751 PetscErrorCode ierr; 4752 4753 PetscFunctionBegin; 4754 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4755 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4756 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4757 in.numberofpoints = vEnd - vStart; 4758 if (in.numberofpoints > 0) { 4759 PetscSection coordSection; 4760 Vec coordinates; 4761 PetscScalar *array; 4762 4763 in.pointlist = new double[in.numberofpoints*dim]; 4764 in.pointmarkerlist = new int[in.numberofpoints]; 4765 4766 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4767 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4768 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4769 for (v = vStart; v < vEnd; ++v) { 4770 const PetscInt idx = v - vStart; 4771 PetscInt off, d; 4772 4773 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4774 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4775 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4776 } 4777 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4778 } 4779 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4780 4781 in.numberoffacets = fEnd - fStart; 4782 if (in.numberoffacets > 0) { 4783 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4784 in.facetmarkerlist = new int[in.numberoffacets]; 4785 for (f = fStart; f < fEnd; ++f) { 4786 const PetscInt idx = f - fStart; 4787 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 4788 4789 in.facetlist[idx].numberofpolygons = 1; 4790 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4791 in.facetlist[idx].numberofholes = 0; 4792 in.facetlist[idx].holelist = NULL; 4793 4794 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4795 for (p = 0; p < numPoints*2; p += 2) { 4796 const PetscInt point = points[p]; 4797 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 4798 } 4799 4800 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4801 poly->numberofvertices = numVertices; 4802 poly->vertexlist = new int[poly->numberofvertices]; 4803 for (v = 0; v < numVertices; ++v) { 4804 const PetscInt vIdx = points[v] - vStart; 4805 poly->vertexlist[v] = vIdx; 4806 } 4807 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4808 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4809 } 4810 } 4811 if (!rank) { 4812 char args[32]; 4813 4814 /* Take away 'Q' for verbose output */ 4815 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4816 ::tetrahedralize(args, &in, &out); 4817 } 4818 { 4819 const PetscInt numCorners = 4; 4820 const PetscInt numCells = out.numberoftetrahedra; 4821 const PetscInt numVertices = out.numberofpoints; 4822 const int *cells = out.tetrahedronlist; 4823 const double *meshCoords = out.pointlist; 4824 4825 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4826 /* Set labels */ 4827 for (v = 0; v < numVertices; ++v) { 4828 if (out.pointmarkerlist[v]) { 4829 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4830 } 4831 } 4832 if (interpolate) { 4833 PetscInt e; 4834 4835 for (e = 0; e < out.numberofedges; e++) { 4836 if (out.edgemarkerlist[e]) { 4837 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4838 const PetscInt *edges; 4839 PetscInt numEdges; 4840 4841 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4842 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4843 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4844 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4845 } 4846 } 4847 for (f = 0; f < out.numberoftrifaces; f++) { 4848 if (out.trifacemarkerlist[f]) { 4849 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4850 const PetscInt *faces; 4851 PetscInt numFaces; 4852 4853 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4854 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4855 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4856 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4857 } 4858 } 4859 } 4860 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4861 } 4862 PetscFunctionReturn(0); 4863 } 4864 4865 #undef __FUNCT__ 4866 #define __FUNCT__ "DMPlexRefine_Tetgen" 4867 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4868 { 4869 MPI_Comm comm; 4870 const PetscInt dim = 3; 4871 ::tetgenio in; 4872 ::tetgenio out; 4873 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4874 PetscMPIInt rank; 4875 PetscErrorCode ierr; 4876 4877 PetscFunctionBegin; 4878 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4879 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4880 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4881 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4882 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4883 4884 in.numberofpoints = vEnd - vStart; 4885 if (in.numberofpoints > 0) { 4886 PetscSection coordSection; 4887 Vec coordinates; 4888 PetscScalar *array; 4889 4890 in.pointlist = new double[in.numberofpoints*dim]; 4891 in.pointmarkerlist = new int[in.numberofpoints]; 4892 4893 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4894 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4895 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4896 for (v = vStart; v < vEnd; ++v) { 4897 const PetscInt idx = v - vStart; 4898 PetscInt off, d; 4899 4900 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4901 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4902 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4903 } 4904 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4905 } 4906 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4907 4908 in.numberofcorners = 4; 4909 in.numberoftetrahedra = cEnd - cStart; 4910 in.tetrahedronvolumelist = (double*) maxVolumes; 4911 if (in.numberoftetrahedra > 0) { 4912 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4913 for (c = cStart; c < cEnd; ++c) { 4914 const PetscInt idx = c - cStart; 4915 PetscInt *closure = NULL; 4916 PetscInt closureSize; 4917 4918 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4919 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 4920 for (v = 0; v < 4; ++v) { 4921 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4922 } 4923 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4924 } 4925 } 4926 /* TODO: Put in boundary faces with markers */ 4927 if (!rank) { 4928 char args[32]; 4929 4930 /* Take away 'Q' for verbose output */ 4931 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 4932 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4933 ::tetrahedralize(args, &in, &out); 4934 } 4935 in.tetrahedronvolumelist = NULL; 4936 4937 { 4938 const PetscInt numCorners = 4; 4939 const PetscInt numCells = out.numberoftetrahedra; 4940 const PetscInt numVertices = out.numberofpoints; 4941 const int *cells = out.tetrahedronlist; 4942 const double *meshCoords = out.pointlist; 4943 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4944 4945 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4946 /* Set labels */ 4947 for (v = 0; v < numVertices; ++v) { 4948 if (out.pointmarkerlist[v]) { 4949 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4950 } 4951 } 4952 if (interpolate) { 4953 PetscInt e, f; 4954 4955 for (e = 0; e < out.numberofedges; e++) { 4956 if (out.edgemarkerlist[e]) { 4957 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4958 const PetscInt *edges; 4959 PetscInt numEdges; 4960 4961 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4962 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4963 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4964 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4965 } 4966 } 4967 for (f = 0; f < out.numberoftrifaces; f++) { 4968 if (out.trifacemarkerlist[f]) { 4969 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4970 const PetscInt *faces; 4971 PetscInt numFaces; 4972 4973 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4974 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4975 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4976 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4977 } 4978 } 4979 } 4980 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4981 } 4982 PetscFunctionReturn(0); 4983 } 4984 #endif 4985 4986 #if defined(PETSC_HAVE_CTETGEN) 4987 #include "ctetgen.h" 4988 4989 #undef __FUNCT__ 4990 #define __FUNCT__ "DMPlexGenerate_CTetgen" 4991 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 4992 { 4993 MPI_Comm comm; 4994 const PetscInt dim = 3; 4995 PLC *in, *out; 4996 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 4997 PetscMPIInt rank; 4998 PetscErrorCode ierr; 4999 5000 PetscFunctionBegin; 5001 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5002 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5003 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5004 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5005 ierr = PLCCreate(&in);CHKERRQ(ierr); 5006 ierr = PLCCreate(&out);CHKERRQ(ierr); 5007 5008 in->numberofpoints = vEnd - vStart; 5009 if (in->numberofpoints > 0) { 5010 PetscSection coordSection; 5011 Vec coordinates; 5012 PetscScalar *array; 5013 5014 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5015 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5016 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5017 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5018 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5019 for (v = vStart; v < vEnd; ++v) { 5020 const PetscInt idx = v - vStart; 5021 PetscInt off, d, m; 5022 5023 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5024 for (d = 0; d < dim; ++d) { 5025 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5026 } 5027 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5028 5029 in->pointmarkerlist[idx] = (int) m; 5030 } 5031 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5032 } 5033 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5034 5035 in->numberoffacets = fEnd - fStart; 5036 if (in->numberoffacets > 0) { 5037 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5038 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5039 for (f = fStart; f < fEnd; ++f) { 5040 const PetscInt idx = f - fStart; 5041 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5042 polygon *poly; 5043 5044 in->facetlist[idx].numberofpolygons = 1; 5045 5046 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5047 5048 in->facetlist[idx].numberofholes = 0; 5049 in->facetlist[idx].holelist = NULL; 5050 5051 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5052 for (p = 0; p < numPoints*2; p += 2) { 5053 const PetscInt point = points[p]; 5054 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5055 } 5056 5057 poly = in->facetlist[idx].polygonlist; 5058 poly->numberofvertices = numVertices; 5059 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5060 for (v = 0; v < numVertices; ++v) { 5061 const PetscInt vIdx = points[v] - vStart; 5062 poly->vertexlist[v] = vIdx; 5063 } 5064 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5065 in->facetmarkerlist[idx] = (int) m; 5066 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5067 } 5068 } 5069 if (!rank) { 5070 TetGenOpts t; 5071 5072 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5073 t.in = boundary; /* Should go away */ 5074 t.plc = 1; 5075 t.quality = 1; 5076 t.edgesout = 1; 5077 t.zeroindex = 1; 5078 t.quiet = 1; 5079 t.verbose = verbose; 5080 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5081 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5082 } 5083 { 5084 const PetscInt numCorners = 4; 5085 const PetscInt numCells = out->numberoftetrahedra; 5086 const PetscInt numVertices = out->numberofpoints; 5087 const int *cells = out->tetrahedronlist; 5088 const double *meshCoords = out->pointlist; 5089 5090 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 5091 /* Set labels */ 5092 for (v = 0; v < numVertices; ++v) { 5093 if (out->pointmarkerlist[v]) { 5094 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5095 } 5096 } 5097 if (interpolate) { 5098 PetscInt e; 5099 5100 for (e = 0; e < out->numberofedges; e++) { 5101 if (out->edgemarkerlist[e]) { 5102 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5103 const PetscInt *edges; 5104 PetscInt numEdges; 5105 5106 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5107 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5108 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5109 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5110 } 5111 } 5112 for (f = 0; f < out->numberoftrifaces; f++) { 5113 if (out->trifacemarkerlist[f]) { 5114 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5115 const PetscInt *faces; 5116 PetscInt numFaces; 5117 5118 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5119 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5120 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5121 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5122 } 5123 } 5124 } 5125 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5126 } 5127 5128 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5129 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5130 PetscFunctionReturn(0); 5131 } 5132 5133 #undef __FUNCT__ 5134 #define __FUNCT__ "DMPlexRefine_CTetgen" 5135 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5136 { 5137 MPI_Comm comm; 5138 const PetscInt dim = 3; 5139 PLC *in, *out; 5140 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5141 PetscMPIInt rank; 5142 PetscErrorCode ierr; 5143 5144 PetscFunctionBegin; 5145 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5146 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5147 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5148 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5149 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5150 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5151 ierr = PLCCreate(&in);CHKERRQ(ierr); 5152 ierr = PLCCreate(&out);CHKERRQ(ierr); 5153 5154 in->numberofpoints = vEnd - vStart; 5155 if (in->numberofpoints > 0) { 5156 PetscSection coordSection; 5157 Vec coordinates; 5158 PetscScalar *array; 5159 5160 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5161 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5162 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5163 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5164 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5165 for (v = vStart; v < vEnd; ++v) { 5166 const PetscInt idx = v - vStart; 5167 PetscInt off, d, m; 5168 5169 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5170 for (d = 0; d < dim; ++d) { 5171 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5172 } 5173 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5174 5175 in->pointmarkerlist[idx] = (int) m; 5176 } 5177 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5178 } 5179 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5180 5181 in->numberofcorners = 4; 5182 in->numberoftetrahedra = cEnd - cStart; 5183 in->tetrahedronvolumelist = maxVolumes; 5184 if (in->numberoftetrahedra > 0) { 5185 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5186 for (c = cStart; c < cEnd; ++c) { 5187 const PetscInt idx = c - cStart; 5188 PetscInt *closure = NULL; 5189 PetscInt closureSize; 5190 5191 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5192 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5193 for (v = 0; v < 4; ++v) { 5194 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5195 } 5196 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5197 } 5198 } 5199 if (!rank) { 5200 TetGenOpts t; 5201 5202 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5203 5204 t.in = dm; /* Should go away */ 5205 t.refine = 1; 5206 t.varvolume = 1; 5207 t.quality = 1; 5208 t.edgesout = 1; 5209 t.zeroindex = 1; 5210 t.quiet = 1; 5211 t.verbose = verbose; /* Change this */ 5212 5213 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5214 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5215 } 5216 { 5217 const PetscInt numCorners = 4; 5218 const PetscInt numCells = out->numberoftetrahedra; 5219 const PetscInt numVertices = out->numberofpoints; 5220 const int *cells = out->tetrahedronlist; 5221 const double *meshCoords = out->pointlist; 5222 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5223 5224 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 5225 /* Set labels */ 5226 for (v = 0; v < numVertices; ++v) { 5227 if (out->pointmarkerlist[v]) { 5228 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5229 } 5230 } 5231 if (interpolate) { 5232 PetscInt e, f; 5233 5234 for (e = 0; e < out->numberofedges; e++) { 5235 if (out->edgemarkerlist[e]) { 5236 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5237 const PetscInt *edges; 5238 PetscInt numEdges; 5239 5240 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5241 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5242 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5243 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5244 } 5245 } 5246 for (f = 0; f < out->numberoftrifaces; f++) { 5247 if (out->trifacemarkerlist[f]) { 5248 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5249 const PetscInt *faces; 5250 PetscInt numFaces; 5251 5252 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5253 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5254 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5255 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5256 } 5257 } 5258 } 5259 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5260 } 5261 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5262 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5263 PetscFunctionReturn(0); 5264 } 5265 #endif 5266 5267 #undef __FUNCT__ 5268 #define __FUNCT__ "DMPlexGenerate" 5269 /*@C 5270 DMPlexGenerate - Generates a mesh. 5271 5272 Not Collective 5273 5274 Input Parameters: 5275 + boundary - The DMPlex boundary object 5276 . name - The mesh generation package name 5277 - interpolate - Flag to create intermediate mesh elements 5278 5279 Output Parameter: 5280 . mesh - The DMPlex object 5281 5282 Level: intermediate 5283 5284 .keywords: mesh, elements 5285 .seealso: DMPlexCreate(), DMRefine() 5286 @*/ 5287 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5288 { 5289 PetscInt dim; 5290 char genname[1024]; 5291 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5292 PetscErrorCode ierr; 5293 5294 PetscFunctionBegin; 5295 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5296 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5297 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5298 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5299 if (flg) name = genname; 5300 if (name) { 5301 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5302 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5303 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5304 } 5305 switch (dim) { 5306 case 1: 5307 if (!name || isTriangle) { 5308 #if defined(PETSC_HAVE_TRIANGLE) 5309 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5310 #else 5311 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5312 #endif 5313 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5314 break; 5315 case 2: 5316 if (!name || isCTetgen) { 5317 #if defined(PETSC_HAVE_CTETGEN) 5318 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5319 #else 5320 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5321 #endif 5322 } else if (isTetgen) { 5323 #if defined(PETSC_HAVE_TETGEN) 5324 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5325 #else 5326 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5327 #endif 5328 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5329 break; 5330 default: 5331 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5332 } 5333 PetscFunctionReturn(0); 5334 } 5335 5336 typedef PetscInt CellRefiner; 5337 5338 #undef __FUNCT__ 5339 #define __FUNCT__ "GetDepthStart_Private" 5340 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5341 { 5342 PetscFunctionBegin; 5343 if (cStart) *cStart = 0; 5344 if (vStart) *vStart = depthSize[depth]; 5345 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5346 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5347 PetscFunctionReturn(0); 5348 } 5349 5350 #undef __FUNCT__ 5351 #define __FUNCT__ "GetDepthEnd_Private" 5352 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5353 { 5354 PetscFunctionBegin; 5355 if (cEnd) *cEnd = depthSize[depth]; 5356 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5357 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5358 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5359 PetscFunctionReturn(0); 5360 } 5361 5362 #undef __FUNCT__ 5363 #define __FUNCT__ "CellRefinerGetSizes" 5364 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5365 { 5366 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5367 PetscErrorCode ierr; 5368 5369 PetscFunctionBegin; 5370 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5371 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5372 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5373 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5374 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5375 switch (refiner) { 5376 case 1: 5377 /* Simplicial 2D */ 5378 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5379 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5380 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5381 break; 5382 case 3: 5383 /* Hybrid 2D */ 5384 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5385 cMax = PetscMin(cEnd, cMax); 5386 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5387 fMax = PetscMin(fEnd, fMax); 5388 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5389 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 */ 5390 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5391 break; 5392 case 2: 5393 /* Hex 2D */ 5394 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5395 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5396 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5397 break; 5398 default: 5399 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5400 } 5401 PetscFunctionReturn(0); 5402 } 5403 5404 #undef __FUNCT__ 5405 #define __FUNCT__ "CellRefinerSetConeSizes" 5406 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5407 { 5408 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5409 PetscErrorCode ierr; 5410 5411 PetscFunctionBegin; 5412 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5413 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5414 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5415 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5416 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5417 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5418 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5419 switch (refiner) { 5420 case 1: 5421 /* Simplicial 2D */ 5422 /* All cells have 3 faces */ 5423 for (c = cStart; c < cEnd; ++c) { 5424 for (r = 0; r < 4; ++r) { 5425 const PetscInt newp = (c - cStart)*4 + r; 5426 5427 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5428 } 5429 } 5430 /* Split faces have 2 vertices and the same cells as the parent */ 5431 for (f = fStart; f < fEnd; ++f) { 5432 for (r = 0; r < 2; ++r) { 5433 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5434 PetscInt size; 5435 5436 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5437 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5438 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5439 } 5440 } 5441 /* Interior faces have 2 vertices and 2 cells */ 5442 for (c = cStart; c < cEnd; ++c) { 5443 for (r = 0; r < 3; ++r) { 5444 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5445 5446 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5447 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5448 } 5449 } 5450 /* Old vertices have identical supports */ 5451 for (v = vStart; v < vEnd; ++v) { 5452 const PetscInt newp = vStartNew + (v - vStart); 5453 PetscInt size; 5454 5455 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5456 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5457 } 5458 /* Face vertices have 2 + cells*2 supports */ 5459 for (f = fStart; f < fEnd; ++f) { 5460 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5461 PetscInt size; 5462 5463 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5464 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5465 } 5466 break; 5467 case 2: 5468 /* Hex 2D */ 5469 /* All cells have 4 faces */ 5470 for (c = cStart; c < cEnd; ++c) { 5471 for (r = 0; r < 4; ++r) { 5472 const PetscInt newp = (c - cStart)*4 + r; 5473 5474 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5475 } 5476 } 5477 /* Split faces have 2 vertices and the same cells as the parent */ 5478 for (f = fStart; f < fEnd; ++f) { 5479 for (r = 0; r < 2; ++r) { 5480 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5481 PetscInt size; 5482 5483 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5484 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5485 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5486 } 5487 } 5488 /* Interior faces have 2 vertices and 2 cells */ 5489 for (c = cStart; c < cEnd; ++c) { 5490 for (r = 0; r < 4; ++r) { 5491 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5492 5493 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5494 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5495 } 5496 } 5497 /* Old vertices have identical supports */ 5498 for (v = vStart; v < vEnd; ++v) { 5499 const PetscInt newp = vStartNew + (v - vStart); 5500 PetscInt size; 5501 5502 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5503 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5504 } 5505 /* Face vertices have 2 + cells supports */ 5506 for (f = fStart; f < fEnd; ++f) { 5507 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5508 PetscInt size; 5509 5510 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5511 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5512 } 5513 /* Cell vertices have 4 supports */ 5514 for (c = cStart; c < cEnd; ++c) { 5515 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5516 5517 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5518 } 5519 break; 5520 case 3: 5521 /* Hybrid 2D */ 5522 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5523 cMax = PetscMin(cEnd, cMax); 5524 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5525 fMax = PetscMin(fEnd, fMax); 5526 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5527 /* Interior cells have 3 faces */ 5528 for (c = cStart; c < cMax; ++c) { 5529 for (r = 0; r < 4; ++r) { 5530 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5531 5532 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5533 } 5534 } 5535 /* Hybrid cells have 4 faces */ 5536 for (c = cMax; c < cEnd; ++c) { 5537 for (r = 0; r < 2; ++r) { 5538 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5539 5540 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5541 } 5542 } 5543 /* Interior split faces have 2 vertices and the same cells as the parent */ 5544 for (f = fStart; f < fMax; ++f) { 5545 for (r = 0; r < 2; ++r) { 5546 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5547 PetscInt size; 5548 5549 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5550 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5551 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5552 } 5553 } 5554 /* Interior cell faces have 2 vertices and 2 cells */ 5555 for (c = cStart; c < cMax; ++c) { 5556 for (r = 0; r < 3; ++r) { 5557 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5558 5559 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5560 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5561 } 5562 } 5563 /* Hybrid faces have 2 vertices and the same cells */ 5564 for (f = fMax; f < fEnd; ++f) { 5565 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5566 PetscInt size; 5567 5568 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5569 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5570 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5571 } 5572 /* Hybrid cell faces have 2 vertices and 2 cells */ 5573 for (c = cMax; c < cEnd; ++c) { 5574 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5575 5576 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5577 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5578 } 5579 /* Old vertices have identical supports */ 5580 for (v = vStart; v < vEnd; ++v) { 5581 const PetscInt newp = vStartNew + (v - vStart); 5582 PetscInt size; 5583 5584 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5585 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5586 } 5587 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5588 for (f = fStart; f < fMax; ++f) { 5589 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5590 const PetscInt *support; 5591 PetscInt size, newSize = 2, s; 5592 5593 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5594 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5595 for (s = 0; s < size; ++s) { 5596 if (support[s] >= cMax) newSize += 1; 5597 else newSize += 2; 5598 } 5599 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5600 } 5601 break; 5602 default: 5603 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5604 } 5605 PetscFunctionReturn(0); 5606 } 5607 5608 #undef __FUNCT__ 5609 #define __FUNCT__ "CellRefinerSetCones" 5610 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5611 { 5612 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; 5613 PetscInt maxSupportSize, *supportRef; 5614 PetscErrorCode ierr; 5615 5616 PetscFunctionBegin; 5617 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5618 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5619 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5620 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5621 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5622 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5623 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5624 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5625 switch (refiner) { 5626 case 1: 5627 /* Simplicial 2D */ 5628 /* 5629 2 5630 |\ 5631 | \ 5632 | \ 5633 | \ 5634 | C \ 5635 | \ 5636 | \ 5637 2---1---1 5638 |\ D / \ 5639 | 2 0 \ 5640 |A \ / B \ 5641 0---0-------1 5642 */ 5643 /* All cells have 3 faces */ 5644 for (c = cStart; c < cEnd; ++c) { 5645 const PetscInt newp = cStartNew + (c - cStart)*4; 5646 const PetscInt *cone, *ornt; 5647 PetscInt coneNew[3], orntNew[3]; 5648 5649 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5650 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5651 /* A triangle */ 5652 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5653 orntNew[0] = ornt[0]; 5654 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5655 orntNew[1] = -2; 5656 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5657 orntNew[2] = ornt[2]; 5658 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5659 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5660 #if 1 5661 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5662 for (p = 0; p < 3; ++p) { 5663 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5664 } 5665 #endif 5666 /* B triangle */ 5667 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5668 orntNew[0] = ornt[0]; 5669 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5670 orntNew[1] = ornt[1]; 5671 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5672 orntNew[2] = -2; 5673 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5674 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5675 #if 1 5676 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 5677 for (p = 0; p < 3; ++p) { 5678 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5679 } 5680 #endif 5681 /* C triangle */ 5682 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5683 orntNew[0] = -2; 5684 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5685 orntNew[1] = ornt[1]; 5686 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5687 orntNew[2] = ornt[2]; 5688 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5689 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5690 #if 1 5691 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 5692 for (p = 0; p < 3; ++p) { 5693 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5694 } 5695 #endif 5696 /* D triangle */ 5697 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5698 orntNew[0] = 0; 5699 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5700 orntNew[1] = 0; 5701 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5702 orntNew[2] = 0; 5703 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5704 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5705 #if 1 5706 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 5707 for (p = 0; p < 3; ++p) { 5708 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5709 } 5710 #endif 5711 } 5712 /* Split faces have 2 vertices and the same cells as the parent */ 5713 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5714 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5715 for (f = fStart; f < fEnd; ++f) { 5716 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5717 5718 for (r = 0; r < 2; ++r) { 5719 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5720 const PetscInt *cone, *support; 5721 PetscInt coneNew[2], coneSize, c, supportSize, s; 5722 5723 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5724 coneNew[0] = vStartNew + (cone[0] - vStart); 5725 coneNew[1] = vStartNew + (cone[1] - vStart); 5726 coneNew[(r+1)%2] = newv; 5727 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5728 #if 1 5729 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5730 for (p = 0; p < 2; ++p) { 5731 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5732 } 5733 #endif 5734 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5735 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5736 for (s = 0; s < supportSize; ++s) { 5737 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5738 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5739 for (c = 0; c < coneSize; ++c) { 5740 if (cone[c] == f) break; 5741 } 5742 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5743 } 5744 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5745 #if 1 5746 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5747 for (p = 0; p < supportSize; ++p) { 5748 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 5749 } 5750 #endif 5751 } 5752 } 5753 /* Interior faces have 2 vertices and 2 cells */ 5754 for (c = cStart; c < cEnd; ++c) { 5755 const PetscInt *cone; 5756 5757 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5758 for (r = 0; r < 3; ++r) { 5759 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5760 PetscInt coneNew[2]; 5761 PetscInt supportNew[2]; 5762 5763 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5764 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5765 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5766 #if 1 5767 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5768 for (p = 0; p < 2; ++p) { 5769 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5770 } 5771 #endif 5772 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5773 supportNew[1] = (c - cStart)*4 + 3; 5774 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5775 #if 1 5776 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5777 for (p = 0; p < 2; ++p) { 5778 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5779 } 5780 #endif 5781 } 5782 } 5783 /* Old vertices have identical supports */ 5784 for (v = vStart; v < vEnd; ++v) { 5785 const PetscInt newp = vStartNew + (v - vStart); 5786 const PetscInt *support, *cone; 5787 PetscInt size, s; 5788 5789 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5790 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5791 for (s = 0; s < size; ++s) { 5792 PetscInt r = 0; 5793 5794 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5795 if (cone[1] == v) r = 1; 5796 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5797 } 5798 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5799 #if 1 5800 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5801 for (p = 0; p < size; ++p) { 5802 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5803 } 5804 #endif 5805 } 5806 /* Face vertices have 2 + cells*2 supports */ 5807 for (f = fStart; f < fEnd; ++f) { 5808 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5809 const PetscInt *cone, *support; 5810 PetscInt size, s; 5811 5812 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5813 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5814 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5815 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5816 for (s = 0; s < size; ++s) { 5817 PetscInt r = 0; 5818 5819 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5820 if (cone[1] == f) r = 1; 5821 else if (cone[2] == f) r = 2; 5822 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5823 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5824 } 5825 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5826 #if 1 5827 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5828 for (p = 0; p < 2+size*2; ++p) { 5829 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5830 } 5831 #endif 5832 } 5833 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5834 break; 5835 case 2: 5836 /* Hex 2D */ 5837 /* 5838 3---------2---------2 5839 | | | 5840 | D 2 C | 5841 | | | 5842 3----3----0----1----1 5843 | | | 5844 | A 0 B | 5845 | | | 5846 0---------0---------1 5847 */ 5848 /* All cells have 4 faces */ 5849 for (c = cStart; c < cEnd; ++c) { 5850 const PetscInt newp = (c - cStart)*4; 5851 const PetscInt *cone, *ornt; 5852 PetscInt coneNew[4], orntNew[4]; 5853 5854 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5855 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5856 /* A quad */ 5857 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5858 orntNew[0] = ornt[0]; 5859 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5860 orntNew[1] = 0; 5861 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5862 orntNew[2] = -2; 5863 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5864 orntNew[3] = ornt[3]; 5865 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5866 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5867 #if 1 5868 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5869 for (p = 0; p < 4; ++p) { 5870 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5871 } 5872 #endif 5873 /* B quad */ 5874 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5875 orntNew[0] = ornt[0]; 5876 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5877 orntNew[1] = ornt[1]; 5878 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5879 orntNew[2] = 0; 5880 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5881 orntNew[3] = -2; 5882 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5883 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5884 #if 1 5885 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 5886 for (p = 0; p < 4; ++p) { 5887 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5888 } 5889 #endif 5890 /* C quad */ 5891 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5892 orntNew[0] = -2; 5893 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5894 orntNew[1] = ornt[1]; 5895 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5896 orntNew[2] = ornt[2]; 5897 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5898 orntNew[3] = 0; 5899 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5900 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5901 #if 1 5902 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 5903 for (p = 0; p < 4; ++p) { 5904 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5905 } 5906 #endif 5907 /* D quad */ 5908 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5909 orntNew[0] = 0; 5910 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5911 orntNew[1] = -2; 5912 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5913 orntNew[2] = ornt[2]; 5914 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5915 orntNew[3] = ornt[3]; 5916 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5917 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5918 #if 1 5919 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 5920 for (p = 0; p < 4; ++p) { 5921 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5922 } 5923 #endif 5924 } 5925 /* Split faces have 2 vertices and the same cells as the parent */ 5926 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5927 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5928 for (f = fStart; f < fEnd; ++f) { 5929 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5930 5931 for (r = 0; r < 2; ++r) { 5932 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5933 const PetscInt *cone, *support; 5934 PetscInt coneNew[2], coneSize, c, supportSize, s; 5935 5936 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5937 coneNew[0] = vStartNew + (cone[0] - vStart); 5938 coneNew[1] = vStartNew + (cone[1] - vStart); 5939 coneNew[(r+1)%2] = newv; 5940 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5941 #if 1 5942 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5943 for (p = 0; p < 2; ++p) { 5944 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5945 } 5946 #endif 5947 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5948 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5949 for (s = 0; s < supportSize; ++s) { 5950 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5951 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5952 for (c = 0; c < coneSize; ++c) { 5953 if (cone[c] == f) break; 5954 } 5955 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5956 } 5957 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5958 #if 1 5959 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5960 for (p = 0; p < supportSize; ++p) { 5961 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 5962 } 5963 #endif 5964 } 5965 } 5966 /* Interior faces have 2 vertices and 2 cells */ 5967 for (c = cStart; c < cEnd; ++c) { 5968 const PetscInt *cone; 5969 PetscInt coneNew[2], supportNew[2]; 5970 5971 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5972 for (r = 0; r < 4; ++r) { 5973 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5974 5975 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5976 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5977 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5978 #if 1 5979 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5980 for (p = 0; p < 2; ++p) { 5981 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5982 } 5983 #endif 5984 supportNew[0] = (c - cStart)*4 + r; 5985 supportNew[1] = (c - cStart)*4 + (r+1)%4; 5986 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5987 #if 1 5988 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5989 for (p = 0; p < 2; ++p) { 5990 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5991 } 5992 #endif 5993 } 5994 } 5995 /* Old vertices have identical supports */ 5996 for (v = vStart; v < vEnd; ++v) { 5997 const PetscInt newp = vStartNew + (v - vStart); 5998 const PetscInt *support, *cone; 5999 PetscInt size, s; 6000 6001 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6002 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6003 for (s = 0; s < size; ++s) { 6004 PetscInt r = 0; 6005 6006 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6007 if (cone[1] == v) r = 1; 6008 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6009 } 6010 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6011 #if 1 6012 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6013 for (p = 0; p < size; ++p) { 6014 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6015 } 6016 #endif 6017 } 6018 /* Face vertices have 2 + cells supports */ 6019 for (f = fStart; f < fEnd; ++f) { 6020 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6021 const PetscInt *cone, *support; 6022 PetscInt size, s; 6023 6024 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6025 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6026 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6027 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6028 for (s = 0; s < size; ++s) { 6029 PetscInt r = 0; 6030 6031 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6032 if (cone[1] == f) r = 1; 6033 else if (cone[2] == f) r = 2; 6034 else if (cone[3] == f) r = 3; 6035 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6036 } 6037 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6038 #if 1 6039 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6040 for (p = 0; p < 2+size; ++p) { 6041 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6042 } 6043 #endif 6044 } 6045 /* Cell vertices have 4 supports */ 6046 for (c = cStart; c < cEnd; ++c) { 6047 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6048 PetscInt supportNew[4]; 6049 6050 for (r = 0; r < 4; ++r) { 6051 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6052 } 6053 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6054 } 6055 break; 6056 case 3: 6057 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6058 cMax = PetscMin(cEnd, cMax); 6059 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6060 fMax = PetscMin(fEnd, fMax); 6061 /* Interior cells have 3 faces */ 6062 for (c = cStart; c < cMax; ++c) { 6063 const PetscInt newp = cStartNew + (c - cStart)*4; 6064 const PetscInt *cone, *ornt; 6065 PetscInt coneNew[3], orntNew[3]; 6066 6067 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6068 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6069 /* A triangle */ 6070 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6071 orntNew[0] = ornt[0]; 6072 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6073 orntNew[1] = -2; 6074 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6075 orntNew[2] = ornt[2]; 6076 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6077 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6078 #if 1 6079 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6080 for (p = 0; p < 3; ++p) { 6081 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6082 } 6083 #endif 6084 /* B triangle */ 6085 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6086 orntNew[0] = ornt[0]; 6087 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6088 orntNew[1] = ornt[1]; 6089 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6090 orntNew[2] = -2; 6091 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6092 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6093 #if 1 6094 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6095 for (p = 0; p < 3; ++p) { 6096 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6097 } 6098 #endif 6099 /* C triangle */ 6100 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6101 orntNew[0] = -2; 6102 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6103 orntNew[1] = ornt[1]; 6104 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6105 orntNew[2] = ornt[2]; 6106 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6107 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6108 #if 1 6109 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6110 for (p = 0; p < 3; ++p) { 6111 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6112 } 6113 #endif 6114 /* D triangle */ 6115 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6116 orntNew[0] = 0; 6117 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6118 orntNew[1] = 0; 6119 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6120 orntNew[2] = 0; 6121 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6122 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6123 #if 1 6124 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6125 for (p = 0; p < 3; ++p) { 6126 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6127 } 6128 #endif 6129 } 6130 /* 6131 2----3----3 6132 | | 6133 | B | 6134 | | 6135 0----4--- 1 6136 | | 6137 | A | 6138 | | 6139 0----2----1 6140 */ 6141 /* Hybrid cells have 4 faces */ 6142 for (c = cMax; c < cEnd; ++c) { 6143 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6144 const PetscInt *cone, *ornt; 6145 PetscInt coneNew[4], orntNew[4]; 6146 6147 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6148 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6149 /* A quad */ 6150 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6151 orntNew[0] = ornt[0]; 6152 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6153 orntNew[1] = ornt[1]; 6154 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6155 orntNew[2] = 0; 6156 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6157 orntNew[3] = 0; 6158 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6159 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6160 #if 1 6161 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6162 for (p = 0; p < 4; ++p) { 6163 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6164 } 6165 #endif 6166 /* B quad */ 6167 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6168 orntNew[0] = ornt[0]; 6169 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6170 orntNew[1] = ornt[1]; 6171 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6172 orntNew[2] = 0; 6173 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6174 orntNew[3] = 0; 6175 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6176 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6177 #if 1 6178 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6179 for (p = 0; p < 4; ++p) { 6180 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6181 } 6182 #endif 6183 } 6184 /* Interior split faces have 2 vertices and the same cells as the parent */ 6185 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6186 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6187 for (f = fStart; f < fMax; ++f) { 6188 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6189 6190 for (r = 0; r < 2; ++r) { 6191 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6192 const PetscInt *cone, *support; 6193 PetscInt coneNew[2], coneSize, c, supportSize, s; 6194 6195 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6196 coneNew[0] = vStartNew + (cone[0] - vStart); 6197 coneNew[1] = vStartNew + (cone[1] - vStart); 6198 coneNew[(r+1)%2] = newv; 6199 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6200 #if 1 6201 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6202 for (p = 0; p < 2; ++p) { 6203 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6204 } 6205 #endif 6206 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6207 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6208 for (s = 0; s < supportSize; ++s) { 6209 if (support[s] >= cMax) { 6210 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6211 } else { 6212 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6213 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6214 for (c = 0; c < coneSize; ++c) { 6215 if (cone[c] == f) break; 6216 } 6217 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6218 } 6219 } 6220 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6221 #if 1 6222 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6223 for (p = 0; p < supportSize; ++p) { 6224 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6225 } 6226 #endif 6227 } 6228 } 6229 /* Interior cell faces have 2 vertices and 2 cells */ 6230 for (c = cStart; c < cMax; ++c) { 6231 const PetscInt *cone; 6232 6233 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6234 for (r = 0; r < 3; ++r) { 6235 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6236 PetscInt coneNew[2]; 6237 PetscInt supportNew[2]; 6238 6239 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6240 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6241 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6242 #if 1 6243 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6244 for (p = 0; p < 2; ++p) { 6245 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6246 } 6247 #endif 6248 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6249 supportNew[1] = (c - cStart)*4 + 3; 6250 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6251 #if 1 6252 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6253 for (p = 0; p < 2; ++p) { 6254 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6255 } 6256 #endif 6257 } 6258 } 6259 /* Interior hybrid faces have 2 vertices and the same cells */ 6260 for (f = fMax; f < fEnd; ++f) { 6261 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6262 const PetscInt *cone; 6263 const PetscInt *support; 6264 PetscInt coneNew[2]; 6265 PetscInt supportNew[2]; 6266 PetscInt size, s, r; 6267 6268 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6269 coneNew[0] = vStartNew + (cone[0] - vStart); 6270 coneNew[1] = vStartNew + (cone[1] - vStart); 6271 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6272 #if 1 6273 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6274 for (p = 0; p < 2; ++p) { 6275 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6276 } 6277 #endif 6278 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6279 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6280 for (s = 0; s < size; ++s) { 6281 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6282 for (r = 0; r < 2; ++r) { 6283 if (cone[r+2] == f) break; 6284 } 6285 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6286 } 6287 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6288 #if 1 6289 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6290 for (p = 0; p < size; ++p) { 6291 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6292 } 6293 #endif 6294 } 6295 /* Cell hybrid faces have 2 vertices and 2 cells */ 6296 for (c = cMax; c < cEnd; ++c) { 6297 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6298 const PetscInt *cone; 6299 PetscInt coneNew[2]; 6300 PetscInt supportNew[2]; 6301 6302 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6303 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6304 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6305 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6306 #if 1 6307 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6308 for (p = 0; p < 2; ++p) { 6309 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6310 } 6311 #endif 6312 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6313 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6314 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6315 #if 1 6316 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6317 for (p = 0; p < 2; ++p) { 6318 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6319 } 6320 #endif 6321 } 6322 /* Old vertices have identical supports */ 6323 for (v = vStart; v < vEnd; ++v) { 6324 const PetscInt newp = vStartNew + (v - vStart); 6325 const PetscInt *support, *cone; 6326 PetscInt size, s; 6327 6328 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6329 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6330 for (s = 0; s < size; ++s) { 6331 if (support[s] >= fMax) { 6332 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6333 } else { 6334 PetscInt r = 0; 6335 6336 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6337 if (cone[1] == v) r = 1; 6338 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6339 } 6340 } 6341 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6342 #if 1 6343 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6344 for (p = 0; p < size; ++p) { 6345 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6346 } 6347 #endif 6348 } 6349 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6350 for (f = fStart; f < fMax; ++f) { 6351 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6352 const PetscInt *cone, *support; 6353 PetscInt size, newSize = 2, s; 6354 6355 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6356 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6357 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6358 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6359 for (s = 0; s < size; ++s) { 6360 PetscInt r = 0; 6361 6362 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6363 if (support[s] >= cMax) { 6364 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6365 6366 newSize += 1; 6367 } else { 6368 if (cone[1] == f) r = 1; 6369 else if (cone[2] == f) r = 2; 6370 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6371 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6372 6373 newSize += 2; 6374 } 6375 } 6376 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6377 #if 1 6378 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6379 for (p = 0; p < newSize; ++p) { 6380 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6381 } 6382 #endif 6383 } 6384 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6385 break; 6386 default: 6387 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6388 } 6389 PetscFunctionReturn(0); 6390 } 6391 6392 #undef __FUNCT__ 6393 #define __FUNCT__ "CellRefinerSetCoordinates" 6394 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6395 { 6396 PetscSection coordSection, coordSectionNew; 6397 Vec coordinates, coordinatesNew; 6398 PetscScalar *coords, *coordsNew; 6399 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6400 PetscErrorCode ierr; 6401 6402 PetscFunctionBegin; 6403 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6404 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6405 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6406 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6407 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6408 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6409 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6410 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6411 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6412 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6413 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6414 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6415 if (fMax < 0) fMax = fEnd; 6416 switch (refiner) { 6417 case 1: 6418 case 2: 6419 case 3: 6420 /* Simplicial and Hex 2D */ 6421 /* All vertices have the dim coordinates */ 6422 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6423 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6424 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6425 } 6426 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6427 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6428 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6429 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6430 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6431 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6432 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6433 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6434 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6435 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6436 /* Old vertices have the same coordinates */ 6437 for (v = vStart; v < vEnd; ++v) { 6438 const PetscInt newv = vStartNew + (v - vStart); 6439 PetscInt off, offnew, d; 6440 6441 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6442 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6443 for (d = 0; d < dim; ++d) { 6444 coordsNew[offnew+d] = coords[off+d]; 6445 } 6446 } 6447 /* Face vertices have the average of endpoint coordinates */ 6448 for (f = fStart; f < fMax; ++f) { 6449 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6450 const PetscInt *cone; 6451 PetscInt coneSize, offA, offB, offnew, d; 6452 6453 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6454 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6455 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6456 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6457 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6458 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6459 for (d = 0; d < dim; ++d) { 6460 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6461 } 6462 } 6463 /* Just Hex 2D */ 6464 if (refiner == 2) { 6465 /* Cell vertices have the average of corner coordinates */ 6466 for (c = cStart; c < cEnd; ++c) { 6467 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6468 PetscInt *cone = NULL; 6469 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6470 6471 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6472 for (p = 0; p < closureSize*2; p += 2) { 6473 const PetscInt point = cone[p]; 6474 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6475 } 6476 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6477 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6478 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6479 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6480 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6481 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6482 for (d = 0; d < dim; ++d) { 6483 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6484 } 6485 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6486 } 6487 } 6488 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6489 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6490 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6491 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6492 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 6493 break; 6494 default: 6495 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6496 } 6497 PetscFunctionReturn(0); 6498 } 6499 6500 #undef __FUNCT__ 6501 #define __FUNCT__ "DMPlexCreateProcessSF" 6502 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6503 { 6504 PetscInt numRoots, numLeaves, l; 6505 const PetscInt *localPoints; 6506 const PetscSFNode *remotePoints; 6507 PetscInt *localPointsNew; 6508 PetscSFNode *remotePointsNew; 6509 PetscInt *ranks, *ranksNew; 6510 PetscErrorCode ierr; 6511 6512 PetscFunctionBegin; 6513 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6514 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6515 for (l = 0; l < numLeaves; ++l) { 6516 ranks[l] = remotePoints[l].rank; 6517 } 6518 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6519 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6520 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6521 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6522 for (l = 0; l < numLeaves; ++l) { 6523 ranksNew[l] = ranks[l]; 6524 localPointsNew[l] = l; 6525 remotePointsNew[l].index = 0; 6526 remotePointsNew[l].rank = ranksNew[l]; 6527 } 6528 ierr = PetscFree(ranks);CHKERRQ(ierr); 6529 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6530 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 6531 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6532 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6533 PetscFunctionReturn(0); 6534 } 6535 6536 #undef __FUNCT__ 6537 #define __FUNCT__ "CellRefinerCreateSF" 6538 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6539 { 6540 PetscSF sf, sfNew, sfProcess; 6541 IS processRanks; 6542 MPI_Datatype depthType; 6543 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6544 const PetscInt *localPoints, *neighbors; 6545 const PetscSFNode *remotePoints; 6546 PetscInt *localPointsNew; 6547 PetscSFNode *remotePointsNew; 6548 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6549 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6550 PetscErrorCode ierr; 6551 6552 PetscFunctionBegin; 6553 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6554 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6555 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6556 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6557 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6558 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6559 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6560 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6561 switch (refiner) { 6562 case 3: 6563 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6564 cMax = PetscMin(cEnd, cMax); 6565 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6566 fMax = PetscMin(fEnd, fMax); 6567 } 6568 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6569 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6570 /* Caculate size of new SF */ 6571 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6572 if (numRoots < 0) PetscFunctionReturn(0); 6573 for (l = 0; l < numLeaves; ++l) { 6574 const PetscInt p = localPoints[l]; 6575 6576 switch (refiner) { 6577 case 1: 6578 /* Simplicial 2D */ 6579 if ((p >= vStart) && (p < vEnd)) { 6580 /* Old vertices stay the same */ 6581 ++numLeavesNew; 6582 } else if ((p >= fStart) && (p < fEnd)) { 6583 /* Old faces add new faces and vertex */ 6584 numLeavesNew += 1 + 2; 6585 } else if ((p >= cStart) && (p < cEnd)) { 6586 /* Old cells add new cells and interior faces */ 6587 numLeavesNew += 4 + 3; 6588 } 6589 break; 6590 case 2: 6591 /* Hex 2D */ 6592 if ((p >= vStart) && (p < vEnd)) { 6593 /* Old vertices stay the same */ 6594 ++numLeavesNew; 6595 } else if ((p >= fStart) && (p < fEnd)) { 6596 /* Old faces add new faces and vertex */ 6597 numLeavesNew += 1 + 2; 6598 } else if ((p >= cStart) && (p < cEnd)) { 6599 /* Old cells add new cells and interior faces */ 6600 numLeavesNew += 4 + 4; 6601 } 6602 break; 6603 default: 6604 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6605 } 6606 } 6607 /* Communicate depthSizes for each remote rank */ 6608 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6609 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6610 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6611 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); 6612 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6613 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6614 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6615 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6616 for (n = 0; n < numNeighbors; ++n) { 6617 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6618 } 6619 depthSizeOld[depth] = cMax; 6620 depthSizeOld[0] = vMax; 6621 depthSizeOld[depth-1] = fMax; 6622 depthSizeOld[1] = eMax; 6623 6624 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6625 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6626 6627 depthSizeOld[depth] = cEnd - cStart; 6628 depthSizeOld[0] = vEnd - vStart; 6629 depthSizeOld[depth-1] = fEnd - fStart; 6630 depthSizeOld[1] = eEnd - eStart; 6631 6632 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6633 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6634 for (n = 0; n < numNeighbors; ++n) { 6635 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6636 } 6637 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6638 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6639 /* Calculate new point SF */ 6640 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6641 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6642 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6643 for (l = 0, m = 0; l < numLeaves; ++l) { 6644 PetscInt p = localPoints[l]; 6645 PetscInt rp = remotePoints[l].index, n; 6646 PetscMPIInt rrank = remotePoints[l].rank; 6647 6648 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6649 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6650 switch (refiner) { 6651 case 1: 6652 /* Simplicial 2D */ 6653 if ((p >= vStart) && (p < vEnd)) { 6654 /* Old vertices stay the same */ 6655 localPointsNew[m] = vStartNew + (p - vStart); 6656 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6657 remotePointsNew[m].rank = rrank; 6658 ++m; 6659 } else if ((p >= fStart) && (p < fEnd)) { 6660 /* Old faces add new faces and vertex */ 6661 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6662 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6663 remotePointsNew[m].rank = rrank; 6664 ++m; 6665 for (r = 0; r < 2; ++r, ++m) { 6666 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6667 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6668 remotePointsNew[m].rank = rrank; 6669 } 6670 } else if ((p >= cStart) && (p < cEnd)) { 6671 /* Old cells add new cells and interior faces */ 6672 for (r = 0; r < 4; ++r, ++m) { 6673 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6674 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6675 remotePointsNew[m].rank = rrank; 6676 } 6677 for (r = 0; r < 3; ++r, ++m) { 6678 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6679 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6680 remotePointsNew[m].rank = rrank; 6681 } 6682 } 6683 break; 6684 case 2: 6685 /* Hex 2D */ 6686 if ((p >= vStart) && (p < vEnd)) { 6687 /* Old vertices stay the same */ 6688 localPointsNew[m] = vStartNew + (p - vStart); 6689 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6690 remotePointsNew[m].rank = rrank; 6691 ++m; 6692 } else if ((p >= fStart) && (p < fEnd)) { 6693 /* Old faces add new faces and vertex */ 6694 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6695 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6696 remotePointsNew[m].rank = rrank; 6697 ++m; 6698 for (r = 0; r < 2; ++r, ++m) { 6699 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6700 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6701 remotePointsNew[m].rank = rrank; 6702 } 6703 } else if ((p >= cStart) && (p < cEnd)) { 6704 /* Old cells add new cells and interior faces */ 6705 for (r = 0; r < 4; ++r, ++m) { 6706 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6707 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6708 remotePointsNew[m].rank = rrank; 6709 } 6710 for (r = 0; r < 4; ++r, ++m) { 6711 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6712 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6713 remotePointsNew[m].rank = rrank; 6714 } 6715 } 6716 break; 6717 case 3: 6718 /* Hybrid simplicial 2D */ 6719 if ((p >= vStart) && (p < vEnd)) { 6720 /* Old vertices stay the same */ 6721 localPointsNew[m] = vStartNew + (p - vStart); 6722 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6723 remotePointsNew[m].rank = rrank; 6724 ++m; 6725 } else if ((p >= fStart) && (p < fMax)) { 6726 /* Old interior faces add new faces and vertex */ 6727 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6728 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6729 remotePointsNew[m].rank = rrank; 6730 ++m; 6731 for (r = 0; r < 2; ++r, ++m) { 6732 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6733 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6734 remotePointsNew[m].rank = rrank; 6735 } 6736 } else if ((p >= fMax) && (p < fEnd)) { 6737 /* Old hybrid faces stay the same */ 6738 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6739 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6740 remotePointsNew[m].rank = rrank; 6741 ++m; 6742 } else if ((p >= cStart) && (p < cMax)) { 6743 /* Old interior cells add new cells and interior faces */ 6744 for (r = 0; r < 4; ++r, ++m) { 6745 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6746 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6747 remotePointsNew[m].rank = rrank; 6748 } 6749 for (r = 0; r < 3; ++r, ++m) { 6750 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6751 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6752 remotePointsNew[m].rank = rrank; 6753 } 6754 } else if ((p >= cStart) && (p < cMax)) { 6755 /* Old hybrid cells add new cells and hybrid face */ 6756 for (r = 0; r < 2; ++r, ++m) { 6757 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6758 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6759 remotePointsNew[m].rank = rrank; 6760 } 6761 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6762 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]); 6763 remotePointsNew[m].rank = rrank; 6764 ++m; 6765 } 6766 break; 6767 default: 6768 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6769 } 6770 } 6771 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6772 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6773 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6774 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6775 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6776 PetscFunctionReturn(0); 6777 } 6778 6779 #undef __FUNCT__ 6780 #define __FUNCT__ "CellRefinerCreateLabels" 6781 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6782 { 6783 PetscInt numLabels, l; 6784 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6785 PetscErrorCode ierr; 6786 6787 PetscFunctionBegin; 6788 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6789 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6790 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6791 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6792 6793 cStartNew = 0; 6794 vStartNew = depthSize[2]; 6795 fStartNew = depthSize[2] + depthSize[0]; 6796 6797 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6798 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6799 switch (refiner) { 6800 case 3: 6801 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6802 cMax = PetscMin(cEnd, cMax); 6803 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6804 fMax = PetscMin(fEnd, fMax); 6805 } 6806 for (l = 0; l < numLabels; ++l) { 6807 DMLabel label, labelNew; 6808 const char *lname; 6809 PetscBool isDepth; 6810 IS valueIS; 6811 const PetscInt *values; 6812 PetscInt numValues, val; 6813 6814 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6815 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6816 if (isDepth) continue; 6817 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6818 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6819 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6820 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6821 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6822 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6823 for (val = 0; val < numValues; ++val) { 6824 IS pointIS; 6825 const PetscInt *points; 6826 PetscInt numPoints, n; 6827 6828 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6829 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6830 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6831 for (n = 0; n < numPoints; ++n) { 6832 const PetscInt p = points[n]; 6833 switch (refiner) { 6834 case 1: 6835 /* Simplicial 2D */ 6836 if ((p >= vStart) && (p < vEnd)) { 6837 /* Old vertices stay the same */ 6838 newp = vStartNew + (p - vStart); 6839 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6840 } else if ((p >= fStart) && (p < fEnd)) { 6841 /* Old faces add new faces and vertex */ 6842 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6843 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6844 for (r = 0; r < 2; ++r) { 6845 newp = fStartNew + (p - fStart)*2 + r; 6846 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6847 } 6848 } else if ((p >= cStart) && (p < cEnd)) { 6849 /* Old cells add new cells and interior faces */ 6850 for (r = 0; r < 4; ++r) { 6851 newp = cStartNew + (p - cStart)*4 + r; 6852 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6853 } 6854 for (r = 0; r < 3; ++r) { 6855 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6856 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6857 } 6858 } 6859 break; 6860 case 2: 6861 /* Hex 2D */ 6862 if ((p >= vStart) && (p < vEnd)) { 6863 /* Old vertices stay the same */ 6864 newp = vStartNew + (p - vStart); 6865 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6866 } else if ((p >= fStart) && (p < fEnd)) { 6867 /* Old faces add new faces and vertex */ 6868 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6869 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6870 for (r = 0; r < 2; ++r) { 6871 newp = fStartNew + (p - fStart)*2 + r; 6872 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6873 } 6874 } else if ((p >= cStart) && (p < cEnd)) { 6875 /* Old cells add new cells and interior faces and vertex */ 6876 for (r = 0; r < 4; ++r) { 6877 newp = cStartNew + (p - cStart)*4 + r; 6878 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6879 } 6880 for (r = 0; r < 4; ++r) { 6881 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6882 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6883 } 6884 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6885 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6886 } 6887 break; 6888 case 3: 6889 /* Hybrid simplicial 2D */ 6890 if ((p >= vStart) && (p < vEnd)) { 6891 /* Old vertices stay the same */ 6892 newp = vStartNew + (p - vStart); 6893 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6894 } else if ((p >= fStart) && (p < fMax)) { 6895 /* Old interior faces add new faces and vertex */ 6896 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6897 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6898 for (r = 0; r < 2; ++r) { 6899 newp = fStartNew + (p - fStart)*2 + r; 6900 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6901 } 6902 } else if ((p >= fMax) && (p < fEnd)) { 6903 /* Old hybrid faces stay the same */ 6904 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 6905 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6906 } else if ((p >= cStart) && (p < cMax)) { 6907 /* Old interior cells add new cells and interior faces */ 6908 for (r = 0; r < 4; ++r) { 6909 newp = cStartNew + (p - cStart)*4 + r; 6910 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6911 } 6912 for (r = 0; r < 3; ++r) { 6913 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6914 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6915 } 6916 } else if ((p >= cMax) && (p < cEnd)) { 6917 /* Old hybrid cells add new cells and hybrid face */ 6918 for (r = 0; r < 2; ++r) { 6919 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 6920 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6921 } 6922 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6923 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6924 } 6925 break; 6926 default: 6927 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6928 } 6929 } 6930 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6931 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6932 } 6933 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6934 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6935 if (0) { 6936 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6937 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6938 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6939 } 6940 } 6941 PetscFunctionReturn(0); 6942 } 6943 6944 #undef __FUNCT__ 6945 #define __FUNCT__ "DMPlexRefine_Uniform" 6946 /* This will only work for interpolated meshes */ 6947 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6948 { 6949 DM rdm; 6950 PetscInt *depthSize; 6951 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6952 PetscErrorCode ierr; 6953 6954 PetscFunctionBegin; 6955 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 6956 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6957 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6958 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6959 /* Calculate number of new points of each depth */ 6960 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6961 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6962 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6963 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6964 /* Step 1: Set chart */ 6965 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 6966 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6967 /* Step 2: Set cone/support sizes */ 6968 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6969 /* Step 3: Setup refined DM */ 6970 ierr = DMSetUp(rdm);CHKERRQ(ierr); 6971 /* Step 4: Set cones and supports */ 6972 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6973 /* Step 5: Stratify */ 6974 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6975 /* Step 6: Set coordinates for vertices */ 6976 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6977 /* Step 7: Create pointSF */ 6978 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6979 /* Step 8: Create labels */ 6980 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6981 ierr = PetscFree(depthSize);CHKERRQ(ierr); 6982 6983 *dmRefined = rdm; 6984 PetscFunctionReturn(0); 6985 } 6986 6987 #undef __FUNCT__ 6988 #define __FUNCT__ "DMPlexSetRefinementUniform" 6989 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 6990 { 6991 DM_Plex *mesh = (DM_Plex*) dm->data; 6992 6993 PetscFunctionBegin; 6994 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6995 mesh->refinementUniform = refinementUniform; 6996 PetscFunctionReturn(0); 6997 } 6998 6999 #undef __FUNCT__ 7000 #define __FUNCT__ "DMPlexGetRefinementUniform" 7001 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7002 { 7003 DM_Plex *mesh = (DM_Plex*) dm->data; 7004 7005 PetscFunctionBegin; 7006 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7007 PetscValidPointer(refinementUniform, 2); 7008 *refinementUniform = mesh->refinementUniform; 7009 PetscFunctionReturn(0); 7010 } 7011 7012 #undef __FUNCT__ 7013 #define __FUNCT__ "DMPlexSetRefinementLimit" 7014 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7015 { 7016 DM_Plex *mesh = (DM_Plex*) dm->data; 7017 7018 PetscFunctionBegin; 7019 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7020 mesh->refinementLimit = refinementLimit; 7021 PetscFunctionReturn(0); 7022 } 7023 7024 #undef __FUNCT__ 7025 #define __FUNCT__ "DMPlexGetRefinementLimit" 7026 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7027 { 7028 DM_Plex *mesh = (DM_Plex*) dm->data; 7029 7030 PetscFunctionBegin; 7031 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7032 PetscValidPointer(refinementLimit, 2); 7033 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7034 *refinementLimit = mesh->refinementLimit; 7035 PetscFunctionReturn(0); 7036 } 7037 7038 #undef __FUNCT__ 7039 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7040 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7041 { 7042 PetscInt dim, cStart, coneSize, cMax; 7043 PetscErrorCode ierr; 7044 7045 PetscFunctionBegin; 7046 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7047 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7048 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7049 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7050 switch (dim) { 7051 case 2: 7052 switch (coneSize) { 7053 case 3: 7054 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7055 else *cellRefiner = 1; /* Triangular */ 7056 break; 7057 case 4: 7058 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7059 else *cellRefiner = 2; /* Quadrilateral */ 7060 break; 7061 default: 7062 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7063 } 7064 break; 7065 default: 7066 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7067 } 7068 PetscFunctionReturn(0); 7069 } 7070 7071 #undef __FUNCT__ 7072 #define __FUNCT__ "DMRefine_Plex" 7073 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7074 { 7075 PetscReal refinementLimit; 7076 PetscInt dim, cStart, cEnd; 7077 char genname[1024], *name = NULL; 7078 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7079 PetscErrorCode ierr; 7080 7081 PetscFunctionBegin; 7082 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7083 if (isUniform) { 7084 CellRefiner cellRefiner; 7085 7086 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7087 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7088 PetscFunctionReturn(0); 7089 } 7090 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7091 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7092 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7093 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7094 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7095 if (flg) name = genname; 7096 if (name) { 7097 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7098 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7099 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7100 } 7101 switch (dim) { 7102 case 2: 7103 if (!name || isTriangle) { 7104 #if defined(PETSC_HAVE_TRIANGLE) 7105 double *maxVolumes; 7106 PetscInt c; 7107 7108 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7109 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7110 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7111 #else 7112 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7113 #endif 7114 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7115 break; 7116 case 3: 7117 if (!name || isCTetgen) { 7118 #if defined(PETSC_HAVE_CTETGEN) 7119 PetscReal *maxVolumes; 7120 PetscInt c; 7121 7122 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7123 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7124 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7125 #else 7126 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7127 #endif 7128 } else if (isTetgen) { 7129 #if defined(PETSC_HAVE_TETGEN) 7130 double *maxVolumes; 7131 PetscInt c; 7132 7133 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7134 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7135 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7136 #else 7137 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7138 #endif 7139 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7140 break; 7141 default: 7142 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7143 } 7144 PetscFunctionReturn(0); 7145 } 7146 7147 #undef __FUNCT__ 7148 #define __FUNCT__ "DMPlexGetDepth" 7149 /*@ 7150 DMPlexGetDepth - get the number of strata 7151 7152 Not Collective 7153 7154 Input Parameters: 7155 . dm - The DMPlex object 7156 7157 Output Parameters: 7158 . depth - number of strata 7159 7160 Level: developer 7161 7162 Notes: 7163 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7164 7165 .keywords: mesh, points 7166 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7167 @*/ 7168 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7169 { 7170 PetscInt d; 7171 PetscErrorCode ierr; 7172 7173 PetscFunctionBegin; 7174 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7175 PetscValidPointer(depth, 2); 7176 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7177 *depth = d-1; 7178 PetscFunctionReturn(0); 7179 } 7180 7181 #undef __FUNCT__ 7182 #define __FUNCT__ "DMPlexGetDepthStratum" 7183 /*@ 7184 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7185 7186 Not Collective 7187 7188 Input Parameters: 7189 + dm - The DMPlex object 7190 - stratumValue - The requested depth 7191 7192 Output Parameters: 7193 + start - The first point at this depth 7194 - end - One beyond the last point at this depth 7195 7196 Level: developer 7197 7198 .keywords: mesh, points 7199 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7200 @*/ 7201 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7202 { 7203 DM_Plex *mesh = (DM_Plex*) dm->data; 7204 DMLabel next = mesh->labels; 7205 PetscBool flg = PETSC_FALSE; 7206 PetscInt depth; 7207 PetscErrorCode ierr; 7208 7209 PetscFunctionBegin; 7210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7211 if (stratumValue < 0) { 7212 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7213 PetscFunctionReturn(0); 7214 } else { 7215 PetscInt pStart, pEnd; 7216 7217 if (start) *start = 0; 7218 if (end) *end = 0; 7219 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7220 if (pStart == pEnd) PetscFunctionReturn(0); 7221 } 7222 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7223 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7224 /* We should have a generic GetLabel() and a Label class */ 7225 while (next) { 7226 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7227 if (flg) break; 7228 next = next->next; 7229 } 7230 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7231 depth = stratumValue; 7232 if ((depth < 0) || (depth >= next->numStrata)) { 7233 if (start) *start = 0; 7234 if (end) *end = 0; 7235 } else { 7236 if (start) *start = next->points[next->stratumOffsets[depth]]; 7237 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7238 } 7239 PetscFunctionReturn(0); 7240 } 7241 7242 #undef __FUNCT__ 7243 #define __FUNCT__ "DMPlexGetHeightStratum" 7244 /*@ 7245 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7246 7247 Not Collective 7248 7249 Input Parameters: 7250 + dm - The DMPlex object 7251 - stratumValue - The requested height 7252 7253 Output Parameters: 7254 + start - The first point at this height 7255 - end - One beyond the last point at this height 7256 7257 Level: developer 7258 7259 .keywords: mesh, points 7260 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7261 @*/ 7262 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7263 { 7264 DM_Plex *mesh = (DM_Plex*) dm->data; 7265 DMLabel next = mesh->labels; 7266 PetscBool flg = PETSC_FALSE; 7267 PetscInt depth; 7268 PetscErrorCode ierr; 7269 7270 PetscFunctionBegin; 7271 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7272 if (stratumValue < 0) { 7273 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7274 } else { 7275 PetscInt pStart, pEnd; 7276 7277 if (start) *start = 0; 7278 if (end) *end = 0; 7279 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7280 if (pStart == pEnd) PetscFunctionReturn(0); 7281 } 7282 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7283 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7284 /* We should have a generic GetLabel() and a Label class */ 7285 while (next) { 7286 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7287 if (flg) break; 7288 next = next->next; 7289 } 7290 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7291 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7292 if ((depth < 0) || (depth >= next->numStrata)) { 7293 if (start) *start = 0; 7294 if (end) *end = 0; 7295 } else { 7296 if (start) *start = next->points[next->stratumOffsets[depth]]; 7297 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7298 } 7299 PetscFunctionReturn(0); 7300 } 7301 7302 #undef __FUNCT__ 7303 #define __FUNCT__ "DMPlexCreateSectionInitial" 7304 /* Set the number of dof on each point and separate by fields */ 7305 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7306 { 7307 PetscInt *numDofTot; 7308 PetscInt pStart = 0, pEnd = 0; 7309 PetscInt p, d, f; 7310 PetscErrorCode ierr; 7311 7312 PetscFunctionBegin; 7313 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7314 for (d = 0; d <= dim; ++d) { 7315 numDofTot[d] = 0; 7316 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7317 } 7318 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7319 if (numFields > 0) { 7320 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7321 if (numComp) { 7322 for (f = 0; f < numFields; ++f) { 7323 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7324 } 7325 } 7326 } 7327 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7328 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7329 for (d = 0; d <= dim; ++d) { 7330 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7331 for (p = pStart; p < pEnd; ++p) { 7332 for (f = 0; f < numFields; ++f) { 7333 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7334 } 7335 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7336 } 7337 } 7338 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7339 PetscFunctionReturn(0); 7340 } 7341 7342 #undef __FUNCT__ 7343 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7344 /* Set the number of dof on each point and separate by fields 7345 If constDof is PETSC_DETERMINE, constrain every dof on the point 7346 */ 7347 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7348 { 7349 PetscInt numFields; 7350 PetscInt bc; 7351 PetscErrorCode ierr; 7352 7353 PetscFunctionBegin; 7354 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7355 for (bc = 0; bc < numBC; ++bc) { 7356 PetscInt field = 0; 7357 const PetscInt *idx; 7358 PetscInt n, i; 7359 7360 if (numFields) field = bcField[bc]; 7361 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7362 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7363 for (i = 0; i < n; ++i) { 7364 const PetscInt p = idx[i]; 7365 PetscInt numConst = constDof; 7366 7367 /* Constrain every dof on the point */ 7368 if (numConst < 0) { 7369 if (numFields) { 7370 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7371 } else { 7372 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7373 } 7374 } 7375 if (numFields) { 7376 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7377 } 7378 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7379 } 7380 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7381 } 7382 PetscFunctionReturn(0); 7383 } 7384 7385 #undef __FUNCT__ 7386 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7387 /* Set the constrained indices on each point and separate by fields */ 7388 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7389 { 7390 PetscInt *maxConstraints; 7391 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7392 PetscErrorCode ierr; 7393 7394 PetscFunctionBegin; 7395 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7396 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7397 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7398 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7399 for (p = pStart; p < pEnd; ++p) { 7400 PetscInt cdof; 7401 7402 if (numFields) { 7403 for (f = 0; f < numFields; ++f) { 7404 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7405 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7406 } 7407 } else { 7408 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7409 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7410 } 7411 } 7412 for (f = 0; f < numFields; ++f) { 7413 maxConstraints[numFields] += maxConstraints[f]; 7414 } 7415 if (maxConstraints[numFields]) { 7416 PetscInt *indices; 7417 7418 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7419 for (p = pStart; p < pEnd; ++p) { 7420 PetscInt cdof, d; 7421 7422 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7423 if (cdof) { 7424 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7425 if (numFields) { 7426 PetscInt numConst = 0, foff = 0; 7427 7428 for (f = 0; f < numFields; ++f) { 7429 PetscInt cfdof, fdof; 7430 7431 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7432 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7433 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7434 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7435 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7436 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7437 numConst += cfdof; 7438 foff += fdof; 7439 } 7440 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7441 } else { 7442 for (d = 0; d < cdof; ++d) indices[d] = d; 7443 } 7444 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7445 } 7446 } 7447 ierr = PetscFree(indices);CHKERRQ(ierr); 7448 } 7449 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7450 PetscFunctionReturn(0); 7451 } 7452 7453 #undef __FUNCT__ 7454 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7455 /* Set the constrained field indices on each point */ 7456 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7457 { 7458 const PetscInt *points, *indices; 7459 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7460 PetscErrorCode ierr; 7461 7462 PetscFunctionBegin; 7463 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7464 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7465 7466 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7467 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7468 if (!constraintIndices) { 7469 PetscInt *idx, i; 7470 7471 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7472 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7473 for (i = 0; i < maxDof; ++i) idx[i] = i; 7474 for (p = 0; p < numPoints; ++p) { 7475 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7476 } 7477 ierr = PetscFree(idx);CHKERRQ(ierr); 7478 } else { 7479 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7480 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7481 for (p = 0; p < numPoints; ++p) { 7482 PetscInt fcdof; 7483 7484 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7485 if (fcdof != numConstraints) SETERRQ4(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 7486 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7487 } 7488 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7489 } 7490 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7491 PetscFunctionReturn(0); 7492 } 7493 7494 #undef __FUNCT__ 7495 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7496 /* Set the constrained indices on each point and separate by fields */ 7497 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7498 { 7499 PetscInt *indices; 7500 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7501 PetscErrorCode ierr; 7502 7503 PetscFunctionBegin; 7504 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7505 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7506 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7507 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7508 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7509 for (p = pStart; p < pEnd; ++p) { 7510 PetscInt cdof, d; 7511 7512 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7513 if (cdof) { 7514 PetscInt numConst = 0, foff = 0; 7515 7516 for (f = 0; f < numFields; ++f) { 7517 const PetscInt *fcind; 7518 PetscInt fdof, fcdof; 7519 7520 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7521 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7522 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7523 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7524 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7525 foff += fdof; 7526 numConst += fcdof; 7527 } 7528 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7529 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7530 } 7531 } 7532 ierr = PetscFree(indices);CHKERRQ(ierr); 7533 PetscFunctionReturn(0); 7534 } 7535 7536 #undef __FUNCT__ 7537 #define __FUNCT__ "DMPlexCreateSection" 7538 /*@C 7539 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7540 7541 Not Collective 7542 7543 Input Parameters: 7544 + dm - The DMPlex object 7545 . dim - The spatial dimension of the problem 7546 . numFields - The number of fields in the problem 7547 . numComp - An array of size numFields that holds the number of components for each field 7548 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7549 . numBC - The number of boundary conditions 7550 . bcField - An array of size numBC giving the field number for each boundry condition 7551 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7552 7553 Output Parameter: 7554 . section - The PetscSection object 7555 7556 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 7557 nubmer of dof for field 0 on each edge. 7558 7559 Level: developer 7560 7561 .keywords: mesh, elements 7562 .seealso: DMPlexCreate(), PetscSectionCreate() 7563 @*/ 7564 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 7565 { 7566 PetscErrorCode ierr; 7567 7568 PetscFunctionBegin; 7569 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7570 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7571 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7572 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7573 { 7574 PetscBool view = PETSC_FALSE; 7575 7576 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7577 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7578 } 7579 PetscFunctionReturn(0); 7580 } 7581 7582 #undef __FUNCT__ 7583 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7584 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7585 { 7586 PetscSection section; 7587 PetscErrorCode ierr; 7588 7589 PetscFunctionBegin; 7590 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7591 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7592 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7593 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7594 PetscFunctionReturn(0); 7595 } 7596 7597 #undef __FUNCT__ 7598 #define __FUNCT__ "DMPlexGetCoordinateSection" 7599 /*@ 7600 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7601 7602 Not Collective 7603 7604 Input Parameter: 7605 . dm - The DMPlex object 7606 7607 Output Parameter: 7608 . section - The PetscSection object 7609 7610 Level: intermediate 7611 7612 .keywords: mesh, coordinates 7613 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7614 @*/ 7615 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7616 { 7617 DM cdm; 7618 PetscErrorCode ierr; 7619 7620 PetscFunctionBegin; 7621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7622 PetscValidPointer(section, 2); 7623 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7624 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7625 PetscFunctionReturn(0); 7626 } 7627 7628 #undef __FUNCT__ 7629 #define __FUNCT__ "DMPlexSetCoordinateSection" 7630 /*@ 7631 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7632 7633 Not Collective 7634 7635 Input Parameters: 7636 + dm - The DMPlex object 7637 - section - The PetscSection object 7638 7639 Level: intermediate 7640 7641 .keywords: mesh, coordinates 7642 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7643 @*/ 7644 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7645 { 7646 DM cdm; 7647 PetscErrorCode ierr; 7648 7649 PetscFunctionBegin; 7650 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7651 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 7652 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7653 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7654 PetscFunctionReturn(0); 7655 } 7656 7657 #undef __FUNCT__ 7658 #define __FUNCT__ "DMPlexGetConeSection" 7659 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7660 { 7661 DM_Plex *mesh = (DM_Plex*) dm->data; 7662 7663 PetscFunctionBegin; 7664 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7665 if (section) *section = mesh->coneSection; 7666 PetscFunctionReturn(0); 7667 } 7668 7669 #undef __FUNCT__ 7670 #define __FUNCT__ "DMPlexGetCones" 7671 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 7672 { 7673 DM_Plex *mesh = (DM_Plex*) dm->data; 7674 7675 PetscFunctionBegin; 7676 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7677 if (cones) *cones = mesh->cones; 7678 PetscFunctionReturn(0); 7679 } 7680 7681 #undef __FUNCT__ 7682 #define __FUNCT__ "DMPlexGetConeOrientations" 7683 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 7684 { 7685 DM_Plex *mesh = (DM_Plex*) dm->data; 7686 7687 PetscFunctionBegin; 7688 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7689 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7690 PetscFunctionReturn(0); 7691 } 7692 7693 #undef __FUNCT__ 7694 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7695 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7696 { 7697 const PetscInt embedDim = 2; 7698 PetscReal x = PetscRealPart(point[0]); 7699 PetscReal y = PetscRealPart(point[1]); 7700 PetscReal v0[2], J[4], invJ[4], detJ; 7701 PetscReal xi, eta; 7702 PetscErrorCode ierr; 7703 7704 PetscFunctionBegin; 7705 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7706 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7707 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7708 7709 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 7710 else *cell = -1; 7711 PetscFunctionReturn(0); 7712 } 7713 7714 #undef __FUNCT__ 7715 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7716 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7717 { 7718 PetscSection coordSection; 7719 Vec coordsLocal; 7720 const PetscScalar *coords; 7721 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7722 PetscReal x = PetscRealPart(point[0]); 7723 PetscReal y = PetscRealPart(point[1]); 7724 PetscInt crossings = 0, f; 7725 PetscErrorCode ierr; 7726 7727 PetscFunctionBegin; 7728 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7729 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7730 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7731 for (f = 0; f < 4; ++f) { 7732 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7733 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7734 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7735 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7736 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7737 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7738 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7739 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7740 if ((cond1 || cond2) && above) ++crossings; 7741 } 7742 if (crossings % 2) *cell = c; 7743 else *cell = -1; 7744 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7745 PetscFunctionReturn(0); 7746 } 7747 7748 #undef __FUNCT__ 7749 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7750 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7751 { 7752 const PetscInt embedDim = 3; 7753 PetscReal v0[3], J[9], invJ[9], detJ; 7754 PetscReal x = PetscRealPart(point[0]); 7755 PetscReal y = PetscRealPart(point[1]); 7756 PetscReal z = PetscRealPart(point[2]); 7757 PetscReal xi, eta, zeta; 7758 PetscErrorCode ierr; 7759 7760 PetscFunctionBegin; 7761 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7762 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7763 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7764 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7765 7766 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 7767 else *cell = -1; 7768 PetscFunctionReturn(0); 7769 } 7770 7771 #undef __FUNCT__ 7772 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7773 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7774 { 7775 PetscSection coordSection; 7776 Vec coordsLocal; 7777 const PetscScalar *coords; 7778 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7779 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7780 PetscBool found = PETSC_TRUE; 7781 PetscInt f; 7782 PetscErrorCode ierr; 7783 7784 PetscFunctionBegin; 7785 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7786 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7787 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7788 for (f = 0; f < 6; ++f) { 7789 /* Check the point is under plane */ 7790 /* Get face normal */ 7791 PetscReal v_i[3]; 7792 PetscReal v_j[3]; 7793 PetscReal normal[3]; 7794 PetscReal pp[3]; 7795 PetscReal dot; 7796 7797 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 7798 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 7799 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 7800 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 7801 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 7802 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 7803 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 7804 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 7805 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 7806 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 7807 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 7808 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 7809 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7810 7811 /* Check that projected point is in face (2D location problem) */ 7812 if (dot < 0.0) { 7813 found = PETSC_FALSE; 7814 break; 7815 } 7816 } 7817 if (found) *cell = c; 7818 else *cell = -1; 7819 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7820 PetscFunctionReturn(0); 7821 } 7822 7823 #undef __FUNCT__ 7824 #define __FUNCT__ "DMLocatePoints_Plex" 7825 /* 7826 Need to implement using the guess 7827 */ 7828 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7829 { 7830 PetscInt cell = -1 /*, guess = -1*/; 7831 PetscInt bs, numPoints, p; 7832 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7833 PetscInt *cells; 7834 PetscScalar *a; 7835 PetscErrorCode ierr; 7836 7837 PetscFunctionBegin; 7838 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7839 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7840 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7841 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7842 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7843 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7844 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7845 if (bs != dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 7846 numPoints /= bs; 7847 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7848 for (p = 0; p < numPoints; ++p) { 7849 const PetscScalar *point = &a[p*bs]; 7850 7851 switch (dim) { 7852 case 2: 7853 for (c = cStart; c < cEnd; ++c) { 7854 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7855 switch (coneSize) { 7856 case 3: 7857 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7858 break; 7859 case 4: 7860 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7861 break; 7862 default: 7863 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7864 } 7865 if (cell >= 0) break; 7866 } 7867 break; 7868 case 3: 7869 for (c = cStart; c < cEnd; ++c) { 7870 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7871 switch (coneSize) { 7872 case 4: 7873 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7874 break; 7875 case 8: 7876 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7877 break; 7878 default: 7879 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7880 } 7881 if (cell >= 0) break; 7882 } 7883 break; 7884 default: 7885 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 7886 } 7887 cells[p] = cell; 7888 } 7889 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 7890 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 7891 PetscFunctionReturn(0); 7892 } 7893 7894 /******************************** FEM Support **********************************/ 7895 7896 #undef __FUNCT__ 7897 #define __FUNCT__ "DMPlexVecGetClosure" 7898 /*@C 7899 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 7900 7901 Not collective 7902 7903 Input Parameters: 7904 + dm - The DM 7905 . section - The section describing the layout in v, or NULL to use the default section 7906 . v - The local vector 7907 - point - The sieve point in the DM 7908 7909 Output Parameters: 7910 + csize - The number of values in the closure, or NULL 7911 - values - The array of values, which is a borrowed array and should not be freed 7912 7913 Level: intermediate 7914 7915 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7916 @*/ 7917 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 7918 { 7919 PetscScalar *array, *vArray; 7920 PetscInt *points = NULL; 7921 PetscInt offsets[32]; 7922 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 7923 PetscErrorCode ierr; 7924 7925 PetscFunctionBegin; 7926 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7927 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7928 if (!section) { 7929 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7930 } 7931 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7932 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7933 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7934 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7935 /* Compress out points not in the section */ 7936 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7937 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7938 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7939 points[q*2] = points[p]; 7940 points[q*2+1] = points[p+1]; 7941 ++q; 7942 } 7943 } 7944 numPoints = q; 7945 for (p = 0, size = 0; p < numPoints*2; p += 2) { 7946 PetscInt dof, fdof; 7947 7948 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7949 for (f = 0; f < numFields; ++f) { 7950 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7951 offsets[f+1] += fdof; 7952 } 7953 size += dof; 7954 } 7955 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7956 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 7957 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 7958 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 7959 for (p = 0; p < numPoints*2; p += 2) { 7960 PetscInt o = points[p+1]; 7961 PetscInt dof, off, d; 7962 PetscScalar *varr; 7963 7964 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7965 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 7966 varr = &vArray[off]; 7967 if (numFields) { 7968 PetscInt fdof, foff, fcomp, f, c; 7969 7970 for (f = 0, foff = 0; f < numFields; ++f) { 7971 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7972 if (o >= 0) { 7973 for (d = 0; d < fdof; ++d, ++offsets[f]) { 7974 array[offsets[f]] = varr[foff+d]; 7975 } 7976 } else { 7977 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7978 for (d = fdof/fcomp-1; d >= 0; --d) { 7979 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 7980 array[offsets[f]] = varr[foff+d*fcomp+c]; 7981 } 7982 } 7983 } 7984 foff += fdof; 7985 } 7986 } else { 7987 if (o >= 0) { 7988 for (d = 0; d < dof; ++d, ++offsets[0]) { 7989 array[offsets[0]] = varr[d]; 7990 } 7991 } else { 7992 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 7993 array[offsets[0]] = varr[d]; 7994 } 7995 } 7996 } 7997 } 7998 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7999 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8000 if (csize) *csize = size; 8001 *values = array; 8002 PetscFunctionReturn(0); 8003 } 8004 8005 #undef __FUNCT__ 8006 #define __FUNCT__ "DMPlexVecRestoreClosure" 8007 /*@C 8008 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8009 8010 Not collective 8011 8012 Input Parameters: 8013 + dm - The DM 8014 . section - The section describing the layout in v, or NULL to use the default section 8015 . v - The local vector 8016 . point - The sieve point in the DM 8017 . csize - The number of values in the closure, or NULL 8018 - values - The array of values, which is a borrowed array and should not be freed 8019 8020 Level: intermediate 8021 8022 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8023 @*/ 8024 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8025 { 8026 PetscInt size = 0; 8027 PetscErrorCode ierr; 8028 8029 PetscFunctionBegin; 8030 /* Should work without recalculating size */ 8031 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8032 PetscFunctionReturn(0); 8033 } 8034 8035 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8036 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8037 8038 #undef __FUNCT__ 8039 #define __FUNCT__ "updatePoint_private" 8040 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8041 { 8042 PetscInt cdof; /* The number of constraints on this point */ 8043 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8044 PetscScalar *a; 8045 PetscInt off, cind = 0, k; 8046 PetscErrorCode ierr; 8047 8048 PetscFunctionBegin; 8049 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8050 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8051 a = &array[off]; 8052 if (!cdof || setBC) { 8053 if (orientation >= 0) { 8054 for (k = 0; k < dof; ++k) { 8055 fuse(&a[k], values[k]); 8056 } 8057 } else { 8058 for (k = 0; k < dof; ++k) { 8059 fuse(&a[k], values[dof-k-1]); 8060 } 8061 } 8062 } else { 8063 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8064 if (orientation >= 0) { 8065 for (k = 0; k < dof; ++k) { 8066 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8067 fuse(&a[k], values[k]); 8068 } 8069 } else { 8070 for (k = 0; k < dof; ++k) { 8071 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8072 fuse(&a[k], values[dof-k-1]); 8073 } 8074 } 8075 } 8076 PetscFunctionReturn(0); 8077 } 8078 8079 #undef __FUNCT__ 8080 #define __FUNCT__ "updatePointFields_private" 8081 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8082 { 8083 PetscScalar *a; 8084 PetscInt numFields, off, foff, f; 8085 PetscErrorCode ierr; 8086 8087 PetscFunctionBegin; 8088 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8089 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8090 a = &array[off]; 8091 for (f = 0, foff = 0; f < numFields; ++f) { 8092 PetscInt fdof, fcomp, fcdof; 8093 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8094 PetscInt cind = 0, k, c; 8095 8096 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8097 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8098 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8099 if (!fcdof || setBC) { 8100 if (orientation >= 0) { 8101 for (k = 0; k < fdof; ++k) { 8102 fuse(&a[foff+k], values[foffs[f]+k]); 8103 } 8104 } else { 8105 for (k = fdof/fcomp-1; k >= 0; --k) { 8106 for (c = 0; c < fcomp; ++c) { 8107 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8108 } 8109 } 8110 } 8111 } else { 8112 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8113 if (orientation >= 0) { 8114 for (k = 0; k < fdof; ++k) { 8115 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8116 fuse(&a[foff+k], values[foffs[f]+k]); 8117 } 8118 } else { 8119 for (k = fdof/fcomp-1; k >= 0; --k) { 8120 for (c = 0; c < fcomp; ++c) { 8121 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8122 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8123 } 8124 } 8125 } 8126 } 8127 foff += fdof; 8128 foffs[f] += fdof; 8129 } 8130 PetscFunctionReturn(0); 8131 } 8132 8133 #undef __FUNCT__ 8134 #define __FUNCT__ "DMPlexVecSetClosure" 8135 /*@C 8136 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8137 8138 Not collective 8139 8140 Input Parameters: 8141 + dm - The DM 8142 . section - The section describing the layout in v, or NULL to use the default sectionw 8143 . v - The local vector 8144 . point - The sieve point in the DM 8145 . values - The array of values, which is a borrowed array and should not be freed 8146 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8147 8148 Level: intermediate 8149 8150 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8151 @*/ 8152 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8153 { 8154 PetscScalar *array; 8155 PetscInt *points = NULL; 8156 PetscInt offsets[32]; 8157 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8158 PetscErrorCode ierr; 8159 8160 PetscFunctionBegin; 8161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8162 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8163 if (!section) { 8164 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8165 } 8166 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8167 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8168 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8169 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8170 /* Compress out points not in the section */ 8171 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8172 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8173 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8174 points[q*2] = points[p]; 8175 points[q*2+1] = points[p+1]; 8176 ++q; 8177 } 8178 } 8179 numPoints = q; 8180 for (p = 0; p < numPoints*2; p += 2) { 8181 PetscInt fdof; 8182 8183 for (f = 0; f < numFields; ++f) { 8184 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8185 offsets[f+1] += fdof; 8186 } 8187 } 8188 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8189 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8190 if (numFields) { 8191 switch (mode) { 8192 case INSERT_VALUES: 8193 for (p = 0; p < numPoints*2; p += 2) { 8194 PetscInt o = points[p+1]; 8195 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8196 } break; 8197 case INSERT_ALL_VALUES: 8198 for (p = 0; p < numPoints*2; p += 2) { 8199 PetscInt o = points[p+1]; 8200 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8201 } break; 8202 case ADD_VALUES: 8203 for (p = 0; p < numPoints*2; p += 2) { 8204 PetscInt o = points[p+1]; 8205 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8206 } break; 8207 case ADD_ALL_VALUES: 8208 for (p = 0; p < numPoints*2; p += 2) { 8209 PetscInt o = points[p+1]; 8210 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8211 } break; 8212 default: 8213 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8214 } 8215 } else { 8216 switch (mode) { 8217 case INSERT_VALUES: 8218 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8219 PetscInt o = points[p+1]; 8220 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8221 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8222 } break; 8223 case INSERT_ALL_VALUES: 8224 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8225 PetscInt o = points[p+1]; 8226 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8227 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8228 } break; 8229 case ADD_VALUES: 8230 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8231 PetscInt o = points[p+1]; 8232 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8233 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8234 } break; 8235 case ADD_ALL_VALUES: 8236 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8237 PetscInt o = points[p+1]; 8238 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8239 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8240 } break; 8241 default: 8242 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8243 } 8244 } 8245 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8246 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8247 PetscFunctionReturn(0); 8248 } 8249 8250 #undef __FUNCT__ 8251 #define __FUNCT__ "DMPlexPrintMatSetValues" 8252 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8253 { 8254 PetscMPIInt rank; 8255 PetscInt i, j; 8256 PetscErrorCode ierr; 8257 8258 PetscFunctionBegin; 8259 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8260 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8261 for (i = 0; i < numIndices; i++) { 8262 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8263 } 8264 for (i = 0; i < numIndices; i++) { 8265 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8266 for (j = 0; j < numIndices; j++) { 8267 #if defined(PETSC_USE_COMPLEX) 8268 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8269 #else 8270 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8271 #endif 8272 } 8273 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8274 } 8275 PetscFunctionReturn(0); 8276 } 8277 8278 #undef __FUNCT__ 8279 #define __FUNCT__ "indicesPoint_private" 8280 /* . off - The global offset of this point */ 8281 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8282 { 8283 PetscInt dof; /* The number of unknowns on this point */ 8284 PetscInt cdof; /* The number of constraints on this point */ 8285 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8286 PetscInt cind = 0, k; 8287 PetscErrorCode ierr; 8288 8289 PetscFunctionBegin; 8290 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8291 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8292 if (!cdof || setBC) { 8293 if (orientation >= 0) { 8294 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8295 } else { 8296 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8297 } 8298 } else { 8299 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8300 if (orientation >= 0) { 8301 for (k = 0; k < dof; ++k) { 8302 if ((cind < cdof) && (k == cdofs[cind])) { 8303 /* Insert check for returning constrained indices */ 8304 indices[*loff+k] = -(off+k+1); 8305 ++cind; 8306 } else { 8307 indices[*loff+k] = off+k-cind; 8308 } 8309 } 8310 } else { 8311 for (k = 0; k < dof; ++k) { 8312 if ((cind < cdof) && (k == cdofs[cind])) { 8313 /* Insert check for returning constrained indices */ 8314 indices[*loff+dof-k-1] = -(off+k+1); 8315 ++cind; 8316 } else { 8317 indices[*loff+dof-k-1] = off+k-cind; 8318 } 8319 } 8320 } 8321 } 8322 *loff += dof; 8323 PetscFunctionReturn(0); 8324 } 8325 8326 #undef __FUNCT__ 8327 #define __FUNCT__ "indicesPointFields_private" 8328 /* . off - The global offset of this point */ 8329 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8330 { 8331 PetscInt numFields, foff, f; 8332 PetscErrorCode ierr; 8333 8334 PetscFunctionBegin; 8335 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8336 for (f = 0, foff = 0; f < numFields; ++f) { 8337 PetscInt fdof, fcomp, cfdof; 8338 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8339 PetscInt cind = 0, k, c; 8340 8341 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8342 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8343 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8344 if (!cfdof || setBC) { 8345 if (orientation >= 0) { 8346 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8347 } else { 8348 for (k = fdof/fcomp-1; k >= 0; --k) { 8349 for (c = 0; c < fcomp; ++c) { 8350 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8351 } 8352 } 8353 } 8354 } else { 8355 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8356 if (orientation >= 0) { 8357 for (k = 0; k < fdof; ++k) { 8358 if ((cind < cfdof) && (k == fcdofs[cind])) { 8359 indices[foffs[f]+k] = -(off+foff+k+1); 8360 ++cind; 8361 } else { 8362 indices[foffs[f]+k] = off+foff+k-cind; 8363 } 8364 } 8365 } else { 8366 for (k = fdof/fcomp-1; k >= 0; --k) { 8367 for (c = 0; c < fcomp; ++c) { 8368 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8369 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8370 ++cind; 8371 } else { 8372 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8373 } 8374 } 8375 } 8376 } 8377 } 8378 foff += fdof - cfdof; 8379 foffs[f] += fdof; 8380 } 8381 PetscFunctionReturn(0); 8382 } 8383 8384 #undef __FUNCT__ 8385 #define __FUNCT__ "DMPlexMatSetClosure" 8386 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8387 { 8388 DM_Plex *mesh = (DM_Plex*) dm->data; 8389 PetscInt *points = NULL; 8390 PetscInt *indices; 8391 PetscInt offsets[32]; 8392 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8393 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8394 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8395 PetscErrorCode ierr; 8396 8397 PetscFunctionBegin; 8398 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8399 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8400 if (useDefault) { 8401 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8402 } 8403 if (useGlobalDefault) { 8404 if (useDefault) { 8405 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8406 } else { 8407 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8408 } 8409 } 8410 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8411 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8412 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8413 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8414 /* Compress out points not in the section */ 8415 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8416 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8417 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8418 points[q*2] = points[p]; 8419 points[q*2+1] = points[p+1]; 8420 ++q; 8421 } 8422 } 8423 numPoints = q; 8424 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8425 PetscInt fdof; 8426 8427 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8428 for (f = 0; f < numFields; ++f) { 8429 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8430 offsets[f+1] += fdof; 8431 } 8432 numIndices += dof; 8433 } 8434 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8435 8436 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8437 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8438 if (numFields) { 8439 for (p = 0; p < numPoints*2; p += 2) { 8440 PetscInt o = points[p+1]; 8441 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8442 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8443 } 8444 } else { 8445 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8446 PetscInt o = points[p+1]; 8447 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8448 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8449 } 8450 } 8451 if (useGlobalDefault && !useDefault) { 8452 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8453 } 8454 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8455 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8456 if (ierr) { 8457 PetscMPIInt rank; 8458 PetscErrorCode ierr2; 8459 8460 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8461 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8462 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8463 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8464 CHKERRQ(ierr); 8465 } 8466 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8467 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8468 PetscFunctionReturn(0); 8469 } 8470 8471 #undef __FUNCT__ 8472 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8473 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8474 { 8475 PetscSection coordSection; 8476 Vec coordinates; 8477 const PetscScalar *coords; 8478 const PetscInt dim = 2; 8479 PetscInt d, f; 8480 PetscErrorCode ierr; 8481 8482 PetscFunctionBegin; 8483 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8484 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8485 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8486 if (v0) { 8487 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8488 } 8489 if (J) { 8490 for (d = 0; d < dim; d++) { 8491 for (f = 0; f < dim; f++) { 8492 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8493 } 8494 } 8495 *detJ = J[0]*J[3] - J[1]*J[2]; 8496 #if 0 8497 if (detJ < 0.0) { 8498 const PetscReal xLength = mesh->periodicity[0]; 8499 8500 if (xLength != 0.0) { 8501 PetscReal v0x = coords[0*dim+0]; 8502 8503 if (v0x == 0.0) v0x = v0[0] = xLength; 8504 for (f = 0; f < dim; f++) { 8505 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8506 8507 J[0*dim+f] = 0.5*(px - v0x); 8508 } 8509 } 8510 detJ = J[0]*J[3] - J[1]*J[2]; 8511 } 8512 #endif 8513 PetscLogFlops(8.0 + 3.0); 8514 } 8515 if (invJ) { 8516 const PetscReal invDet = 1.0/(*detJ); 8517 8518 invJ[0] = invDet*J[3]; 8519 invJ[1] = -invDet*J[1]; 8520 invJ[2] = -invDet*J[2]; 8521 invJ[3] = invDet*J[0]; 8522 PetscLogFlops(5.0); 8523 } 8524 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8525 PetscFunctionReturn(0); 8526 } 8527 8528 #undef __FUNCT__ 8529 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8530 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8531 { 8532 PetscSection coordSection; 8533 Vec coordinates; 8534 const PetscScalar *coords; 8535 const PetscInt dim = 2; 8536 PetscInt d, f; 8537 PetscErrorCode ierr; 8538 8539 PetscFunctionBegin; 8540 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8541 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8542 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8543 if (v0) { 8544 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8545 } 8546 if (J) { 8547 for (d = 0; d < dim; d++) { 8548 for (f = 0; f < dim; f++) { 8549 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8550 } 8551 } 8552 *detJ = J[0]*J[3] - J[1]*J[2]; 8553 PetscLogFlops(8.0 + 3.0); 8554 } 8555 if (invJ) { 8556 const PetscReal invDet = 1.0/(*detJ); 8557 8558 invJ[0] = invDet*J[3]; 8559 invJ[1] = -invDet*J[1]; 8560 invJ[2] = -invDet*J[2]; 8561 invJ[3] = invDet*J[0]; 8562 PetscLogFlops(5.0); 8563 } 8564 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8565 PetscFunctionReturn(0); 8566 } 8567 8568 #undef __FUNCT__ 8569 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8570 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8571 { 8572 PetscSection coordSection; 8573 Vec coordinates; 8574 const PetscScalar *coords; 8575 const PetscInt dim = 3; 8576 PetscInt d, f; 8577 PetscErrorCode ierr; 8578 8579 PetscFunctionBegin; 8580 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8581 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8582 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8583 if (v0) { 8584 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8585 } 8586 if (J) { 8587 for (d = 0; d < dim; d++) { 8588 for (f = 0; f < dim; f++) { 8589 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8590 } 8591 } 8592 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8593 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8594 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8595 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8596 PetscLogFlops(18.0 + 12.0); 8597 } 8598 if (invJ) { 8599 const PetscReal invDet = 1.0/(*detJ); 8600 8601 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8602 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8603 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8604 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8605 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8606 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8607 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8608 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8609 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8610 PetscLogFlops(37.0); 8611 } 8612 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8613 PetscFunctionReturn(0); 8614 } 8615 8616 #undef __FUNCT__ 8617 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8618 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8619 { 8620 PetscSection coordSection; 8621 Vec coordinates; 8622 const PetscScalar *coords; 8623 const PetscInt dim = 3; 8624 PetscInt d; 8625 PetscErrorCode ierr; 8626 8627 PetscFunctionBegin; 8628 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8629 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8630 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8631 if (v0) { 8632 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8633 } 8634 if (J) { 8635 for (d = 0; d < dim; d++) { 8636 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8637 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8638 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8639 } 8640 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8641 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8642 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8643 PetscLogFlops(18.0 + 12.0); 8644 } 8645 if (invJ) { 8646 const PetscReal invDet = -1.0/(*detJ); 8647 8648 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8649 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8650 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8651 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8652 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8653 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8654 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8655 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8656 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8657 PetscLogFlops(37.0); 8658 } 8659 *detJ *= 8.0; 8660 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8661 PetscFunctionReturn(0); 8662 } 8663 8664 #undef __FUNCT__ 8665 #define __FUNCT__ "DMPlexComputeCellGeometry" 8666 /*@C 8667 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8668 8669 Collective on DM 8670 8671 Input Arguments: 8672 + dm - the DM 8673 - cell - the cell 8674 8675 Output Arguments: 8676 + v0 - the translation part of this affine transform 8677 . J - the Jacobian of the transform to the reference element 8678 . invJ - the inverse of the Jacobian 8679 - detJ - the Jacobian determinant 8680 8681 Level: advanced 8682 8683 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8684 @*/ 8685 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8686 { 8687 PetscInt dim, coneSize; 8688 PetscErrorCode ierr; 8689 8690 PetscFunctionBegin; 8691 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8692 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8693 switch (dim) { 8694 case 2: 8695 switch (coneSize) { 8696 case 3: 8697 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8698 break; 8699 case 4: 8700 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8701 break; 8702 default: 8703 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8704 } 8705 break; 8706 case 3: 8707 switch (coneSize) { 8708 case 4: 8709 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8710 break; 8711 case 8: 8712 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8713 break; 8714 default: 8715 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8716 } 8717 break; 8718 default: 8719 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8720 } 8721 PetscFunctionReturn(0); 8722 } 8723 8724 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8725 { 8726 switch (i) { 8727 case 0: 8728 switch (j) { 8729 case 0: return 0; 8730 case 1: 8731 switch (k) { 8732 case 0: return 0; 8733 case 1: return 0; 8734 case 2: return 1; 8735 } 8736 case 2: 8737 switch (k) { 8738 case 0: return 0; 8739 case 1: return -1; 8740 case 2: return 0; 8741 } 8742 } 8743 case 1: 8744 switch (j) { 8745 case 0: 8746 switch (k) { 8747 case 0: return 0; 8748 case 1: return 0; 8749 case 2: return -1; 8750 } 8751 case 1: return 0; 8752 case 2: 8753 switch (k) { 8754 case 0: return 1; 8755 case 1: return 0; 8756 case 2: return 0; 8757 } 8758 } 8759 case 2: 8760 switch (j) { 8761 case 0: 8762 switch (k) { 8763 case 0: return 0; 8764 case 1: return 1; 8765 case 2: return 0; 8766 } 8767 case 1: 8768 switch (k) { 8769 case 0: return -1; 8770 case 1: return 0; 8771 case 2: return 0; 8772 } 8773 case 2: return 0; 8774 } 8775 } 8776 return 0; 8777 } 8778 8779 #undef __FUNCT__ 8780 #define __FUNCT__ "DMPlexCreateRigidBody" 8781 /*@C 8782 DMPlexCreateRigidBody - create rigid body modes from coordinates 8783 8784 Collective on DM 8785 8786 Input Arguments: 8787 + dm - the DM 8788 . section - the local section associated with the rigid field, or NULL for the default section 8789 - globalSection - the global section associated with the rigid field, or NULL for the default section 8790 8791 Output Argument: 8792 . sp - the null space 8793 8794 Note: This is necessary to take account of Dirichlet conditions on the displacements 8795 8796 Level: advanced 8797 8798 .seealso: MatNullSpaceCreate() 8799 @*/ 8800 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8801 { 8802 MPI_Comm comm; 8803 Vec coordinates, localMode, mode[6]; 8804 PetscSection coordSection; 8805 PetscScalar *coords; 8806 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8807 PetscErrorCode ierr; 8808 8809 PetscFunctionBegin; 8810 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 8811 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8812 if (dim == 1) { 8813 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 8814 PetscFunctionReturn(0); 8815 } 8816 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8817 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8818 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8819 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8820 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8821 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8822 m = (dim*(dim+1))/2; 8823 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8824 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8825 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8826 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8827 /* Assume P1 */ 8828 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8829 for (d = 0; d < dim; ++d) { 8830 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8831 8832 values[d] = 1.0; 8833 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8834 for (v = vStart; v < vEnd; ++v) { 8835 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8836 } 8837 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8838 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8839 } 8840 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8841 for (d = dim; d < dim*(dim+1)/2; ++d) { 8842 PetscInt i, j, k = dim > 2 ? d - dim : d; 8843 8844 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8845 for (v = vStart; v < vEnd; ++v) { 8846 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8847 PetscInt off; 8848 8849 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8850 for (i = 0; i < dim; ++i) { 8851 for (j = 0; j < dim; ++j) { 8852 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8853 } 8854 } 8855 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8856 } 8857 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8858 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8859 } 8860 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8861 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8862 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 8863 /* Orthonormalize system */ 8864 for (i = dim; i < m; ++i) { 8865 PetscScalar dots[6]; 8866 8867 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8868 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8869 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8870 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 8871 } 8872 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8873 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8874 PetscFunctionReturn(0); 8875 } 8876 8877 #undef __FUNCT__ 8878 #define __FUNCT__ "DMPlexGetHybridBounds" 8879 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 8880 { 8881 DM_Plex *mesh = (DM_Plex*) dm->data; 8882 PetscInt dim; 8883 PetscErrorCode ierr; 8884 8885 PetscFunctionBegin; 8886 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8887 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8888 if (cMax) *cMax = mesh->hybridPointMax[dim]; 8889 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 8890 if (eMax) *eMax = mesh->hybridPointMax[1]; 8891 if (vMax) *vMax = mesh->hybridPointMax[0]; 8892 PetscFunctionReturn(0); 8893 } 8894 8895 #undef __FUNCT__ 8896 #define __FUNCT__ "DMPlexSetHybridBounds" 8897 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 8898 { 8899 DM_Plex *mesh = (DM_Plex*) dm->data; 8900 PetscInt dim; 8901 PetscErrorCode ierr; 8902 8903 PetscFunctionBegin; 8904 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8905 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8906 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 8907 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 8908 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 8909 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 8910 PetscFunctionReturn(0); 8911 } 8912 8913 #undef __FUNCT__ 8914 #define __FUNCT__ "DMPlexGetVTKCellHeight" 8915 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8916 { 8917 DM_Plex *mesh = (DM_Plex*) dm->data; 8918 8919 PetscFunctionBegin; 8920 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8921 PetscValidPointer(cellHeight, 2); 8922 *cellHeight = mesh->vtkCellHeight; 8923 PetscFunctionReturn(0); 8924 } 8925 8926 #undef __FUNCT__ 8927 #define __FUNCT__ "DMPlexSetVTKCellHeight" 8928 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8929 { 8930 DM_Plex *mesh = (DM_Plex*) dm->data; 8931 8932 PetscFunctionBegin; 8933 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8934 mesh->vtkCellHeight = cellHeight; 8935 PetscFunctionReturn(0); 8936 } 8937 8938 #undef __FUNCT__ 8939 #define __FUNCT__ "DMPlexCreateNumbering_Private" 8940 /* We can easily have a form that takes an IS instead */ 8941 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 8942 { 8943 PetscSection section, globalSection; 8944 PetscInt *numbers, p; 8945 PetscErrorCode ierr; 8946 8947 PetscFunctionBegin; 8948 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8949 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 8950 for (p = pStart; p < pEnd; ++p) { 8951 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 8952 } 8953 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 8954 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8955 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 8956 for (p = pStart; p < pEnd; ++p) { 8957 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8958 } 8959 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8960 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8961 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8962 PetscFunctionReturn(0); 8963 } 8964 8965 #undef __FUNCT__ 8966 #define __FUNCT__ "DMPlexGetCellNumbering" 8967 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8968 { 8969 DM_Plex *mesh = (DM_Plex*) dm->data; 8970 PetscInt cellHeight, cStart, cEnd, cMax; 8971 PetscErrorCode ierr; 8972 8973 PetscFunctionBegin; 8974 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8975 if (!mesh->globalCellNumbers) { 8976 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8977 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8978 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 8979 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8980 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 8981 } 8982 *globalCellNumbers = mesh->globalCellNumbers; 8983 PetscFunctionReturn(0); 8984 } 8985 8986 #undef __FUNCT__ 8987 #define __FUNCT__ "DMPlexGetVertexNumbering" 8988 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8989 { 8990 DM_Plex *mesh = (DM_Plex*) dm->data; 8991 PetscInt vStart, vEnd, vMax; 8992 PetscErrorCode ierr; 8993 8994 PetscFunctionBegin; 8995 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8996 if (!mesh->globalVertexNumbers) { 8997 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8998 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 8999 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9000 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9001 } 9002 *globalVertexNumbers = mesh->globalVertexNumbers; 9003 PetscFunctionReturn(0); 9004 } 9005 9006 #undef __FUNCT__ 9007 #define __FUNCT__ "DMPlexGetScale" 9008 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9009 { 9010 DM_Plex *mesh = (DM_Plex*) dm->data; 9011 9012 PetscFunctionBegin; 9013 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9014 PetscValidPointer(scale, 3); 9015 *scale = mesh->scale[unit]; 9016 PetscFunctionReturn(0); 9017 } 9018 9019 #undef __FUNCT__ 9020 #define __FUNCT__ "DMPlexSetScale" 9021 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9022 { 9023 DM_Plex *mesh = (DM_Plex*) dm->data; 9024 9025 PetscFunctionBegin; 9026 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9027 mesh->scale[unit] = scale; 9028 PetscFunctionReturn(0); 9029 } 9030 9031 9032 /******************************************************************************* 9033 This should be in a separate Discretization object, but I am not sure how to lay 9034 it out yet, so I am stuffing things here while I experiment. 9035 *******************************************************************************/ 9036 #undef __FUNCT__ 9037 #define __FUNCT__ "DMPlexSetFEMIntegration" 9038 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9039 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9040 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9041 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9042 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9043 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9044 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9045 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9046 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9047 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9048 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9049 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9050 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9051 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9052 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9053 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9054 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9055 { 9056 DM_Plex *mesh = (DM_Plex*) dm->data; 9057 9058 PetscFunctionBegin; 9059 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9060 mesh->integrateResidualFEM = integrateResidualFEM; 9061 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9062 mesh->integrateJacobianFEM = integrateJacobianFEM; 9063 PetscFunctionReturn(0); 9064 } 9065 9066 #undef __FUNCT__ 9067 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9068 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9069 { 9070 Vec coordinates; 9071 PetscSection section, cSection; 9072 PetscInt dim, vStart, vEnd, v, c, d; 9073 PetscScalar *values, *cArray; 9074 PetscReal *coords; 9075 PetscErrorCode ierr; 9076 9077 PetscFunctionBegin; 9078 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9079 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9080 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9081 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9082 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9083 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9084 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9085 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9086 for (v = vStart; v < vEnd; ++v) { 9087 PetscInt dof, off; 9088 9089 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9090 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9091 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9092 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9093 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9094 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9095 } 9096 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9097 /* Temporary, must be replaced by a projection on the finite element basis */ 9098 { 9099 PetscInt eStart = 0, eEnd = 0, e, depth; 9100 9101 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9102 --depth; 9103 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9104 for (e = eStart; e < eEnd; ++e) { 9105 const PetscInt *cone = NULL; 9106 PetscInt coneSize, d; 9107 PetscScalar *coordsA, *coordsB; 9108 9109 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9110 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9111 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9112 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9113 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9114 for (d = 0; d < dim; ++d) { 9115 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9116 } 9117 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9118 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9119 } 9120 } 9121 9122 ierr = PetscFree(coords);CHKERRQ(ierr); 9123 ierr = PetscFree(values);CHKERRQ(ierr); 9124 #if 0 9125 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9126 PetscReal detJ; 9127 9128 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9129 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9130 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9131 9132 for (PetscInt c = cStart; c < cEnd; ++c) { 9133 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9134 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9135 const int oSize = pV.getSize(); 9136 int v = 0; 9137 9138 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9139 for (PetscInt cl = 0; cl < oSize; ++cl) { 9140 const PetscInt fDim; 9141 9142 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9143 if (pointDim) { 9144 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9145 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9146 } 9147 } 9148 } 9149 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9150 pV.clear(); 9151 } 9152 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9153 ierr = PetscFree(values);CHKERRQ(ierr); 9154 #endif 9155 PetscFunctionReturn(0); 9156 } 9157 9158 #undef __FUNCT__ 9159 #define __FUNCT__ "DMPlexProjectFunction" 9160 /*@C 9161 DMPlexProjectFunction - This projects the given function into the function space provided. 9162 9163 Input Parameters: 9164 + dm - The DM 9165 . numComp - The number of components (functions) 9166 . funcs - The coordinate functions to evaluate 9167 - mode - The insertion mode for values 9168 9169 Output Parameter: 9170 . X - vector 9171 9172 Level: developer 9173 9174 Note: 9175 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9176 We will eventually fix it. 9177 9178 ,seealso: DMPlexComputeL2Diff() 9179 */ 9180 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9181 { 9182 Vec localX; 9183 PetscErrorCode ierr; 9184 9185 PetscFunctionBegin; 9186 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9187 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9188 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9189 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9190 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9191 PetscFunctionReturn(0); 9192 } 9193 9194 #undef __FUNCT__ 9195 #define __FUNCT__ "DMPlexComputeL2Diff" 9196 /*@C 9197 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9198 9199 Input Parameters: 9200 + dm - The DM 9201 . quad - The PetscQuadrature object for each field 9202 . funcs - The functions to evaluate for each field component 9203 - X - The coefficient vector u_h 9204 9205 Output Parameter: 9206 . diff - The diff ||u - u_h||_2 9207 9208 Level: developer 9209 9210 .seealso: DMPlexProjectFunction() 9211 */ 9212 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9213 { 9214 const PetscInt debug = 0; 9215 PetscSection section; 9216 Vec localX; 9217 PetscReal *coords, *v0, *J, *invJ, detJ; 9218 PetscReal localDiff = 0.0; 9219 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9220 PetscErrorCode ierr; 9221 9222 PetscFunctionBegin; 9223 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9224 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9225 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9226 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9227 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9228 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9229 for (field = 0; field < numFields; ++field) { 9230 numComponents += quad[field].numComponents; 9231 } 9232 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9233 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9234 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9235 for (c = cStart; c < cEnd; ++c) { 9236 const PetscScalar *x; 9237 PetscReal elemDiff = 0.0; 9238 9239 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9240 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9241 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9242 9243 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9244 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9245 const PetscReal *quadPoints = quad[field].quadPoints; 9246 const PetscReal *quadWeights = quad[field].quadWeights; 9247 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9248 const PetscInt numBasisComps = quad[field].numComponents; 9249 const PetscReal *basis = quad[field].basis; 9250 PetscInt q, d, e, fc, f; 9251 9252 if (debug) { 9253 char title[1024]; 9254 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9255 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9256 } 9257 for (q = 0; q < numQuadPoints; ++q) { 9258 for (d = 0; d < dim; d++) { 9259 coords[d] = v0[d]; 9260 for (e = 0; e < dim; e++) { 9261 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9262 } 9263 } 9264 for (fc = 0; fc < numBasisComps; ++fc) { 9265 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9266 PetscReal interpolant = 0.0; 9267 for (f = 0; f < numBasisFuncs; ++f) { 9268 const PetscInt fidx = f*numBasisComps+fc; 9269 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9270 } 9271 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9272 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9273 } 9274 } 9275 comp += numBasisComps; 9276 fieldOffset += numBasisFuncs*numBasisComps; 9277 } 9278 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9279 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9280 localDiff += elemDiff; 9281 } 9282 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9283 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9284 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9285 *diff = PetscSqrtReal(*diff); 9286 PetscFunctionReturn(0); 9287 } 9288 9289 #undef __FUNCT__ 9290 #define __FUNCT__ "DMPlexComputeResidualFEM" 9291 /*@ 9292 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9293 9294 Input Parameters: 9295 + dm - The mesh 9296 . X - Local input vector 9297 - user - The user context 9298 9299 Output Parameter: 9300 . F - Local output vector 9301 9302 Note: 9303 The second member of the user context must be an FEMContext. 9304 9305 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9306 like a GPU, or vectorize on a multicore machine. 9307 9308 .seealso: DMPlexComputeJacobianActionFEM() 9309 */ 9310 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9311 { 9312 DM_Plex *mesh = (DM_Plex*) dm->data; 9313 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9314 PetscQuadrature *quad = fem->quad; 9315 PetscSection section; 9316 PetscReal *v0, *J, *invJ, *detJ; 9317 PetscScalar *elemVec, *u; 9318 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9319 PetscInt cellDof = 0, numComponents = 0; 9320 PetscErrorCode ierr; 9321 9322 PetscFunctionBegin; 9323 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9324 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9325 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9326 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9327 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9328 numCells = cEnd - cStart; 9329 for (field = 0; field < numFields; ++field) { 9330 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9331 numComponents += quad[field].numComponents; 9332 } 9333 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9334 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9335 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); 9336 for (c = cStart; c < cEnd; ++c) { 9337 const PetscScalar *x; 9338 PetscInt i; 9339 9340 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9341 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9342 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9343 9344 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9345 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9346 } 9347 for (field = 0; field < numFields; ++field) { 9348 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9349 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9350 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9351 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9352 /* Conforming batches */ 9353 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9354 PetscInt numBlocks = 1; 9355 PetscInt batchSize = numBlocks * blockSize; 9356 PetscInt numBatches = numBatchesTmp; 9357 PetscInt numChunks = numCells / (numBatches*batchSize); 9358 /* Remainder */ 9359 PetscInt numRemainder = numCells % (numBatches * batchSize); 9360 PetscInt offset = numCells - numRemainder; 9361 9362 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9363 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9364 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9365 } 9366 for (c = cStart; c < cEnd; ++c) { 9367 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9368 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9369 } 9370 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9371 if (mesh->printFEM) { 9372 PetscMPIInt rank, numProcs; 9373 PetscInt p; 9374 9375 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9376 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9377 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9378 for (p = 0; p < numProcs; ++p) { 9379 if (p == rank) { 9380 Vec f; 9381 9382 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9383 ierr = VecCopy(F, f);CHKERRQ(ierr); 9384 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9385 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9386 ierr = VecDestroy(&f);CHKERRQ(ierr); 9387 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9388 } 9389 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9390 } 9391 } 9392 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9393 PetscFunctionReturn(0); 9394 } 9395 9396 #undef __FUNCT__ 9397 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9398 /*@C 9399 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9400 9401 Input Parameters: 9402 + dm - The mesh 9403 . J - The Jacobian shell matrix 9404 . X - Local input vector 9405 - user - The user context 9406 9407 Output Parameter: 9408 . F - Local output vector 9409 9410 Note: 9411 The second member of the user context must be an FEMContext. 9412 9413 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9414 like a GPU, or vectorize on a multicore machine. 9415 9416 .seealso: DMPlexComputeResidualFEM() 9417 */ 9418 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9419 { 9420 DM_Plex *mesh = (DM_Plex*) dm->data; 9421 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9422 PetscQuadrature *quad = fem->quad; 9423 PetscSection section; 9424 JacActionCtx *jctx; 9425 PetscReal *v0, *J, *invJ, *detJ; 9426 PetscScalar *elemVec, *u, *a; 9427 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9428 PetscInt cellDof = 0; 9429 PetscErrorCode ierr; 9430 9431 PetscFunctionBegin; 9432 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9433 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9434 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9435 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9436 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9437 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9438 numCells = cEnd - cStart; 9439 for (field = 0; field < numFields; ++field) { 9440 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9441 } 9442 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9443 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); 9444 for (c = cStart; c < cEnd; ++c) { 9445 const PetscScalar *x; 9446 PetscInt i; 9447 9448 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9449 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9450 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9451 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9452 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9453 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9454 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9455 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9456 } 9457 for (field = 0; field < numFields; ++field) { 9458 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9459 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9460 /* Conforming batches */ 9461 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9462 PetscInt numBlocks = 1; 9463 PetscInt batchSize = numBlocks * blockSize; 9464 PetscInt numBatches = numBatchesTmp; 9465 PetscInt numChunks = numCells / (numBatches*batchSize); 9466 /* Remainder */ 9467 PetscInt numRemainder = numCells % (numBatches * batchSize); 9468 PetscInt offset = numCells - numRemainder; 9469 9470 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); 9471 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], 9472 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9473 } 9474 for (c = cStart; c < cEnd; ++c) { 9475 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9476 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9477 } 9478 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9479 if (mesh->printFEM) { 9480 PetscMPIInt rank, numProcs; 9481 PetscInt p; 9482 9483 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9484 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9485 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9486 for (p = 0; p < numProcs; ++p) { 9487 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9488 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9489 } 9490 } 9491 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9492 PetscFunctionReturn(0); 9493 } 9494 9495 #undef __FUNCT__ 9496 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9497 /*@ 9498 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9499 9500 Input Parameters: 9501 + dm - The mesh 9502 . X - Local input vector 9503 - user - The user context 9504 9505 Output Parameter: 9506 . Jac - Jacobian matrix 9507 9508 Note: 9509 The second member of the user context must be an FEMContext. 9510 9511 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9512 like a GPU, or vectorize on a multicore machine. 9513 9514 .seealso: FormFunctionLocal() 9515 */ 9516 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9517 { 9518 DM_Plex *mesh = (DM_Plex*) dm->data; 9519 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9520 PetscQuadrature *quad = fem->quad; 9521 PetscSection section; 9522 PetscReal *v0, *J, *invJ, *detJ; 9523 PetscScalar *elemMat, *u; 9524 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9525 PetscInt cellDof = 0, numComponents = 0; 9526 PetscBool isShell; 9527 PetscErrorCode ierr; 9528 9529 PetscFunctionBegin; 9530 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9531 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9532 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9533 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9534 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9535 numCells = cEnd - cStart; 9536 for (field = 0; field < numFields; ++field) { 9537 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9538 numComponents += quad[field].numComponents; 9539 } 9540 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9541 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9542 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); 9543 for (c = cStart; c < cEnd; ++c) { 9544 const PetscScalar *x; 9545 PetscInt i; 9546 9547 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9548 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9549 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9550 9551 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9552 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9553 } 9554 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9555 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9556 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9557 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9558 PetscInt fieldJ; 9559 9560 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9561 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9562 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9563 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9564 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9565 /* Conforming batches */ 9566 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9567 PetscInt numBlocks = 1; 9568 PetscInt batchSize = numBlocks * blockSize; 9569 PetscInt numBatches = numBatchesTmp; 9570 PetscInt numChunks = numCells / (numBatches*batchSize); 9571 /* Remainder */ 9572 PetscInt numRemainder = numCells % (numBatches * batchSize); 9573 PetscInt offset = numCells - numRemainder; 9574 9575 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9576 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9577 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9578 } 9579 } 9580 for (c = cStart; c < cEnd; ++c) { 9581 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9582 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9583 } 9584 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9585 9586 /* Assemble matrix, using the 2-step process: 9587 MatAssemblyBegin(), MatAssemblyEnd(). */ 9588 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9589 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9590 9591 if (mesh->printFEM) { 9592 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9593 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9594 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9595 } 9596 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9597 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9598 if (isShell) { 9599 JacActionCtx *jctx; 9600 9601 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9602 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9603 } 9604 *str = SAME_NONZERO_PATTERN; 9605 PetscFunctionReturn(0); 9606 } 9607 9608 9609 #undef __FUNCT__ 9610 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9611 /*@C 9612 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9613 the local section and an SF describing the section point overlap. 9614 9615 Input Parameters: 9616 + s - The PetscSection for the local field layout 9617 . sf - The SF describing parallel layout of the section points 9618 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9619 . label - The label specifying the points 9620 - labelValue - The label stratum specifying the points 9621 9622 Output Parameter: 9623 . gsection - The PetscSection for the global field layout 9624 9625 Note: This gives negative sizes and offsets to points not owned by this process 9626 9627 Level: developer 9628 9629 .seealso: PetscSectionCreate() 9630 @*/ 9631 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9632 { 9633 PetscInt *neg; 9634 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9635 PetscErrorCode ierr; 9636 9637 PetscFunctionBegin; 9638 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9639 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9640 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9641 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9642 /* Mark ghost points with negative dof */ 9643 for (p = pStart; p < pEnd; ++p) { 9644 PetscInt value; 9645 9646 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9647 if (value != labelValue) continue; 9648 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9649 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9650 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9651 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9652 neg[p-pStart] = -(dof+1); 9653 } 9654 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9655 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 9656 if (nroots >= 0) { 9657 if (nroots > pEnd - pStart) { 9658 PetscInt *tmpDof; 9659 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9660 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9661 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9662 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9663 for (p = pStart; p < pEnd; ++p) { 9664 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 9665 } 9666 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9667 } else { 9668 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9669 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9670 } 9671 } 9672 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9673 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9674 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9675 9676 (*gsection)->atlasOff[p] = off; 9677 9678 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9679 } 9680 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9681 globalOff -= off; 9682 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9683 (*gsection)->atlasOff[p] += globalOff; 9684 9685 neg[p] = -((*gsection)->atlasOff[p]+1); 9686 } 9687 /* Put in negative offsets for ghost points */ 9688 if (nroots >= 0) { 9689 if (nroots > pEnd - pStart) { 9690 PetscInt *tmpOff; 9691 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9692 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9693 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9694 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9695 for (p = pStart; p < pEnd; ++p) { 9696 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 9697 } 9698 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9699 } else { 9700 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9701 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9702 } 9703 } 9704 ierr = PetscFree(neg);CHKERRQ(ierr); 9705 PetscFunctionReturn(0); 9706 } 9707