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_Internal" 3743 static PetscErrorCode DMPlexConstructGhostCells_Internal(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, or "Face Sets" if this is NULL 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 ierr = DMPlexConstructGhostCells_Internal(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3862 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3863 *dmGhosted = gdm; 3864 PetscFunctionReturn(0); 3865 } 3866 3867 #undef __FUNCT__ 3868 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3869 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3870 { 3871 MPI_Comm comm; 3872 IS valueIS, *pointIS; 3873 const PetscInt *values, **splitPoints; 3874 PetscSection coordSection; 3875 Vec coordinates; 3876 PetscScalar *coords; 3877 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3878 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3879 PetscErrorCode ierr; 3880 3881 PetscFunctionBegin; 3882 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3883 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3884 /* Count split points and add cohesive cells */ 3885 if (label) { 3886 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3887 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3888 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3889 } 3890 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3891 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3892 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3893 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3894 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3895 for (d = 0; d <= depth; ++d) { 3896 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3897 numSplitPoints[d] = 0; 3898 splitPoints[d] = NULL; 3899 pointIS[d] = NULL; 3900 } 3901 for (sp = 0; sp < numSP; ++sp) { 3902 const PetscInt dep = values[sp]; 3903 3904 if ((dep < 0) || (dep > depth)) continue; 3905 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3906 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3907 if (pointIS[dep]) { 3908 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3909 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3910 } 3911 } 3912 if (depth >= 0) { 3913 /* Calculate number of additional points */ 3914 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3915 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3916 /* Calculate hybrid bound for each dimension */ 3917 pMaxNew[0] += depthShift[depth]; 3918 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3919 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3920 3921 /* Calculate point offset for each dimension */ 3922 depthOffset[depth] = 0; 3923 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3924 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3925 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3926 } 3927 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3928 /* Step 3: Set cone/support sizes for new points */ 3929 for (dep = 0; dep <= depth; ++dep) { 3930 for (p = 0; p < numSplitPoints[dep]; ++p) { 3931 const PetscInt oldp = splitPoints[dep][p]; 3932 const PetscInt newp = depthOffset[dep] + oldp; 3933 const PetscInt splitp = pMaxNew[dep] + p; 3934 const PetscInt *support; 3935 PetscInt coneSize, supportSize, q, e; 3936 3937 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3938 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3939 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3940 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3941 if (dep == depth-1) { 3942 const PetscInt ccell = pMaxNew[depth] + p; 3943 /* Add cohesive cells, they are prisms */ 3944 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3945 } else if (dep == 0) { 3946 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3947 3948 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3949 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3950 for (e = 0, q = 0; e < supportSize; ++e) { 3951 PetscInt val; 3952 3953 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3954 if ((val == 1) || (val == (shift + 1))) ++q; 3955 } 3956 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3957 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3958 for (e = 0, q = 0; e < supportSize; ++e) { 3959 PetscInt val; 3960 3961 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3962 if ((val == 1) || (val == -(shift + 1))) ++q; 3963 } 3964 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3965 /* Add cohesive edges */ 3966 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3967 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3968 } else if (dep == dim-2) { 3969 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3970 /* Split old edge: Faces in positive side cells and old split faces */ 3971 for (e = 0, q = 0; e < supportSize; ++e) { 3972 PetscInt val; 3973 3974 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3975 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 3976 } 3977 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 3978 /* Split new edge: Faces in negative side cells and new split faces */ 3979 for (e = 0, q = 0; e < supportSize; ++e) { 3980 PetscInt val; 3981 3982 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3983 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 3984 } 3985 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 3986 } 3987 } 3988 } 3989 /* Step 4: Setup split DM */ 3990 ierr = DMSetUp(sdm);CHKERRQ(ierr); 3991 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3992 /* Step 6: Set cones and supports for new points */ 3993 for (dep = 0; dep <= depth; ++dep) { 3994 for (p = 0; p < numSplitPoints[dep]; ++p) { 3995 const PetscInt oldp = splitPoints[dep][p]; 3996 const PetscInt newp = depthOffset[dep] + oldp; 3997 const PetscInt splitp = pMaxNew[dep] + p; 3998 const PetscInt *cone, *support, *ornt; 3999 PetscInt coneSize, supportSize, q, v, e, s; 4000 4001 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4002 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4003 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4004 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4005 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4006 if (dep == depth-1) { 4007 const PetscInt ccell = pMaxNew[depth] + p; 4008 const PetscInt *supportF; 4009 4010 /* Split face: copy in old face to new face to start */ 4011 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4012 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4013 /* Split old face: old vertices/edges in cone so no change */ 4014 /* Split new face: new vertices/edges in cone */ 4015 for (q = 0; q < coneSize; ++q) { 4016 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4017 4018 coneNew[2+q] = pMaxNew[dim-2] + v; 4019 } 4020 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4021 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4022 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4023 coneNew[0] = newp; 4024 coneNew[1] = splitp; 4025 for (q = 0; q < coneSize; ++q) { 4026 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4027 } 4028 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4029 4030 4031 for (s = 0; s < supportSize; ++s) { 4032 PetscInt val; 4033 4034 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4035 if (val < 0) { 4036 /* Split old face: Replace negative side cell with cohesive cell */ 4037 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4038 } else { 4039 /* Split new face: Replace positive side cell with cohesive cell */ 4040 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4041 } 4042 } 4043 } else if (dep == 0) { 4044 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4045 4046 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4047 for (e = 0, q = 0; e < supportSize; ++e) { 4048 PetscInt val; 4049 4050 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4051 if ((val == 1) || (val == (shift + 1))) { 4052 supportNew[q++] = depthOffset[1] + support[e]; 4053 } 4054 } 4055 supportNew[q] = cedge; 4056 4057 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4058 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4059 for (e = 0, q = 0; e < supportSize; ++e) { 4060 PetscInt val, edge; 4061 4062 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4063 if (val == 1) { 4064 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4065 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4066 supportNew[q++] = pMaxNew[1] + edge; 4067 } else if (val == -(shift + 1)) { 4068 supportNew[q++] = depthOffset[1] + support[e]; 4069 } 4070 } 4071 supportNew[q] = cedge; 4072 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4073 /* Cohesive edge: Old and new split vertex, punting on support */ 4074 coneNew[0] = newp; 4075 coneNew[1] = splitp; 4076 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4077 } else if (dep == dim-2) { 4078 /* Split old edge: old vertices in cone so no change */ 4079 /* Split new edge: new vertices in cone */ 4080 for (q = 0; q < coneSize; ++q) { 4081 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4082 4083 coneNew[q] = pMaxNew[dim-3] + v; 4084 } 4085 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4086 /* Split old edge: Faces in positive side cells and old split faces */ 4087 for (e = 0, q = 0; e < supportSize; ++e) { 4088 PetscInt val; 4089 4090 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4091 if ((val == dim-1) || (val == (shift + dim-1))) { 4092 supportNew[q++] = depthOffset[dim-1] + support[e]; 4093 } 4094 } 4095 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4096 /* Split new edge: Faces in negative side cells and new split faces */ 4097 for (e = 0, q = 0; e < supportSize; ++e) { 4098 PetscInt val, face; 4099 4100 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4101 if (val == dim-1) { 4102 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4103 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4104 supportNew[q++] = pMaxNew[dim-1] + face; 4105 } else if (val == -(shift + dim-1)) { 4106 supportNew[q++] = depthOffset[dim-1] + support[e]; 4107 } 4108 } 4109 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4110 } 4111 } 4112 } 4113 /* Step 6b: Replace split points in negative side cones */ 4114 for (sp = 0; sp < numSP; ++sp) { 4115 PetscInt dep = values[sp]; 4116 IS pIS; 4117 PetscInt numPoints; 4118 const PetscInt *points; 4119 4120 if (dep >= 0) continue; 4121 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4122 if (!pIS) continue; 4123 dep = -dep - shift; 4124 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4125 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4126 for (p = 0; p < numPoints; ++p) { 4127 const PetscInt oldp = points[p]; 4128 const PetscInt newp = depthOffset[dep] + oldp; 4129 const PetscInt *cone; 4130 PetscInt coneSize, c; 4131 PetscBool replaced = PETSC_FALSE; 4132 4133 /* Negative edge: replace split vertex */ 4134 /* Negative cell: replace split face */ 4135 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4136 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4137 for (c = 0; c < coneSize; ++c) { 4138 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4139 PetscInt csplitp, cp, val; 4140 4141 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4142 if (val == dep-1) { 4143 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4144 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4145 csplitp = pMaxNew[dep-1] + cp; 4146 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4147 replaced = PETSC_TRUE; 4148 } 4149 } 4150 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4151 } 4152 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4153 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4154 } 4155 /* Step 7: Stratify */ 4156 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4157 /* Step 8: Coordinates */ 4158 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4159 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4160 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4161 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4162 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4163 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4164 const PetscInt splitp = pMaxNew[0] + v; 4165 PetscInt dof, off, soff, d; 4166 4167 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4168 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4169 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4170 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4171 } 4172 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4173 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4174 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4175 /* Step 10: Labels */ 4176 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4177 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4178 for (dep = 0; dep <= depth; ++dep) { 4179 for (p = 0; p < numSplitPoints[dep]; ++p) { 4180 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4181 const PetscInt splitp = pMaxNew[dep] + p; 4182 PetscInt l; 4183 4184 for (l = 0; l < numLabels; ++l) { 4185 DMLabel mlabel; 4186 const char *lname; 4187 PetscInt val; 4188 4189 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4190 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4191 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4192 if (val >= 0) { 4193 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4194 if (dep == 0) { 4195 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4196 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4197 } 4198 } 4199 } 4200 } 4201 } 4202 for (sp = 0; sp < numSP; ++sp) { 4203 const PetscInt dep = values[sp]; 4204 4205 if ((dep < 0) || (dep > depth)) continue; 4206 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4207 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4208 } 4209 if (label) { 4210 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4211 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4212 } 4213 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4214 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4215 PetscFunctionReturn(0); 4216 } 4217 4218 #undef __FUNCT__ 4219 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4220 /*@C 4221 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4222 4223 Collective on dm 4224 4225 Input Parameters: 4226 + dm - The original DM 4227 - labelName - The label specifying the boundary faces (this could be auto-generated) 4228 4229 Output Parameters: 4230 - dmSplit - The new DM 4231 4232 Level: developer 4233 4234 .seealso: DMCreate() 4235 */ 4236 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4237 { 4238 DM sdm; 4239 PetscInt dim; 4240 PetscErrorCode ierr; 4241 4242 PetscFunctionBegin; 4243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4244 PetscValidPointer(dmSplit, 4); 4245 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 4246 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4247 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4248 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4249 switch (dim) { 4250 case 2: 4251 case 3: 4252 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4253 break; 4254 default: 4255 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4256 } 4257 *dmSplit = sdm; 4258 PetscFunctionReturn(0); 4259 } 4260 4261 #undef __FUNCT__ 4262 #define __FUNCT__ "DMLabelCohesiveComplete" 4263 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4264 { 4265 IS dimIS; 4266 const PetscInt *points; 4267 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4268 PetscErrorCode ierr; 4269 4270 PetscFunctionBegin; 4271 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4272 /* Cell orientation for face gives the side of the fault */ 4273 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4274 if (!dimIS) PetscFunctionReturn(0); 4275 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4276 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4277 for (p = 0; p < numPoints; ++p) { 4278 const PetscInt *support; 4279 PetscInt supportSize, s; 4280 4281 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4282 if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4283 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4284 for (s = 0; s < supportSize; ++s) { 4285 const PetscInt *cone, *ornt; 4286 PetscInt coneSize, c; 4287 PetscBool pos = PETSC_TRUE; 4288 4289 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4290 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4291 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4292 for (c = 0; c < coneSize; ++c) { 4293 if (cone[c] == points[p]) { 4294 if (ornt[c] >= 0) { 4295 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4296 } else { 4297 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4298 pos = PETSC_FALSE; 4299 } 4300 break; 4301 } 4302 } 4303 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]); 4304 /* Put faces touching the fault in the label */ 4305 for (c = 0; c < coneSize; ++c) { 4306 const PetscInt point = cone[c]; 4307 4308 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4309 if (val == -1) { 4310 PetscInt *closure = NULL; 4311 PetscInt closureSize, cl; 4312 4313 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4314 for (cl = 0; cl < closureSize*2; cl += 2) { 4315 const PetscInt clp = closure[cl]; 4316 4317 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4318 if ((val >= 0) && (val < dim-1)) { 4319 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4320 break; 4321 } 4322 } 4323 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4324 } 4325 } 4326 } 4327 } 4328 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4329 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4330 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4331 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4332 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4333 if (!dimIS) PetscFunctionReturn(0); 4334 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4335 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4336 for (p = 0; p < numPoints; ++p) { 4337 PetscInt *star = NULL; 4338 PetscInt starSize, s; 4339 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4340 4341 /* First mark cells connected to the fault */ 4342 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4343 while (again) { 4344 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4345 again = 0; 4346 for (s = 0; s < starSize*2; s += 2) { 4347 const PetscInt point = star[s]; 4348 const PetscInt *cone; 4349 PetscInt coneSize, c; 4350 4351 if ((point < cStart) || (point >= cEnd)) continue; 4352 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4353 if (val != -1) continue; 4354 again = 2; 4355 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4356 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4357 for (c = 0; c < coneSize; ++c) { 4358 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4359 if (val != -1) { 4360 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); 4361 if (val > 0) { 4362 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4363 } else { 4364 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4365 } 4366 again = 1; 4367 break; 4368 } 4369 } 4370 } 4371 } 4372 /* Classify the rest by cell membership */ 4373 for (s = 0; s < starSize*2; s += 2) { 4374 const PetscInt point = star[s]; 4375 4376 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4377 if (val == -1) { 4378 PetscInt *sstar = NULL; 4379 PetscInt sstarSize, ss; 4380 PetscBool marked = PETSC_FALSE; 4381 4382 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4383 for (ss = 0; ss < sstarSize*2; ss += 2) { 4384 const PetscInt spoint = sstar[ss]; 4385 4386 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4387 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4388 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4389 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4390 if (val > 0) { 4391 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4392 } else { 4393 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4394 } 4395 marked = PETSC_TRUE; 4396 break; 4397 } 4398 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4399 if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 4400 } 4401 } 4402 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4403 } 4404 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4405 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4406 PetscFunctionReturn(0); 4407 } 4408 4409 #if defined(PETSC_HAVE_TRIANGLE) 4410 #include <triangle.h> 4411 4412 #undef __FUNCT__ 4413 #define __FUNCT__ "InitInput_Triangle" 4414 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4415 { 4416 PetscFunctionBegin; 4417 inputCtx->numberofpoints = 0; 4418 inputCtx->numberofpointattributes = 0; 4419 inputCtx->pointlist = NULL; 4420 inputCtx->pointattributelist = NULL; 4421 inputCtx->pointmarkerlist = NULL; 4422 inputCtx->numberofsegments = 0; 4423 inputCtx->segmentlist = NULL; 4424 inputCtx->segmentmarkerlist = NULL; 4425 inputCtx->numberoftriangleattributes = 0; 4426 inputCtx->trianglelist = NULL; 4427 inputCtx->numberofholes = 0; 4428 inputCtx->holelist = NULL; 4429 inputCtx->numberofregions = 0; 4430 inputCtx->regionlist = NULL; 4431 PetscFunctionReturn(0); 4432 } 4433 4434 #undef __FUNCT__ 4435 #define __FUNCT__ "InitOutput_Triangle" 4436 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4437 { 4438 PetscFunctionBegin; 4439 outputCtx->numberofpoints = 0; 4440 outputCtx->pointlist = NULL; 4441 outputCtx->pointattributelist = NULL; 4442 outputCtx->pointmarkerlist = NULL; 4443 outputCtx->numberoftriangles = 0; 4444 outputCtx->trianglelist = NULL; 4445 outputCtx->triangleattributelist = NULL; 4446 outputCtx->neighborlist = NULL; 4447 outputCtx->segmentlist = NULL; 4448 outputCtx->segmentmarkerlist = NULL; 4449 outputCtx->numberofedges = 0; 4450 outputCtx->edgelist = NULL; 4451 outputCtx->edgemarkerlist = NULL; 4452 PetscFunctionReturn(0); 4453 } 4454 4455 #undef __FUNCT__ 4456 #define __FUNCT__ "FiniOutput_Triangle" 4457 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4458 { 4459 PetscFunctionBegin; 4460 free(outputCtx->pointmarkerlist); 4461 free(outputCtx->edgelist); 4462 free(outputCtx->edgemarkerlist); 4463 free(outputCtx->trianglelist); 4464 free(outputCtx->neighborlist); 4465 PetscFunctionReturn(0); 4466 } 4467 4468 #undef __FUNCT__ 4469 #define __FUNCT__ "DMPlexGenerate_Triangle" 4470 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4471 { 4472 MPI_Comm comm; 4473 PetscInt dim = 2; 4474 const PetscBool createConvexHull = PETSC_FALSE; 4475 const PetscBool constrained = PETSC_FALSE; 4476 struct triangulateio in; 4477 struct triangulateio out; 4478 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4479 PetscMPIInt rank; 4480 PetscErrorCode ierr; 4481 4482 PetscFunctionBegin; 4483 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4484 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4485 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4486 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4487 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4488 4489 in.numberofpoints = vEnd - vStart; 4490 if (in.numberofpoints > 0) { 4491 PetscSection coordSection; 4492 Vec coordinates; 4493 PetscScalar *array; 4494 4495 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4496 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4497 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4498 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4499 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4500 for (v = vStart; v < vEnd; ++v) { 4501 const PetscInt idx = v - vStart; 4502 PetscInt off, d; 4503 4504 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4505 for (d = 0; d < dim; ++d) { 4506 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4507 } 4508 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4509 } 4510 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4511 } 4512 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4513 in.numberofsegments = eEnd - eStart; 4514 if (in.numberofsegments > 0) { 4515 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4516 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4517 for (e = eStart; e < eEnd; ++e) { 4518 const PetscInt idx = e - eStart; 4519 const PetscInt *cone; 4520 4521 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4522 4523 in.segmentlist[idx*2+0] = cone[0] - vStart; 4524 in.segmentlist[idx*2+1] = cone[1] - vStart; 4525 4526 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4527 } 4528 } 4529 #if 0 /* Do not currently support holes */ 4530 PetscReal *holeCoords; 4531 PetscInt h, d; 4532 4533 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4534 if (in.numberofholes > 0) { 4535 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4536 for (h = 0; h < in.numberofholes; ++h) { 4537 for (d = 0; d < dim; ++d) { 4538 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4539 } 4540 } 4541 } 4542 #endif 4543 if (!rank) { 4544 char args[32]; 4545 4546 /* Take away 'Q' for verbose output */ 4547 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4548 if (createConvexHull) { 4549 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4550 } 4551 if (constrained) { 4552 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4553 } 4554 triangulate(args, &in, &out, NULL); 4555 } 4556 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4557 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4558 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4559 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4560 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4561 4562 { 4563 const PetscInt numCorners = 3; 4564 const PetscInt numCells = out.numberoftriangles; 4565 const PetscInt numVertices = out.numberofpoints; 4566 const int *cells = out.trianglelist; 4567 const double *meshCoords = out.pointlist; 4568 4569 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4570 /* Set labels */ 4571 for (v = 0; v < numVertices; ++v) { 4572 if (out.pointmarkerlist[v]) { 4573 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4574 } 4575 } 4576 if (interpolate) { 4577 for (e = 0; e < out.numberofedges; e++) { 4578 if (out.edgemarkerlist[e]) { 4579 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4580 const PetscInt *edges; 4581 PetscInt numEdges; 4582 4583 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4584 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4585 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4586 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4587 } 4588 } 4589 } 4590 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4591 } 4592 #if 0 /* Do not currently support holes */ 4593 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4594 #endif 4595 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4596 PetscFunctionReturn(0); 4597 } 4598 4599 #undef __FUNCT__ 4600 #define __FUNCT__ "DMPlexRefine_Triangle" 4601 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4602 { 4603 MPI_Comm comm; 4604 PetscInt dim = 2; 4605 struct triangulateio in; 4606 struct triangulateio out; 4607 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4608 PetscMPIInt rank; 4609 PetscErrorCode ierr; 4610 4611 PetscFunctionBegin; 4612 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4613 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4614 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4615 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4616 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4617 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4618 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4619 4620 in.numberofpoints = vEnd - vStart; 4621 if (in.numberofpoints > 0) { 4622 PetscSection coordSection; 4623 Vec coordinates; 4624 PetscScalar *array; 4625 4626 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4627 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4628 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4629 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4630 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4631 for (v = vStart; v < vEnd; ++v) { 4632 const PetscInt idx = v - vStart; 4633 PetscInt off, d; 4634 4635 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4636 for (d = 0; d < dim; ++d) { 4637 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4638 } 4639 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4640 } 4641 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4642 } 4643 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4644 4645 in.numberofcorners = 3; 4646 in.numberoftriangles = cEnd - cStart; 4647 4648 in.trianglearealist = (double*) maxVolumes; 4649 if (in.numberoftriangles > 0) { 4650 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4651 for (c = cStart; c < cEnd; ++c) { 4652 const PetscInt idx = c - cStart; 4653 PetscInt *closure = NULL; 4654 PetscInt closureSize; 4655 4656 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4657 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4658 for (v = 0; v < 3; ++v) { 4659 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4660 } 4661 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4662 } 4663 } 4664 /* TODO: Segment markers are missing on input */ 4665 #if 0 /* Do not currently support holes */ 4666 PetscReal *holeCoords; 4667 PetscInt h, d; 4668 4669 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4670 if (in.numberofholes > 0) { 4671 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4672 for (h = 0; h < in.numberofholes; ++h) { 4673 for (d = 0; d < dim; ++d) { 4674 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4675 } 4676 } 4677 } 4678 #endif 4679 if (!rank) { 4680 char args[32]; 4681 4682 /* Take away 'Q' for verbose output */ 4683 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4684 triangulate(args, &in, &out, NULL); 4685 } 4686 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4687 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4688 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4689 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4690 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4691 4692 { 4693 const PetscInt numCorners = 3; 4694 const PetscInt numCells = out.numberoftriangles; 4695 const PetscInt numVertices = out.numberofpoints; 4696 const int *cells = out.trianglelist; 4697 const double *meshCoords = out.pointlist; 4698 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4699 4700 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4701 /* Set labels */ 4702 for (v = 0; v < numVertices; ++v) { 4703 if (out.pointmarkerlist[v]) { 4704 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4705 } 4706 } 4707 if (interpolate) { 4708 PetscInt e; 4709 4710 for (e = 0; e < out.numberofedges; e++) { 4711 if (out.edgemarkerlist[e]) { 4712 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4713 const PetscInt *edges; 4714 PetscInt numEdges; 4715 4716 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4717 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4718 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4719 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4720 } 4721 } 4722 } 4723 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4724 } 4725 #if 0 /* Do not currently support holes */ 4726 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4727 #endif 4728 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4729 PetscFunctionReturn(0); 4730 } 4731 #endif 4732 4733 #if defined(PETSC_HAVE_TETGEN) 4734 #include <tetgen.h> 4735 #undef __FUNCT__ 4736 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4737 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4738 { 4739 MPI_Comm comm; 4740 const PetscInt dim = 3; 4741 ::tetgenio in; 4742 ::tetgenio out; 4743 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4744 PetscMPIInt rank; 4745 PetscErrorCode ierr; 4746 4747 PetscFunctionBegin; 4748 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4749 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4750 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4751 in.numberofpoints = vEnd - vStart; 4752 if (in.numberofpoints > 0) { 4753 PetscSection coordSection; 4754 Vec coordinates; 4755 PetscScalar *array; 4756 4757 in.pointlist = new double[in.numberofpoints*dim]; 4758 in.pointmarkerlist = new int[in.numberofpoints]; 4759 4760 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4761 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4762 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4763 for (v = vStart; v < vEnd; ++v) { 4764 const PetscInt idx = v - vStart; 4765 PetscInt off, d; 4766 4767 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4768 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4769 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4770 } 4771 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4772 } 4773 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4774 4775 in.numberoffacets = fEnd - fStart; 4776 if (in.numberoffacets > 0) { 4777 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4778 in.facetmarkerlist = new int[in.numberoffacets]; 4779 for (f = fStart; f < fEnd; ++f) { 4780 const PetscInt idx = f - fStart; 4781 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 4782 4783 in.facetlist[idx].numberofpolygons = 1; 4784 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4785 in.facetlist[idx].numberofholes = 0; 4786 in.facetlist[idx].holelist = NULL; 4787 4788 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4789 for (p = 0; p < numPoints*2; p += 2) { 4790 const PetscInt point = points[p]; 4791 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 4792 } 4793 4794 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4795 poly->numberofvertices = numVertices; 4796 poly->vertexlist = new int[poly->numberofvertices]; 4797 for (v = 0; v < numVertices; ++v) { 4798 const PetscInt vIdx = points[v] - vStart; 4799 poly->vertexlist[v] = vIdx; 4800 } 4801 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4802 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4803 } 4804 } 4805 if (!rank) { 4806 char args[32]; 4807 4808 /* Take away 'Q' for verbose output */ 4809 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4810 ::tetrahedralize(args, &in, &out); 4811 } 4812 { 4813 const PetscInt numCorners = 4; 4814 const PetscInt numCells = out.numberoftetrahedra; 4815 const PetscInt numVertices = out.numberofpoints; 4816 const int *cells = out.tetrahedronlist; 4817 const double *meshCoords = out.pointlist; 4818 4819 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4820 /* Set labels */ 4821 for (v = 0; v < numVertices; ++v) { 4822 if (out.pointmarkerlist[v]) { 4823 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4824 } 4825 } 4826 if (interpolate) { 4827 PetscInt e; 4828 4829 for (e = 0; e < out.numberofedges; e++) { 4830 if (out.edgemarkerlist[e]) { 4831 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4832 const PetscInt *edges; 4833 PetscInt numEdges; 4834 4835 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4836 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4837 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4838 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4839 } 4840 } 4841 for (f = 0; f < out.numberoftrifaces; f++) { 4842 if (out.trifacemarkerlist[f]) { 4843 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4844 const PetscInt *faces; 4845 PetscInt numFaces; 4846 4847 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4848 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4849 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4850 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4851 } 4852 } 4853 } 4854 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4855 } 4856 PetscFunctionReturn(0); 4857 } 4858 4859 #undef __FUNCT__ 4860 #define __FUNCT__ "DMPlexRefine_Tetgen" 4861 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4862 { 4863 MPI_Comm comm; 4864 const PetscInt dim = 3; 4865 ::tetgenio in; 4866 ::tetgenio out; 4867 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4868 PetscMPIInt rank; 4869 PetscErrorCode ierr; 4870 4871 PetscFunctionBegin; 4872 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4873 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4874 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4875 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4876 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4877 4878 in.numberofpoints = vEnd - vStart; 4879 if (in.numberofpoints > 0) { 4880 PetscSection coordSection; 4881 Vec coordinates; 4882 PetscScalar *array; 4883 4884 in.pointlist = new double[in.numberofpoints*dim]; 4885 in.pointmarkerlist = new int[in.numberofpoints]; 4886 4887 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4888 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4889 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4890 for (v = vStart; v < vEnd; ++v) { 4891 const PetscInt idx = v - vStart; 4892 PetscInt off, d; 4893 4894 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4895 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4896 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4897 } 4898 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4899 } 4900 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4901 4902 in.numberofcorners = 4; 4903 in.numberoftetrahedra = cEnd - cStart; 4904 in.tetrahedronvolumelist = (double*) maxVolumes; 4905 if (in.numberoftetrahedra > 0) { 4906 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4907 for (c = cStart; c < cEnd; ++c) { 4908 const PetscInt idx = c - cStart; 4909 PetscInt *closure = NULL; 4910 PetscInt closureSize; 4911 4912 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4913 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 4914 for (v = 0; v < 4; ++v) { 4915 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4916 } 4917 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4918 } 4919 } 4920 /* TODO: Put in boundary faces with markers */ 4921 if (!rank) { 4922 char args[32]; 4923 4924 /* Take away 'Q' for verbose output */ 4925 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 4926 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4927 ::tetrahedralize(args, &in, &out); 4928 } 4929 in.tetrahedronvolumelist = NULL; 4930 4931 { 4932 const PetscInt numCorners = 4; 4933 const PetscInt numCells = out.numberoftetrahedra; 4934 const PetscInt numVertices = out.numberofpoints; 4935 const int *cells = out.tetrahedronlist; 4936 const double *meshCoords = out.pointlist; 4937 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4938 4939 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4940 /* Set labels */ 4941 for (v = 0; v < numVertices; ++v) { 4942 if (out.pointmarkerlist[v]) { 4943 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4944 } 4945 } 4946 if (interpolate) { 4947 PetscInt e, f; 4948 4949 for (e = 0; e < out.numberofedges; e++) { 4950 if (out.edgemarkerlist[e]) { 4951 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4952 const PetscInt *edges; 4953 PetscInt numEdges; 4954 4955 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4956 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4957 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4958 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4959 } 4960 } 4961 for (f = 0; f < out.numberoftrifaces; f++) { 4962 if (out.trifacemarkerlist[f]) { 4963 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4964 const PetscInt *faces; 4965 PetscInt numFaces; 4966 4967 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4968 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4969 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4970 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4971 } 4972 } 4973 } 4974 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4975 } 4976 PetscFunctionReturn(0); 4977 } 4978 #endif 4979 4980 #if defined(PETSC_HAVE_CTETGEN) 4981 #include "ctetgen.h" 4982 4983 #undef __FUNCT__ 4984 #define __FUNCT__ "DMPlexGenerate_CTetgen" 4985 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 4986 { 4987 MPI_Comm comm; 4988 const PetscInt dim = 3; 4989 PLC *in, *out; 4990 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 4991 PetscMPIInt rank; 4992 PetscErrorCode ierr; 4993 4994 PetscFunctionBegin; 4995 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4996 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 4997 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4998 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4999 ierr = PLCCreate(&in);CHKERRQ(ierr); 5000 ierr = PLCCreate(&out);CHKERRQ(ierr); 5001 5002 in->numberofpoints = vEnd - vStart; 5003 if (in->numberofpoints > 0) { 5004 PetscSection coordSection; 5005 Vec coordinates; 5006 PetscScalar *array; 5007 5008 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5009 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5010 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5011 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5012 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5013 for (v = vStart; v < vEnd; ++v) { 5014 const PetscInt idx = v - vStart; 5015 PetscInt off, d, m; 5016 5017 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5018 for (d = 0; d < dim; ++d) { 5019 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5020 } 5021 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5022 5023 in->pointmarkerlist[idx] = (int) m; 5024 } 5025 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5026 } 5027 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5028 5029 in->numberoffacets = fEnd - fStart; 5030 if (in->numberoffacets > 0) { 5031 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5032 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5033 for (f = fStart; f < fEnd; ++f) { 5034 const PetscInt idx = f - fStart; 5035 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5036 polygon *poly; 5037 5038 in->facetlist[idx].numberofpolygons = 1; 5039 5040 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5041 5042 in->facetlist[idx].numberofholes = 0; 5043 in->facetlist[idx].holelist = NULL; 5044 5045 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5046 for (p = 0; p < numPoints*2; p += 2) { 5047 const PetscInt point = points[p]; 5048 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5049 } 5050 5051 poly = in->facetlist[idx].polygonlist; 5052 poly->numberofvertices = numVertices; 5053 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5054 for (v = 0; v < numVertices; ++v) { 5055 const PetscInt vIdx = points[v] - vStart; 5056 poly->vertexlist[v] = vIdx; 5057 } 5058 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5059 in->facetmarkerlist[idx] = (int) m; 5060 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5061 } 5062 } 5063 if (!rank) { 5064 TetGenOpts t; 5065 5066 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5067 t.in = boundary; /* Should go away */ 5068 t.plc = 1; 5069 t.quality = 1; 5070 t.edgesout = 1; 5071 t.zeroindex = 1; 5072 t.quiet = 1; 5073 t.verbose = verbose; 5074 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5075 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5076 } 5077 { 5078 const PetscInt numCorners = 4; 5079 const PetscInt numCells = out->numberoftetrahedra; 5080 const PetscInt numVertices = out->numberofpoints; 5081 const int *cells = out->tetrahedronlist; 5082 const double *meshCoords = out->pointlist; 5083 5084 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 5085 /* Set labels */ 5086 for (v = 0; v < numVertices; ++v) { 5087 if (out->pointmarkerlist[v]) { 5088 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5089 } 5090 } 5091 if (interpolate) { 5092 PetscInt e; 5093 5094 for (e = 0; e < out->numberofedges; e++) { 5095 if (out->edgemarkerlist[e]) { 5096 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5097 const PetscInt *edges; 5098 PetscInt numEdges; 5099 5100 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5101 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5102 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5103 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5104 } 5105 } 5106 for (f = 0; f < out->numberoftrifaces; f++) { 5107 if (out->trifacemarkerlist[f]) { 5108 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5109 const PetscInt *faces; 5110 PetscInt numFaces; 5111 5112 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5113 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5114 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5115 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5116 } 5117 } 5118 } 5119 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5120 } 5121 5122 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5123 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5124 PetscFunctionReturn(0); 5125 } 5126 5127 #undef __FUNCT__ 5128 #define __FUNCT__ "DMPlexRefine_CTetgen" 5129 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5130 { 5131 MPI_Comm comm; 5132 const PetscInt dim = 3; 5133 PLC *in, *out; 5134 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5135 PetscMPIInt rank; 5136 PetscErrorCode ierr; 5137 5138 PetscFunctionBegin; 5139 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5140 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5141 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5142 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5143 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5144 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5145 ierr = PLCCreate(&in);CHKERRQ(ierr); 5146 ierr = PLCCreate(&out);CHKERRQ(ierr); 5147 5148 in->numberofpoints = vEnd - vStart; 5149 if (in->numberofpoints > 0) { 5150 PetscSection coordSection; 5151 Vec coordinates; 5152 PetscScalar *array; 5153 5154 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5155 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5156 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5157 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5158 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5159 for (v = vStart; v < vEnd; ++v) { 5160 const PetscInt idx = v - vStart; 5161 PetscInt off, d, m; 5162 5163 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5164 for (d = 0; d < dim; ++d) { 5165 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5166 } 5167 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5168 5169 in->pointmarkerlist[idx] = (int) m; 5170 } 5171 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5172 } 5173 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5174 5175 in->numberofcorners = 4; 5176 in->numberoftetrahedra = cEnd - cStart; 5177 in->tetrahedronvolumelist = maxVolumes; 5178 if (in->numberoftetrahedra > 0) { 5179 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5180 for (c = cStart; c < cEnd; ++c) { 5181 const PetscInt idx = c - cStart; 5182 PetscInt *closure = NULL; 5183 PetscInt closureSize; 5184 5185 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5186 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5187 for (v = 0; v < 4; ++v) { 5188 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5189 } 5190 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5191 } 5192 } 5193 if (!rank) { 5194 TetGenOpts t; 5195 5196 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5197 5198 t.in = dm; /* Should go away */ 5199 t.refine = 1; 5200 t.varvolume = 1; 5201 t.quality = 1; 5202 t.edgesout = 1; 5203 t.zeroindex = 1; 5204 t.quiet = 1; 5205 t.verbose = verbose; /* Change this */ 5206 5207 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5208 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5209 } 5210 { 5211 const PetscInt numCorners = 4; 5212 const PetscInt numCells = out->numberoftetrahedra; 5213 const PetscInt numVertices = out->numberofpoints; 5214 const int *cells = out->tetrahedronlist; 5215 const double *meshCoords = out->pointlist; 5216 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5217 5218 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 5219 /* Set labels */ 5220 for (v = 0; v < numVertices; ++v) { 5221 if (out->pointmarkerlist[v]) { 5222 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5223 } 5224 } 5225 if (interpolate) { 5226 PetscInt e, f; 5227 5228 for (e = 0; e < out->numberofedges; e++) { 5229 if (out->edgemarkerlist[e]) { 5230 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5231 const PetscInt *edges; 5232 PetscInt numEdges; 5233 5234 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5235 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5236 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5237 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5238 } 5239 } 5240 for (f = 0; f < out->numberoftrifaces; f++) { 5241 if (out->trifacemarkerlist[f]) { 5242 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5243 const PetscInt *faces; 5244 PetscInt numFaces; 5245 5246 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5247 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5248 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5249 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5250 } 5251 } 5252 } 5253 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5254 } 5255 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5256 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5257 PetscFunctionReturn(0); 5258 } 5259 #endif 5260 5261 #undef __FUNCT__ 5262 #define __FUNCT__ "DMPlexGenerate" 5263 /*@C 5264 DMPlexGenerate - Generates a mesh. 5265 5266 Not Collective 5267 5268 Input Parameters: 5269 + boundary - The DMPlex boundary object 5270 . name - The mesh generation package name 5271 - interpolate - Flag to create intermediate mesh elements 5272 5273 Output Parameter: 5274 . mesh - The DMPlex object 5275 5276 Level: intermediate 5277 5278 .keywords: mesh, elements 5279 .seealso: DMPlexCreate(), DMRefine() 5280 @*/ 5281 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5282 { 5283 PetscInt dim; 5284 char genname[1024]; 5285 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5286 PetscErrorCode ierr; 5287 5288 PetscFunctionBegin; 5289 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5290 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5291 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5292 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5293 if (flg) name = genname; 5294 if (name) { 5295 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5296 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5297 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5298 } 5299 switch (dim) { 5300 case 1: 5301 if (!name || isTriangle) { 5302 #if defined(PETSC_HAVE_TRIANGLE) 5303 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5304 #else 5305 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5306 #endif 5307 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5308 break; 5309 case 2: 5310 if (!name || isCTetgen) { 5311 #if defined(PETSC_HAVE_CTETGEN) 5312 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5313 #else 5314 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5315 #endif 5316 } else if (isTetgen) { 5317 #if defined(PETSC_HAVE_TETGEN) 5318 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5319 #else 5320 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5321 #endif 5322 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5323 break; 5324 default: 5325 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5326 } 5327 PetscFunctionReturn(0); 5328 } 5329 5330 typedef PetscInt CellRefiner; 5331 5332 #undef __FUNCT__ 5333 #define __FUNCT__ "GetDepthStart_Private" 5334 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5335 { 5336 PetscFunctionBegin; 5337 if (cStart) *cStart = 0; 5338 if (vStart) *vStart = depthSize[depth]; 5339 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5340 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5341 PetscFunctionReturn(0); 5342 } 5343 5344 #undef __FUNCT__ 5345 #define __FUNCT__ "GetDepthEnd_Private" 5346 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5347 { 5348 PetscFunctionBegin; 5349 if (cEnd) *cEnd = depthSize[depth]; 5350 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5351 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5352 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5353 PetscFunctionReturn(0); 5354 } 5355 5356 #undef __FUNCT__ 5357 #define __FUNCT__ "CellRefinerGetSizes" 5358 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5359 { 5360 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5361 PetscErrorCode ierr; 5362 5363 PetscFunctionBegin; 5364 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5365 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5366 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5367 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5368 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5369 switch (refiner) { 5370 case 1: 5371 /* Simplicial 2D */ 5372 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5373 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5374 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5375 break; 5376 case 3: 5377 /* Hybrid 2D */ 5378 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5379 cMax = PetscMin(cEnd, cMax); 5380 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5381 fMax = PetscMin(fEnd, fMax); 5382 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5383 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 */ 5384 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5385 break; 5386 case 2: 5387 /* Hex 2D */ 5388 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5389 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5390 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5391 break; 5392 default: 5393 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5394 } 5395 PetscFunctionReturn(0); 5396 } 5397 5398 #undef __FUNCT__ 5399 #define __FUNCT__ "CellRefinerSetConeSizes" 5400 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5401 { 5402 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5403 PetscErrorCode ierr; 5404 5405 PetscFunctionBegin; 5406 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5407 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5408 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5409 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5410 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5411 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5412 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5413 switch (refiner) { 5414 case 1: 5415 /* Simplicial 2D */ 5416 /* All cells have 3 faces */ 5417 for (c = cStart; c < cEnd; ++c) { 5418 for (r = 0; r < 4; ++r) { 5419 const PetscInt newp = (c - cStart)*4 + r; 5420 5421 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5422 } 5423 } 5424 /* Split faces have 2 vertices and the same cells as the parent */ 5425 for (f = fStart; f < fEnd; ++f) { 5426 for (r = 0; r < 2; ++r) { 5427 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5428 PetscInt size; 5429 5430 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5431 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5432 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5433 } 5434 } 5435 /* Interior faces have 2 vertices and 2 cells */ 5436 for (c = cStart; c < cEnd; ++c) { 5437 for (r = 0; r < 3; ++r) { 5438 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5439 5440 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5441 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5442 } 5443 } 5444 /* Old vertices have identical supports */ 5445 for (v = vStart; v < vEnd; ++v) { 5446 const PetscInt newp = vStartNew + (v - vStart); 5447 PetscInt size; 5448 5449 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5450 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5451 } 5452 /* Face vertices have 2 + cells*2 supports */ 5453 for (f = fStart; f < fEnd; ++f) { 5454 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5455 PetscInt size; 5456 5457 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5458 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5459 } 5460 break; 5461 case 2: 5462 /* Hex 2D */ 5463 /* All cells have 4 faces */ 5464 for (c = cStart; c < cEnd; ++c) { 5465 for (r = 0; r < 4; ++r) { 5466 const PetscInt newp = (c - cStart)*4 + r; 5467 5468 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5469 } 5470 } 5471 /* Split faces have 2 vertices and the same cells as the parent */ 5472 for (f = fStart; f < fEnd; ++f) { 5473 for (r = 0; r < 2; ++r) { 5474 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5475 PetscInt size; 5476 5477 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5478 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5479 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5480 } 5481 } 5482 /* Interior faces have 2 vertices and 2 cells */ 5483 for (c = cStart; c < cEnd; ++c) { 5484 for (r = 0; r < 4; ++r) { 5485 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5486 5487 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5488 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5489 } 5490 } 5491 /* Old vertices have identical supports */ 5492 for (v = vStart; v < vEnd; ++v) { 5493 const PetscInt newp = vStartNew + (v - vStart); 5494 PetscInt size; 5495 5496 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5497 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5498 } 5499 /* Face vertices have 2 + cells supports */ 5500 for (f = fStart; f < fEnd; ++f) { 5501 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5502 PetscInt size; 5503 5504 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5505 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5506 } 5507 /* Cell vertices have 4 supports */ 5508 for (c = cStart; c < cEnd; ++c) { 5509 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5510 5511 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5512 } 5513 break; 5514 case 3: 5515 /* Hybrid 2D */ 5516 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5517 cMax = PetscMin(cEnd, cMax); 5518 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5519 fMax = PetscMin(fEnd, fMax); 5520 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5521 /* Interior cells have 3 faces */ 5522 for (c = cStart; c < cMax; ++c) { 5523 for (r = 0; r < 4; ++r) { 5524 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5525 5526 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5527 } 5528 } 5529 /* Hybrid cells have 4 faces */ 5530 for (c = cMax; c < cEnd; ++c) { 5531 for (r = 0; r < 2; ++r) { 5532 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5533 5534 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5535 } 5536 } 5537 /* Interior split faces have 2 vertices and the same cells as the parent */ 5538 for (f = fStart; f < fMax; ++f) { 5539 for (r = 0; r < 2; ++r) { 5540 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5541 PetscInt size; 5542 5543 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5544 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5545 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5546 } 5547 } 5548 /* Interior cell faces have 2 vertices and 2 cells */ 5549 for (c = cStart; c < cMax; ++c) { 5550 for (r = 0; r < 3; ++r) { 5551 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5552 5553 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5554 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5555 } 5556 } 5557 /* Hybrid faces have 2 vertices and the same cells */ 5558 for (f = fMax; f < fEnd; ++f) { 5559 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5560 PetscInt size; 5561 5562 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5563 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5564 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5565 } 5566 /* Hybrid cell faces have 2 vertices and 2 cells */ 5567 for (c = cMax; c < cEnd; ++c) { 5568 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5569 5570 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5571 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5572 } 5573 /* Old vertices have identical supports */ 5574 for (v = vStart; v < vEnd; ++v) { 5575 const PetscInt newp = vStartNew + (v - vStart); 5576 PetscInt size; 5577 5578 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5579 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5580 } 5581 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5582 for (f = fStart; f < fMax; ++f) { 5583 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5584 const PetscInt *support; 5585 PetscInt size, newSize = 2, s; 5586 5587 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5588 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5589 for (s = 0; s < size; ++s) { 5590 if (support[s] >= cMax) newSize += 1; 5591 else newSize += 2; 5592 } 5593 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5594 } 5595 break; 5596 default: 5597 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5598 } 5599 PetscFunctionReturn(0); 5600 } 5601 5602 #undef __FUNCT__ 5603 #define __FUNCT__ "CellRefinerSetCones" 5604 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5605 { 5606 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; 5607 PetscInt maxSupportSize, *supportRef; 5608 PetscErrorCode ierr; 5609 5610 PetscFunctionBegin; 5611 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5612 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5613 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5614 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5615 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5616 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5617 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5618 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5619 switch (refiner) { 5620 case 1: 5621 /* Simplicial 2D */ 5622 /* 5623 2 5624 |\ 5625 | \ 5626 | \ 5627 | \ 5628 | C \ 5629 | \ 5630 | \ 5631 2---1---1 5632 |\ D / \ 5633 | 2 0 \ 5634 |A \ / B \ 5635 0---0-------1 5636 */ 5637 /* All cells have 3 faces */ 5638 for (c = cStart; c < cEnd; ++c) { 5639 const PetscInt newp = cStartNew + (c - cStart)*4; 5640 const PetscInt *cone, *ornt; 5641 PetscInt coneNew[3], orntNew[3]; 5642 5643 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5644 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5645 /* A triangle */ 5646 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5647 orntNew[0] = ornt[0]; 5648 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5649 orntNew[1] = -2; 5650 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5651 orntNew[2] = ornt[2]; 5652 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5653 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5654 #if 1 5655 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); 5656 for (p = 0; p < 3; ++p) { 5657 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); 5658 } 5659 #endif 5660 /* B triangle */ 5661 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5662 orntNew[0] = ornt[0]; 5663 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5664 orntNew[1] = ornt[1]; 5665 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5666 orntNew[2] = -2; 5667 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5668 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5669 #if 1 5670 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); 5671 for (p = 0; p < 3; ++p) { 5672 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); 5673 } 5674 #endif 5675 /* C triangle */ 5676 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5677 orntNew[0] = -2; 5678 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5679 orntNew[1] = ornt[1]; 5680 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5681 orntNew[2] = ornt[2]; 5682 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5683 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5684 #if 1 5685 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); 5686 for (p = 0; p < 3; ++p) { 5687 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); 5688 } 5689 #endif 5690 /* D triangle */ 5691 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5692 orntNew[0] = 0; 5693 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5694 orntNew[1] = 0; 5695 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5696 orntNew[2] = 0; 5697 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5698 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5699 #if 1 5700 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); 5701 for (p = 0; p < 3; ++p) { 5702 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); 5703 } 5704 #endif 5705 } 5706 /* Split faces have 2 vertices and the same cells as the parent */ 5707 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5708 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5709 for (f = fStart; f < fEnd; ++f) { 5710 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5711 5712 for (r = 0; r < 2; ++r) { 5713 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5714 const PetscInt *cone, *support; 5715 PetscInt coneNew[2], coneSize, c, supportSize, s; 5716 5717 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5718 coneNew[0] = vStartNew + (cone[0] - vStart); 5719 coneNew[1] = vStartNew + (cone[1] - vStart); 5720 coneNew[(r+1)%2] = newv; 5721 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5722 #if 1 5723 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5724 for (p = 0; p < 2; ++p) { 5725 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); 5726 } 5727 #endif 5728 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5729 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5730 for (s = 0; s < supportSize; ++s) { 5731 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5732 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5733 for (c = 0; c < coneSize; ++c) { 5734 if (cone[c] == f) break; 5735 } 5736 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5737 } 5738 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5739 #if 1 5740 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5741 for (p = 0; p < supportSize; ++p) { 5742 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); 5743 } 5744 #endif 5745 } 5746 } 5747 /* Interior faces have 2 vertices and 2 cells */ 5748 for (c = cStart; c < cEnd; ++c) { 5749 const PetscInt *cone; 5750 5751 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5752 for (r = 0; r < 3; ++r) { 5753 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5754 PetscInt coneNew[2]; 5755 PetscInt supportNew[2]; 5756 5757 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5758 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5759 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5760 #if 1 5761 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5762 for (p = 0; p < 2; ++p) { 5763 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); 5764 } 5765 #endif 5766 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5767 supportNew[1] = (c - cStart)*4 + 3; 5768 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5769 #if 1 5770 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5771 for (p = 0; p < 2; ++p) { 5772 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); 5773 } 5774 #endif 5775 } 5776 } 5777 /* Old vertices have identical supports */ 5778 for (v = vStart; v < vEnd; ++v) { 5779 const PetscInt newp = vStartNew + (v - vStart); 5780 const PetscInt *support, *cone; 5781 PetscInt size, s; 5782 5783 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5784 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5785 for (s = 0; s < size; ++s) { 5786 PetscInt r = 0; 5787 5788 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5789 if (cone[1] == v) r = 1; 5790 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5791 } 5792 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5793 #if 1 5794 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5795 for (p = 0; p < size; ++p) { 5796 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); 5797 } 5798 #endif 5799 } 5800 /* Face vertices have 2 + cells*2 supports */ 5801 for (f = fStart; f < fEnd; ++f) { 5802 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5803 const PetscInt *cone, *support; 5804 PetscInt size, s; 5805 5806 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5807 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5808 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5809 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5810 for (s = 0; s < size; ++s) { 5811 PetscInt r = 0; 5812 5813 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5814 if (cone[1] == f) r = 1; 5815 else if (cone[2] == f) r = 2; 5816 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5817 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5818 } 5819 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5820 #if 1 5821 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5822 for (p = 0; p < 2+size*2; ++p) { 5823 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); 5824 } 5825 #endif 5826 } 5827 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5828 break; 5829 case 2: 5830 /* Hex 2D */ 5831 /* 5832 3---------2---------2 5833 | | | 5834 | D 2 C | 5835 | | | 5836 3----3----0----1----1 5837 | | | 5838 | A 0 B | 5839 | | | 5840 0---------0---------1 5841 */ 5842 /* All cells have 4 faces */ 5843 for (c = cStart; c < cEnd; ++c) { 5844 const PetscInt newp = (c - cStart)*4; 5845 const PetscInt *cone, *ornt; 5846 PetscInt coneNew[4], orntNew[4]; 5847 5848 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5849 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5850 /* A quad */ 5851 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5852 orntNew[0] = ornt[0]; 5853 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5854 orntNew[1] = 0; 5855 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5856 orntNew[2] = -2; 5857 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5858 orntNew[3] = ornt[3]; 5859 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5860 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5861 #if 1 5862 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); 5863 for (p = 0; p < 4; ++p) { 5864 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); 5865 } 5866 #endif 5867 /* B quad */ 5868 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5869 orntNew[0] = ornt[0]; 5870 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5871 orntNew[1] = ornt[1]; 5872 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5873 orntNew[2] = 0; 5874 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5875 orntNew[3] = -2; 5876 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5877 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5878 #if 1 5879 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); 5880 for (p = 0; p < 4; ++p) { 5881 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); 5882 } 5883 #endif 5884 /* C quad */ 5885 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5886 orntNew[0] = -2; 5887 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5888 orntNew[1] = ornt[1]; 5889 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5890 orntNew[2] = ornt[2]; 5891 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5892 orntNew[3] = 0; 5893 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5894 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5895 #if 1 5896 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); 5897 for (p = 0; p < 4; ++p) { 5898 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); 5899 } 5900 #endif 5901 /* D quad */ 5902 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5903 orntNew[0] = 0; 5904 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5905 orntNew[1] = -2; 5906 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5907 orntNew[2] = ornt[2]; 5908 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5909 orntNew[3] = ornt[3]; 5910 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5911 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5912 #if 1 5913 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); 5914 for (p = 0; p < 4; ++p) { 5915 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); 5916 } 5917 #endif 5918 } 5919 /* Split faces have 2 vertices and the same cells as the parent */ 5920 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5921 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5922 for (f = fStart; f < fEnd; ++f) { 5923 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5924 5925 for (r = 0; r < 2; ++r) { 5926 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5927 const PetscInt *cone, *support; 5928 PetscInt coneNew[2], coneSize, c, supportSize, s; 5929 5930 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5931 coneNew[0] = vStartNew + (cone[0] - vStart); 5932 coneNew[1] = vStartNew + (cone[1] - vStart); 5933 coneNew[(r+1)%2] = newv; 5934 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5935 #if 1 5936 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5937 for (p = 0; p < 2; ++p) { 5938 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); 5939 } 5940 #endif 5941 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5942 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5943 for (s = 0; s < supportSize; ++s) { 5944 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5945 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5946 for (c = 0; c < coneSize; ++c) { 5947 if (cone[c] == f) break; 5948 } 5949 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5950 } 5951 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5952 #if 1 5953 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5954 for (p = 0; p < supportSize; ++p) { 5955 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); 5956 } 5957 #endif 5958 } 5959 } 5960 /* Interior faces have 2 vertices and 2 cells */ 5961 for (c = cStart; c < cEnd; ++c) { 5962 const PetscInt *cone; 5963 PetscInt coneNew[2], supportNew[2]; 5964 5965 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5966 for (r = 0; r < 4; ++r) { 5967 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5968 5969 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5970 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5971 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5972 #if 1 5973 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5974 for (p = 0; p < 2; ++p) { 5975 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); 5976 } 5977 #endif 5978 supportNew[0] = (c - cStart)*4 + r; 5979 supportNew[1] = (c - cStart)*4 + (r+1)%4; 5980 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5981 #if 1 5982 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5983 for (p = 0; p < 2; ++p) { 5984 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); 5985 } 5986 #endif 5987 } 5988 } 5989 /* Old vertices have identical supports */ 5990 for (v = vStart; v < vEnd; ++v) { 5991 const PetscInt newp = vStartNew + (v - vStart); 5992 const PetscInt *support, *cone; 5993 PetscInt size, s; 5994 5995 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5996 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5997 for (s = 0; s < size; ++s) { 5998 PetscInt r = 0; 5999 6000 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6001 if (cone[1] == v) r = 1; 6002 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6003 } 6004 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6005 #if 1 6006 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6007 for (p = 0; p < size; ++p) { 6008 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); 6009 } 6010 #endif 6011 } 6012 /* Face vertices have 2 + cells supports */ 6013 for (f = fStart; f < fEnd; ++f) { 6014 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6015 const PetscInt *cone, *support; 6016 PetscInt size, s; 6017 6018 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6019 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6020 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6021 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6022 for (s = 0; s < size; ++s) { 6023 PetscInt r = 0; 6024 6025 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6026 if (cone[1] == f) r = 1; 6027 else if (cone[2] == f) r = 2; 6028 else if (cone[3] == f) r = 3; 6029 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6030 } 6031 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6032 #if 1 6033 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6034 for (p = 0; p < 2+size; ++p) { 6035 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); 6036 } 6037 #endif 6038 } 6039 /* Cell vertices have 4 supports */ 6040 for (c = cStart; c < cEnd; ++c) { 6041 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6042 PetscInt supportNew[4]; 6043 6044 for (r = 0; r < 4; ++r) { 6045 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6046 } 6047 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6048 } 6049 break; 6050 case 3: 6051 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6052 cMax = PetscMin(cEnd, cMax); 6053 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6054 fMax = PetscMin(fEnd, fMax); 6055 /* Interior cells have 3 faces */ 6056 for (c = cStart; c < cMax; ++c) { 6057 const PetscInt newp = cStartNew + (c - cStart)*4; 6058 const PetscInt *cone, *ornt; 6059 PetscInt coneNew[3], orntNew[3]; 6060 6061 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6062 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6063 /* A triangle */ 6064 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6065 orntNew[0] = ornt[0]; 6066 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6067 orntNew[1] = -2; 6068 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6069 orntNew[2] = ornt[2]; 6070 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6071 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6072 #if 1 6073 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); 6074 for (p = 0; p < 3; ++p) { 6075 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); 6076 } 6077 #endif 6078 /* B triangle */ 6079 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6080 orntNew[0] = ornt[0]; 6081 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6082 orntNew[1] = ornt[1]; 6083 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6084 orntNew[2] = -2; 6085 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6086 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6087 #if 1 6088 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); 6089 for (p = 0; p < 3; ++p) { 6090 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); 6091 } 6092 #endif 6093 /* C triangle */ 6094 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6095 orntNew[0] = -2; 6096 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6097 orntNew[1] = ornt[1]; 6098 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6099 orntNew[2] = ornt[2]; 6100 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6101 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6102 #if 1 6103 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); 6104 for (p = 0; p < 3; ++p) { 6105 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); 6106 } 6107 #endif 6108 /* D triangle */ 6109 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6110 orntNew[0] = 0; 6111 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6112 orntNew[1] = 0; 6113 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6114 orntNew[2] = 0; 6115 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6116 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6117 #if 1 6118 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); 6119 for (p = 0; p < 3; ++p) { 6120 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); 6121 } 6122 #endif 6123 } 6124 /* 6125 2----3----3 6126 | | 6127 | B | 6128 | | 6129 0----4--- 1 6130 | | 6131 | A | 6132 | | 6133 0----2----1 6134 */ 6135 /* Hybrid cells have 4 faces */ 6136 for (c = cMax; c < cEnd; ++c) { 6137 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6138 const PetscInt *cone, *ornt; 6139 PetscInt coneNew[4], orntNew[4]; 6140 6141 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6142 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6143 /* A quad */ 6144 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6145 orntNew[0] = ornt[0]; 6146 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6147 orntNew[1] = ornt[1]; 6148 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6149 orntNew[2] = 0; 6150 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6151 orntNew[3] = 0; 6152 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6153 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6154 #if 1 6155 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); 6156 for (p = 0; p < 4; ++p) { 6157 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); 6158 } 6159 #endif 6160 /* B quad */ 6161 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6162 orntNew[0] = ornt[0]; 6163 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6164 orntNew[1] = ornt[1]; 6165 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6166 orntNew[2] = 0; 6167 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6168 orntNew[3] = 0; 6169 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6170 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6171 #if 1 6172 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); 6173 for (p = 0; p < 4; ++p) { 6174 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); 6175 } 6176 #endif 6177 } 6178 /* Interior split faces have 2 vertices and the same cells as the parent */ 6179 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6180 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6181 for (f = fStart; f < fMax; ++f) { 6182 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6183 6184 for (r = 0; r < 2; ++r) { 6185 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6186 const PetscInt *cone, *support; 6187 PetscInt coneNew[2], coneSize, c, supportSize, s; 6188 6189 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6190 coneNew[0] = vStartNew + (cone[0] - vStart); 6191 coneNew[1] = vStartNew + (cone[1] - vStart); 6192 coneNew[(r+1)%2] = newv; 6193 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6194 #if 1 6195 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6196 for (p = 0; p < 2; ++p) { 6197 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); 6198 } 6199 #endif 6200 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6201 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6202 for (s = 0; s < supportSize; ++s) { 6203 if (support[s] >= cMax) { 6204 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6205 } else { 6206 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6207 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6208 for (c = 0; c < coneSize; ++c) { 6209 if (cone[c] == f) break; 6210 } 6211 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6212 } 6213 } 6214 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6215 #if 1 6216 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6217 for (p = 0; p < supportSize; ++p) { 6218 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); 6219 } 6220 #endif 6221 } 6222 } 6223 /* Interior cell faces have 2 vertices and 2 cells */ 6224 for (c = cStart; c < cMax; ++c) { 6225 const PetscInt *cone; 6226 6227 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6228 for (r = 0; r < 3; ++r) { 6229 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6230 PetscInt coneNew[2]; 6231 PetscInt supportNew[2]; 6232 6233 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6234 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6235 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6236 #if 1 6237 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6238 for (p = 0; p < 2; ++p) { 6239 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); 6240 } 6241 #endif 6242 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6243 supportNew[1] = (c - cStart)*4 + 3; 6244 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6245 #if 1 6246 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6247 for (p = 0; p < 2; ++p) { 6248 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); 6249 } 6250 #endif 6251 } 6252 } 6253 /* Interior hybrid faces have 2 vertices and the same cells */ 6254 for (f = fMax; f < fEnd; ++f) { 6255 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6256 const PetscInt *cone; 6257 const PetscInt *support; 6258 PetscInt coneNew[2]; 6259 PetscInt supportNew[2]; 6260 PetscInt size, s, r; 6261 6262 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6263 coneNew[0] = vStartNew + (cone[0] - vStart); 6264 coneNew[1] = vStartNew + (cone[1] - vStart); 6265 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6266 #if 1 6267 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6268 for (p = 0; p < 2; ++p) { 6269 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); 6270 } 6271 #endif 6272 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6273 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6274 for (s = 0; s < size; ++s) { 6275 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6276 for (r = 0; r < 2; ++r) { 6277 if (cone[r+2] == f) break; 6278 } 6279 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6280 } 6281 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6282 #if 1 6283 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6284 for (p = 0; p < size; ++p) { 6285 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); 6286 } 6287 #endif 6288 } 6289 /* Cell hybrid faces have 2 vertices and 2 cells */ 6290 for (c = cMax; c < cEnd; ++c) { 6291 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6292 const PetscInt *cone; 6293 PetscInt coneNew[2]; 6294 PetscInt supportNew[2]; 6295 6296 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6297 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6298 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6299 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6300 #if 1 6301 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6302 for (p = 0; p < 2; ++p) { 6303 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); 6304 } 6305 #endif 6306 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6307 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6308 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6309 #if 1 6310 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6311 for (p = 0; p < 2; ++p) { 6312 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); 6313 } 6314 #endif 6315 } 6316 /* Old vertices have identical supports */ 6317 for (v = vStart; v < vEnd; ++v) { 6318 const PetscInt newp = vStartNew + (v - vStart); 6319 const PetscInt *support, *cone; 6320 PetscInt size, s; 6321 6322 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6323 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6324 for (s = 0; s < size; ++s) { 6325 if (support[s] >= fMax) { 6326 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6327 } else { 6328 PetscInt r = 0; 6329 6330 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6331 if (cone[1] == v) r = 1; 6332 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6333 } 6334 } 6335 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6336 #if 1 6337 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6338 for (p = 0; p < size; ++p) { 6339 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); 6340 } 6341 #endif 6342 } 6343 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6344 for (f = fStart; f < fMax; ++f) { 6345 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6346 const PetscInt *cone, *support; 6347 PetscInt size, newSize = 2, s; 6348 6349 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6350 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6351 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6352 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6353 for (s = 0; s < size; ++s) { 6354 PetscInt r = 0; 6355 6356 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6357 if (support[s] >= cMax) { 6358 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6359 6360 newSize += 1; 6361 } else { 6362 if (cone[1] == f) r = 1; 6363 else if (cone[2] == f) r = 2; 6364 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6365 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6366 6367 newSize += 2; 6368 } 6369 } 6370 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6371 #if 1 6372 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6373 for (p = 0; p < newSize; ++p) { 6374 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); 6375 } 6376 #endif 6377 } 6378 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6379 break; 6380 default: 6381 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6382 } 6383 PetscFunctionReturn(0); 6384 } 6385 6386 #undef __FUNCT__ 6387 #define __FUNCT__ "CellRefinerSetCoordinates" 6388 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6389 { 6390 PetscSection coordSection, coordSectionNew; 6391 Vec coordinates, coordinatesNew; 6392 PetscScalar *coords, *coordsNew; 6393 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6394 PetscErrorCode ierr; 6395 6396 PetscFunctionBegin; 6397 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6398 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6399 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6400 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6401 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6402 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6403 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6404 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6405 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6406 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6407 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6408 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6409 if (fMax < 0) fMax = fEnd; 6410 switch (refiner) { 6411 case 1: 6412 case 2: 6413 case 3: 6414 /* Simplicial and Hex 2D */ 6415 /* All vertices have the dim coordinates */ 6416 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6417 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6418 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6419 } 6420 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6421 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6422 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6423 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6424 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6425 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6426 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6427 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6428 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6429 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6430 /* Old vertices have the same coordinates */ 6431 for (v = vStart; v < vEnd; ++v) { 6432 const PetscInt newv = vStartNew + (v - vStart); 6433 PetscInt off, offnew, d; 6434 6435 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6436 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6437 for (d = 0; d < dim; ++d) { 6438 coordsNew[offnew+d] = coords[off+d]; 6439 } 6440 } 6441 /* Face vertices have the average of endpoint coordinates */ 6442 for (f = fStart; f < fMax; ++f) { 6443 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6444 const PetscInt *cone; 6445 PetscInt coneSize, offA, offB, offnew, d; 6446 6447 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6448 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6449 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6450 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6451 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6452 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6453 for (d = 0; d < dim; ++d) { 6454 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6455 } 6456 } 6457 /* Just Hex 2D */ 6458 if (refiner == 2) { 6459 /* Cell vertices have the average of corner coordinates */ 6460 for (c = cStart; c < cEnd; ++c) { 6461 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6462 PetscInt *cone = NULL; 6463 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6464 6465 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6466 for (p = 0; p < closureSize*2; p += 2) { 6467 const PetscInt point = cone[p]; 6468 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6469 } 6470 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6471 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6472 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6473 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6474 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6475 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6476 for (d = 0; d < dim; ++d) { 6477 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6478 } 6479 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6480 } 6481 } 6482 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6483 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6484 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6485 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6486 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 6487 break; 6488 default: 6489 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6490 } 6491 PetscFunctionReturn(0); 6492 } 6493 6494 #undef __FUNCT__ 6495 #define __FUNCT__ "DMPlexCreateProcessSF" 6496 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6497 { 6498 PetscInt numRoots, numLeaves, l; 6499 const PetscInt *localPoints; 6500 const PetscSFNode *remotePoints; 6501 PetscInt *localPointsNew; 6502 PetscSFNode *remotePointsNew; 6503 PetscInt *ranks, *ranksNew; 6504 PetscErrorCode ierr; 6505 6506 PetscFunctionBegin; 6507 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6508 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6509 for (l = 0; l < numLeaves; ++l) { 6510 ranks[l] = remotePoints[l].rank; 6511 } 6512 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6513 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6514 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6515 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6516 for (l = 0; l < numLeaves; ++l) { 6517 ranksNew[l] = ranks[l]; 6518 localPointsNew[l] = l; 6519 remotePointsNew[l].index = 0; 6520 remotePointsNew[l].rank = ranksNew[l]; 6521 } 6522 ierr = PetscFree(ranks);CHKERRQ(ierr); 6523 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6524 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 6525 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6526 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6527 PetscFunctionReturn(0); 6528 } 6529 6530 #undef __FUNCT__ 6531 #define __FUNCT__ "CellRefinerCreateSF" 6532 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6533 { 6534 PetscSF sf, sfNew, sfProcess; 6535 IS processRanks; 6536 MPI_Datatype depthType; 6537 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6538 const PetscInt *localPoints, *neighbors; 6539 const PetscSFNode *remotePoints; 6540 PetscInt *localPointsNew; 6541 PetscSFNode *remotePointsNew; 6542 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6543 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6544 PetscErrorCode ierr; 6545 6546 PetscFunctionBegin; 6547 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6548 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6549 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6550 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6551 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6552 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6553 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6554 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6555 switch (refiner) { 6556 case 3: 6557 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6558 cMax = PetscMin(cEnd, cMax); 6559 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6560 fMax = PetscMin(fEnd, fMax); 6561 } 6562 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6563 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6564 /* Caculate size of new SF */ 6565 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6566 if (numRoots < 0) PetscFunctionReturn(0); 6567 for (l = 0; l < numLeaves; ++l) { 6568 const PetscInt p = localPoints[l]; 6569 6570 switch (refiner) { 6571 case 1: 6572 /* Simplicial 2D */ 6573 if ((p >= vStart) && (p < vEnd)) { 6574 /* Old vertices stay the same */ 6575 ++numLeavesNew; 6576 } else if ((p >= fStart) && (p < fEnd)) { 6577 /* Old faces add new faces and vertex */ 6578 numLeavesNew += 1 + 2; 6579 } else if ((p >= cStart) && (p < cEnd)) { 6580 /* Old cells add new cells and interior faces */ 6581 numLeavesNew += 4 + 3; 6582 } 6583 break; 6584 case 2: 6585 /* Hex 2D */ 6586 if ((p >= vStart) && (p < vEnd)) { 6587 /* Old vertices stay the same */ 6588 ++numLeavesNew; 6589 } else if ((p >= fStart) && (p < fEnd)) { 6590 /* Old faces add new faces and vertex */ 6591 numLeavesNew += 1 + 2; 6592 } else if ((p >= cStart) && (p < cEnd)) { 6593 /* Old cells add new cells and interior faces */ 6594 numLeavesNew += 4 + 4; 6595 } 6596 break; 6597 default: 6598 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6599 } 6600 } 6601 /* Communicate depthSizes for each remote rank */ 6602 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6603 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6604 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6605 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); 6606 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6607 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6608 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6609 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6610 for (n = 0; n < numNeighbors; ++n) { 6611 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6612 } 6613 depthSizeOld[depth] = cMax; 6614 depthSizeOld[0] = vMax; 6615 depthSizeOld[depth-1] = fMax; 6616 depthSizeOld[1] = eMax; 6617 6618 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6619 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6620 6621 depthSizeOld[depth] = cEnd - cStart; 6622 depthSizeOld[0] = vEnd - vStart; 6623 depthSizeOld[depth-1] = fEnd - fStart; 6624 depthSizeOld[1] = eEnd - eStart; 6625 6626 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6627 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6628 for (n = 0; n < numNeighbors; ++n) { 6629 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6630 } 6631 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6632 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6633 /* Calculate new point SF */ 6634 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6635 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6636 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6637 for (l = 0, m = 0; l < numLeaves; ++l) { 6638 PetscInt p = localPoints[l]; 6639 PetscInt rp = remotePoints[l].index, n; 6640 PetscMPIInt rrank = remotePoints[l].rank; 6641 6642 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6643 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6644 switch (refiner) { 6645 case 1: 6646 /* Simplicial 2D */ 6647 if ((p >= vStart) && (p < vEnd)) { 6648 /* Old vertices stay the same */ 6649 localPointsNew[m] = vStartNew + (p - vStart); 6650 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6651 remotePointsNew[m].rank = rrank; 6652 ++m; 6653 } else if ((p >= fStart) && (p < fEnd)) { 6654 /* Old faces add new faces and vertex */ 6655 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6656 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6657 remotePointsNew[m].rank = rrank; 6658 ++m; 6659 for (r = 0; r < 2; ++r, ++m) { 6660 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6661 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6662 remotePointsNew[m].rank = rrank; 6663 } 6664 } else if ((p >= cStart) && (p < cEnd)) { 6665 /* Old cells add new cells and interior faces */ 6666 for (r = 0; r < 4; ++r, ++m) { 6667 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6668 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6669 remotePointsNew[m].rank = rrank; 6670 } 6671 for (r = 0; r < 3; ++r, ++m) { 6672 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6673 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6674 remotePointsNew[m].rank = rrank; 6675 } 6676 } 6677 break; 6678 case 2: 6679 /* Hex 2D */ 6680 if ((p >= vStart) && (p < vEnd)) { 6681 /* Old vertices stay the same */ 6682 localPointsNew[m] = vStartNew + (p - vStart); 6683 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6684 remotePointsNew[m].rank = rrank; 6685 ++m; 6686 } else if ((p >= fStart) && (p < fEnd)) { 6687 /* Old faces add new faces and vertex */ 6688 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6689 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6690 remotePointsNew[m].rank = rrank; 6691 ++m; 6692 for (r = 0; r < 2; ++r, ++m) { 6693 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6694 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6695 remotePointsNew[m].rank = rrank; 6696 } 6697 } else if ((p >= cStart) && (p < cEnd)) { 6698 /* Old cells add new cells and interior faces */ 6699 for (r = 0; r < 4; ++r, ++m) { 6700 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6701 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6702 remotePointsNew[m].rank = rrank; 6703 } 6704 for (r = 0; r < 4; ++r, ++m) { 6705 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6706 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6707 remotePointsNew[m].rank = rrank; 6708 } 6709 } 6710 break; 6711 case 3: 6712 /* Hybrid simplicial 2D */ 6713 if ((p >= vStart) && (p < vEnd)) { 6714 /* Old vertices stay the same */ 6715 localPointsNew[m] = vStartNew + (p - vStart); 6716 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6717 remotePointsNew[m].rank = rrank; 6718 ++m; 6719 } else if ((p >= fStart) && (p < fMax)) { 6720 /* Old interior faces add new faces and vertex */ 6721 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6722 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6723 remotePointsNew[m].rank = rrank; 6724 ++m; 6725 for (r = 0; r < 2; ++r, ++m) { 6726 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6727 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6728 remotePointsNew[m].rank = rrank; 6729 } 6730 } else if ((p >= fMax) && (p < fEnd)) { 6731 /* Old hybrid faces stay the same */ 6732 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6733 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6734 remotePointsNew[m].rank = rrank; 6735 ++m; 6736 } else if ((p >= cStart) && (p < cMax)) { 6737 /* Old interior cells add new cells and interior faces */ 6738 for (r = 0; r < 4; ++r, ++m) { 6739 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6740 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6741 remotePointsNew[m].rank = rrank; 6742 } 6743 for (r = 0; r < 3; ++r, ++m) { 6744 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6745 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6746 remotePointsNew[m].rank = rrank; 6747 } 6748 } else if ((p >= cStart) && (p < cMax)) { 6749 /* Old hybrid cells add new cells and hybrid face */ 6750 for (r = 0; r < 2; ++r, ++m) { 6751 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6752 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6753 remotePointsNew[m].rank = rrank; 6754 } 6755 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6756 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]); 6757 remotePointsNew[m].rank = rrank; 6758 ++m; 6759 } 6760 break; 6761 default: 6762 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6763 } 6764 } 6765 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6766 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6767 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6768 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6769 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6770 PetscFunctionReturn(0); 6771 } 6772 6773 #undef __FUNCT__ 6774 #define __FUNCT__ "CellRefinerCreateLabels" 6775 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6776 { 6777 PetscInt numLabels, l; 6778 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6779 PetscErrorCode ierr; 6780 6781 PetscFunctionBegin; 6782 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6783 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6784 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6785 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6786 6787 cStartNew = 0; 6788 vStartNew = depthSize[2]; 6789 fStartNew = depthSize[2] + depthSize[0]; 6790 6791 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6792 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6793 switch (refiner) { 6794 case 3: 6795 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6796 cMax = PetscMin(cEnd, cMax); 6797 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6798 fMax = PetscMin(fEnd, fMax); 6799 } 6800 for (l = 0; l < numLabels; ++l) { 6801 DMLabel label, labelNew; 6802 const char *lname; 6803 PetscBool isDepth; 6804 IS valueIS; 6805 const PetscInt *values; 6806 PetscInt numValues, val; 6807 6808 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6809 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6810 if (isDepth) continue; 6811 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6812 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6813 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6814 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6815 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6816 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6817 for (val = 0; val < numValues; ++val) { 6818 IS pointIS; 6819 const PetscInt *points; 6820 PetscInt numPoints, n; 6821 6822 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6823 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6824 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6825 for (n = 0; n < numPoints; ++n) { 6826 const PetscInt p = points[n]; 6827 switch (refiner) { 6828 case 1: 6829 /* Simplicial 2D */ 6830 if ((p >= vStart) && (p < vEnd)) { 6831 /* Old vertices stay the same */ 6832 newp = vStartNew + (p - vStart); 6833 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6834 } else if ((p >= fStart) && (p < fEnd)) { 6835 /* Old faces add new faces and vertex */ 6836 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6837 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6838 for (r = 0; r < 2; ++r) { 6839 newp = fStartNew + (p - fStart)*2 + r; 6840 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6841 } 6842 } else if ((p >= cStart) && (p < cEnd)) { 6843 /* Old cells add new cells and interior faces */ 6844 for (r = 0; r < 4; ++r) { 6845 newp = cStartNew + (p - cStart)*4 + r; 6846 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6847 } 6848 for (r = 0; r < 3; ++r) { 6849 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6850 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6851 } 6852 } 6853 break; 6854 case 2: 6855 /* Hex 2D */ 6856 if ((p >= vStart) && (p < vEnd)) { 6857 /* Old vertices stay the same */ 6858 newp = vStartNew + (p - vStart); 6859 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6860 } else if ((p >= fStart) && (p < fEnd)) { 6861 /* Old faces add new faces and vertex */ 6862 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6863 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6864 for (r = 0; r < 2; ++r) { 6865 newp = fStartNew + (p - fStart)*2 + r; 6866 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6867 } 6868 } else if ((p >= cStart) && (p < cEnd)) { 6869 /* Old cells add new cells and interior faces and vertex */ 6870 for (r = 0; r < 4; ++r) { 6871 newp = cStartNew + (p - cStart)*4 + r; 6872 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6873 } 6874 for (r = 0; r < 4; ++r) { 6875 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6876 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6877 } 6878 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6879 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6880 } 6881 break; 6882 case 3: 6883 /* Hybrid simplicial 2D */ 6884 if ((p >= vStart) && (p < vEnd)) { 6885 /* Old vertices stay the same */ 6886 newp = vStartNew + (p - vStart); 6887 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6888 } else if ((p >= fStart) && (p < fMax)) { 6889 /* Old interior faces add new faces and vertex */ 6890 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6891 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6892 for (r = 0; r < 2; ++r) { 6893 newp = fStartNew + (p - fStart)*2 + r; 6894 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6895 } 6896 } else if ((p >= fMax) && (p < fEnd)) { 6897 /* Old hybrid faces stay the same */ 6898 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 6899 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6900 } else if ((p >= cStart) && (p < cMax)) { 6901 /* Old interior cells add new cells and interior faces */ 6902 for (r = 0; r < 4; ++r) { 6903 newp = cStartNew + (p - cStart)*4 + r; 6904 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6905 } 6906 for (r = 0; r < 3; ++r) { 6907 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6908 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6909 } 6910 } else if ((p >= cMax) && (p < cEnd)) { 6911 /* Old hybrid cells add new cells and hybrid face */ 6912 for (r = 0; r < 2; ++r) { 6913 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 6914 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6915 } 6916 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6917 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6918 } 6919 break; 6920 default: 6921 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6922 } 6923 } 6924 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6925 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6926 } 6927 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6928 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6929 if (0) { 6930 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6931 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6932 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6933 } 6934 } 6935 PetscFunctionReturn(0); 6936 } 6937 6938 #undef __FUNCT__ 6939 #define __FUNCT__ "DMPlexRefine_Uniform" 6940 /* This will only work for interpolated meshes */ 6941 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6942 { 6943 DM rdm; 6944 PetscInt *depthSize; 6945 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6946 PetscErrorCode ierr; 6947 6948 PetscFunctionBegin; 6949 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 6950 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6951 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6952 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6953 /* Calculate number of new points of each depth */ 6954 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6955 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6956 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6957 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6958 /* Step 1: Set chart */ 6959 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 6960 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6961 /* Step 2: Set cone/support sizes */ 6962 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6963 /* Step 3: Setup refined DM */ 6964 ierr = DMSetUp(rdm);CHKERRQ(ierr); 6965 /* Step 4: Set cones and supports */ 6966 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6967 /* Step 5: Stratify */ 6968 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6969 /* Step 6: Set coordinates for vertices */ 6970 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6971 /* Step 7: Create pointSF */ 6972 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6973 /* Step 8: Create labels */ 6974 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6975 ierr = PetscFree(depthSize);CHKERRQ(ierr); 6976 6977 *dmRefined = rdm; 6978 PetscFunctionReturn(0); 6979 } 6980 6981 #undef __FUNCT__ 6982 #define __FUNCT__ "DMPlexSetRefinementUniform" 6983 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 6984 { 6985 DM_Plex *mesh = (DM_Plex*) dm->data; 6986 6987 PetscFunctionBegin; 6988 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6989 mesh->refinementUniform = refinementUniform; 6990 PetscFunctionReturn(0); 6991 } 6992 6993 #undef __FUNCT__ 6994 #define __FUNCT__ "DMPlexGetRefinementUniform" 6995 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 6996 { 6997 DM_Plex *mesh = (DM_Plex*) dm->data; 6998 6999 PetscFunctionBegin; 7000 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7001 PetscValidPointer(refinementUniform, 2); 7002 *refinementUniform = mesh->refinementUniform; 7003 PetscFunctionReturn(0); 7004 } 7005 7006 #undef __FUNCT__ 7007 #define __FUNCT__ "DMPlexSetRefinementLimit" 7008 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7009 { 7010 DM_Plex *mesh = (DM_Plex*) dm->data; 7011 7012 PetscFunctionBegin; 7013 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7014 mesh->refinementLimit = refinementLimit; 7015 PetscFunctionReturn(0); 7016 } 7017 7018 #undef __FUNCT__ 7019 #define __FUNCT__ "DMPlexGetRefinementLimit" 7020 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7021 { 7022 DM_Plex *mesh = (DM_Plex*) dm->data; 7023 7024 PetscFunctionBegin; 7025 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7026 PetscValidPointer(refinementLimit, 2); 7027 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7028 *refinementLimit = mesh->refinementLimit; 7029 PetscFunctionReturn(0); 7030 } 7031 7032 #undef __FUNCT__ 7033 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7034 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7035 { 7036 PetscInt dim, cStart, coneSize, cMax; 7037 PetscErrorCode ierr; 7038 7039 PetscFunctionBegin; 7040 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7041 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7042 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7043 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7044 switch (dim) { 7045 case 2: 7046 switch (coneSize) { 7047 case 3: 7048 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7049 else *cellRefiner = 1; /* Triangular */ 7050 break; 7051 case 4: 7052 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7053 else *cellRefiner = 2; /* Quadrilateral */ 7054 break; 7055 default: 7056 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7057 } 7058 break; 7059 default: 7060 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7061 } 7062 PetscFunctionReturn(0); 7063 } 7064 7065 #undef __FUNCT__ 7066 #define __FUNCT__ "DMRefine_Plex" 7067 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7068 { 7069 PetscReal refinementLimit; 7070 PetscInt dim, cStart, cEnd; 7071 char genname[1024], *name = NULL; 7072 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7073 PetscErrorCode ierr; 7074 7075 PetscFunctionBegin; 7076 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7077 if (isUniform) { 7078 CellRefiner cellRefiner; 7079 7080 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7081 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7082 PetscFunctionReturn(0); 7083 } 7084 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7085 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7086 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7087 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7088 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7089 if (flg) name = genname; 7090 if (name) { 7091 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7092 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7093 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7094 } 7095 switch (dim) { 7096 case 2: 7097 if (!name || isTriangle) { 7098 #if defined(PETSC_HAVE_TRIANGLE) 7099 double *maxVolumes; 7100 PetscInt c; 7101 7102 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7103 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7104 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7105 #else 7106 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7107 #endif 7108 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7109 break; 7110 case 3: 7111 if (!name || isCTetgen) { 7112 #if defined(PETSC_HAVE_CTETGEN) 7113 PetscReal *maxVolumes; 7114 PetscInt c; 7115 7116 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7117 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7118 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7119 #else 7120 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7121 #endif 7122 } else if (isTetgen) { 7123 #if defined(PETSC_HAVE_TETGEN) 7124 double *maxVolumes; 7125 PetscInt c; 7126 7127 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7128 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7129 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7130 #else 7131 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7132 #endif 7133 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7134 break; 7135 default: 7136 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7137 } 7138 PetscFunctionReturn(0); 7139 } 7140 7141 #undef __FUNCT__ 7142 #define __FUNCT__ "DMPlexGetDepth" 7143 /*@ 7144 DMPlexGetDepth - get the number of strata 7145 7146 Not Collective 7147 7148 Input Parameters: 7149 . dm - The DMPlex object 7150 7151 Output Parameters: 7152 . depth - number of strata 7153 7154 Level: developer 7155 7156 Notes: 7157 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7158 7159 .keywords: mesh, points 7160 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7161 @*/ 7162 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7163 { 7164 PetscInt d; 7165 PetscErrorCode ierr; 7166 7167 PetscFunctionBegin; 7168 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7169 PetscValidPointer(depth, 2); 7170 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7171 *depth = d-1; 7172 PetscFunctionReturn(0); 7173 } 7174 7175 #undef __FUNCT__ 7176 #define __FUNCT__ "DMPlexGetDepthStratum" 7177 /*@ 7178 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7179 7180 Not Collective 7181 7182 Input Parameters: 7183 + dm - The DMPlex object 7184 - stratumValue - The requested depth 7185 7186 Output Parameters: 7187 + start - The first point at this depth 7188 - end - One beyond the last point at this depth 7189 7190 Level: developer 7191 7192 .keywords: mesh, points 7193 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7194 @*/ 7195 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7196 { 7197 DM_Plex *mesh = (DM_Plex*) dm->data; 7198 DMLabel next = mesh->labels; 7199 PetscBool flg = PETSC_FALSE; 7200 PetscInt depth; 7201 PetscErrorCode ierr; 7202 7203 PetscFunctionBegin; 7204 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7205 if (stratumValue < 0) { 7206 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7207 PetscFunctionReturn(0); 7208 } else { 7209 PetscInt pStart, pEnd; 7210 7211 if (start) *start = 0; 7212 if (end) *end = 0; 7213 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7214 if (pStart == pEnd) PetscFunctionReturn(0); 7215 } 7216 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7217 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7218 /* We should have a generic GetLabel() and a Label class */ 7219 while (next) { 7220 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7221 if (flg) break; 7222 next = next->next; 7223 } 7224 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7225 depth = stratumValue; 7226 if ((depth < 0) || (depth >= next->numStrata)) { 7227 if (start) *start = 0; 7228 if (end) *end = 0; 7229 } else { 7230 if (start) *start = next->points[next->stratumOffsets[depth]]; 7231 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7232 } 7233 PetscFunctionReturn(0); 7234 } 7235 7236 #undef __FUNCT__ 7237 #define __FUNCT__ "DMPlexGetHeightStratum" 7238 /*@ 7239 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7240 7241 Not Collective 7242 7243 Input Parameters: 7244 + dm - The DMPlex object 7245 - stratumValue - The requested height 7246 7247 Output Parameters: 7248 + start - The first point at this height 7249 - end - One beyond the last point at this height 7250 7251 Level: developer 7252 7253 .keywords: mesh, points 7254 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7255 @*/ 7256 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7257 { 7258 DM_Plex *mesh = (DM_Plex*) dm->data; 7259 DMLabel next = mesh->labels; 7260 PetscBool flg = PETSC_FALSE; 7261 PetscInt depth; 7262 PetscErrorCode ierr; 7263 7264 PetscFunctionBegin; 7265 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7266 if (stratumValue < 0) { 7267 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7268 } else { 7269 PetscInt pStart, pEnd; 7270 7271 if (start) *start = 0; 7272 if (end) *end = 0; 7273 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7274 if (pStart == pEnd) PetscFunctionReturn(0); 7275 } 7276 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7277 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7278 /* We should have a generic GetLabel() and a Label class */ 7279 while (next) { 7280 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7281 if (flg) break; 7282 next = next->next; 7283 } 7284 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7285 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7286 if ((depth < 0) || (depth >= next->numStrata)) { 7287 if (start) *start = 0; 7288 if (end) *end = 0; 7289 } else { 7290 if (start) *start = next->points[next->stratumOffsets[depth]]; 7291 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7292 } 7293 PetscFunctionReturn(0); 7294 } 7295 7296 #undef __FUNCT__ 7297 #define __FUNCT__ "DMPlexCreateSectionInitial" 7298 /* Set the number of dof on each point and separate by fields */ 7299 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7300 { 7301 PetscInt *numDofTot; 7302 PetscInt pStart = 0, pEnd = 0; 7303 PetscInt p, d, f; 7304 PetscErrorCode ierr; 7305 7306 PetscFunctionBegin; 7307 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7308 for (d = 0; d <= dim; ++d) { 7309 numDofTot[d] = 0; 7310 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7311 } 7312 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7313 if (numFields > 0) { 7314 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7315 if (numComp) { 7316 for (f = 0; f < numFields; ++f) { 7317 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7318 } 7319 } 7320 } 7321 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7322 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7323 for (d = 0; d <= dim; ++d) { 7324 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7325 for (p = pStart; p < pEnd; ++p) { 7326 for (f = 0; f < numFields; ++f) { 7327 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7328 } 7329 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7330 } 7331 } 7332 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7333 PetscFunctionReturn(0); 7334 } 7335 7336 #undef __FUNCT__ 7337 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7338 /* Set the number of dof on each point and separate by fields 7339 If constDof is PETSC_DETERMINE, constrain every dof on the point 7340 */ 7341 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7342 { 7343 PetscInt numFields; 7344 PetscInt bc; 7345 PetscErrorCode ierr; 7346 7347 PetscFunctionBegin; 7348 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7349 for (bc = 0; bc < numBC; ++bc) { 7350 PetscInt field = 0; 7351 const PetscInt *idx; 7352 PetscInt n, i; 7353 7354 if (numFields) field = bcField[bc]; 7355 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7356 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7357 for (i = 0; i < n; ++i) { 7358 const PetscInt p = idx[i]; 7359 PetscInt numConst = constDof; 7360 7361 /* Constrain every dof on the point */ 7362 if (numConst < 0) { 7363 if (numFields) { 7364 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7365 } else { 7366 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7367 } 7368 } 7369 if (numFields) { 7370 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7371 } 7372 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7373 } 7374 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7375 } 7376 PetscFunctionReturn(0); 7377 } 7378 7379 #undef __FUNCT__ 7380 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7381 /* Set the constrained indices on each point and separate by fields */ 7382 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7383 { 7384 PetscInt *maxConstraints; 7385 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7386 PetscErrorCode ierr; 7387 7388 PetscFunctionBegin; 7389 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7390 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7391 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7392 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7393 for (p = pStart; p < pEnd; ++p) { 7394 PetscInt cdof; 7395 7396 if (numFields) { 7397 for (f = 0; f < numFields; ++f) { 7398 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7399 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7400 } 7401 } else { 7402 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7403 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7404 } 7405 } 7406 for (f = 0; f < numFields; ++f) { 7407 maxConstraints[numFields] += maxConstraints[f]; 7408 } 7409 if (maxConstraints[numFields]) { 7410 PetscInt *indices; 7411 7412 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7413 for (p = pStart; p < pEnd; ++p) { 7414 PetscInt cdof, d; 7415 7416 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7417 if (cdof) { 7418 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7419 if (numFields) { 7420 PetscInt numConst = 0, foff = 0; 7421 7422 for (f = 0; f < numFields; ++f) { 7423 PetscInt cfdof, fdof; 7424 7425 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7426 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7427 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7428 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7429 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7430 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7431 numConst += cfdof; 7432 foff += fdof; 7433 } 7434 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7435 } else { 7436 for (d = 0; d < cdof; ++d) indices[d] = d; 7437 } 7438 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7439 } 7440 } 7441 ierr = PetscFree(indices);CHKERRQ(ierr); 7442 } 7443 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7444 PetscFunctionReturn(0); 7445 } 7446 7447 #undef __FUNCT__ 7448 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7449 /* Set the constrained field indices on each point */ 7450 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7451 { 7452 const PetscInt *points, *indices; 7453 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7454 PetscErrorCode ierr; 7455 7456 PetscFunctionBegin; 7457 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7458 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7459 7460 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7461 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7462 if (!constraintIndices) { 7463 PetscInt *idx, i; 7464 7465 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7466 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7467 for (i = 0; i < maxDof; ++i) idx[i] = i; 7468 for (p = 0; p < numPoints; ++p) { 7469 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7470 } 7471 ierr = PetscFree(idx);CHKERRQ(ierr); 7472 } else { 7473 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7474 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7475 for (p = 0; p < numPoints; ++p) { 7476 PetscInt fcdof; 7477 7478 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7479 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); 7480 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7481 } 7482 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7483 } 7484 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7485 PetscFunctionReturn(0); 7486 } 7487 7488 #undef __FUNCT__ 7489 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7490 /* Set the constrained indices on each point and separate by fields */ 7491 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7492 { 7493 PetscInt *indices; 7494 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7495 PetscErrorCode ierr; 7496 7497 PetscFunctionBegin; 7498 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7499 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7500 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7501 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7502 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7503 for (p = pStart; p < pEnd; ++p) { 7504 PetscInt cdof, d; 7505 7506 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7507 if (cdof) { 7508 PetscInt numConst = 0, foff = 0; 7509 7510 for (f = 0; f < numFields; ++f) { 7511 const PetscInt *fcind; 7512 PetscInt fdof, fcdof; 7513 7514 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7515 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7516 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7517 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7518 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7519 foff += fdof; 7520 numConst += fcdof; 7521 } 7522 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7523 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7524 } 7525 } 7526 ierr = PetscFree(indices);CHKERRQ(ierr); 7527 PetscFunctionReturn(0); 7528 } 7529 7530 #undef __FUNCT__ 7531 #define __FUNCT__ "DMPlexCreateSection" 7532 /*@C 7533 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7534 7535 Not Collective 7536 7537 Input Parameters: 7538 + dm - The DMPlex object 7539 . dim - The spatial dimension of the problem 7540 . numFields - The number of fields in the problem 7541 . numComp - An array of size numFields that holds the number of components for each field 7542 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7543 . numBC - The number of boundary conditions 7544 . bcField - An array of size numBC giving the field number for each boundry condition 7545 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7546 7547 Output Parameter: 7548 . section - The PetscSection object 7549 7550 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 7551 nubmer of dof for field 0 on each edge. 7552 7553 Level: developer 7554 7555 .keywords: mesh, elements 7556 .seealso: DMPlexCreate(), PetscSectionCreate() 7557 @*/ 7558 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 7559 { 7560 PetscErrorCode ierr; 7561 7562 PetscFunctionBegin; 7563 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7564 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7565 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7566 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7567 { 7568 PetscBool view = PETSC_FALSE; 7569 7570 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7571 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7572 } 7573 PetscFunctionReturn(0); 7574 } 7575 7576 #undef __FUNCT__ 7577 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7578 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7579 { 7580 PetscSection section; 7581 PetscErrorCode ierr; 7582 7583 PetscFunctionBegin; 7584 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7585 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7586 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7587 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7588 PetscFunctionReturn(0); 7589 } 7590 7591 #undef __FUNCT__ 7592 #define __FUNCT__ "DMPlexGetCoordinateSection" 7593 /*@ 7594 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7595 7596 Not Collective 7597 7598 Input Parameter: 7599 . dm - The DMPlex object 7600 7601 Output Parameter: 7602 . section - The PetscSection object 7603 7604 Level: intermediate 7605 7606 .keywords: mesh, coordinates 7607 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7608 @*/ 7609 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7610 { 7611 DM cdm; 7612 PetscErrorCode ierr; 7613 7614 PetscFunctionBegin; 7615 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7616 PetscValidPointer(section, 2); 7617 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7618 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7619 PetscFunctionReturn(0); 7620 } 7621 7622 #undef __FUNCT__ 7623 #define __FUNCT__ "DMPlexSetCoordinateSection" 7624 /*@ 7625 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7626 7627 Not Collective 7628 7629 Input Parameters: 7630 + dm - The DMPlex object 7631 - section - The PetscSection object 7632 7633 Level: intermediate 7634 7635 .keywords: mesh, coordinates 7636 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7637 @*/ 7638 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7639 { 7640 DM cdm; 7641 PetscErrorCode ierr; 7642 7643 PetscFunctionBegin; 7644 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7645 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 7646 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7647 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7648 PetscFunctionReturn(0); 7649 } 7650 7651 #undef __FUNCT__ 7652 #define __FUNCT__ "DMPlexGetConeSection" 7653 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7654 { 7655 DM_Plex *mesh = (DM_Plex*) dm->data; 7656 7657 PetscFunctionBegin; 7658 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7659 if (section) *section = mesh->coneSection; 7660 PetscFunctionReturn(0); 7661 } 7662 7663 #undef __FUNCT__ 7664 #define __FUNCT__ "DMPlexGetCones" 7665 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 7666 { 7667 DM_Plex *mesh = (DM_Plex*) dm->data; 7668 7669 PetscFunctionBegin; 7670 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7671 if (cones) *cones = mesh->cones; 7672 PetscFunctionReturn(0); 7673 } 7674 7675 #undef __FUNCT__ 7676 #define __FUNCT__ "DMPlexGetConeOrientations" 7677 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 7678 { 7679 DM_Plex *mesh = (DM_Plex*) dm->data; 7680 7681 PetscFunctionBegin; 7682 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7683 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7684 PetscFunctionReturn(0); 7685 } 7686 7687 #undef __FUNCT__ 7688 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7689 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7690 { 7691 const PetscInt embedDim = 2; 7692 PetscReal x = PetscRealPart(point[0]); 7693 PetscReal y = PetscRealPart(point[1]); 7694 PetscReal v0[2], J[4], invJ[4], detJ; 7695 PetscReal xi, eta; 7696 PetscErrorCode ierr; 7697 7698 PetscFunctionBegin; 7699 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7700 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7701 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7702 7703 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 7704 else *cell = -1; 7705 PetscFunctionReturn(0); 7706 } 7707 7708 #undef __FUNCT__ 7709 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7710 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7711 { 7712 PetscSection coordSection; 7713 Vec coordsLocal; 7714 const PetscScalar *coords; 7715 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7716 PetscReal x = PetscRealPart(point[0]); 7717 PetscReal y = PetscRealPart(point[1]); 7718 PetscInt crossings = 0, f; 7719 PetscErrorCode ierr; 7720 7721 PetscFunctionBegin; 7722 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7723 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7724 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7725 for (f = 0; f < 4; ++f) { 7726 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7727 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7728 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7729 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7730 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7731 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7732 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7733 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7734 if ((cond1 || cond2) && above) ++crossings; 7735 } 7736 if (crossings % 2) *cell = c; 7737 else *cell = -1; 7738 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7739 PetscFunctionReturn(0); 7740 } 7741 7742 #undef __FUNCT__ 7743 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7744 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7745 { 7746 const PetscInt embedDim = 3; 7747 PetscReal v0[3], J[9], invJ[9], detJ; 7748 PetscReal x = PetscRealPart(point[0]); 7749 PetscReal y = PetscRealPart(point[1]); 7750 PetscReal z = PetscRealPart(point[2]); 7751 PetscReal xi, eta, zeta; 7752 PetscErrorCode ierr; 7753 7754 PetscFunctionBegin; 7755 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7756 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7757 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7758 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7759 7760 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 7761 else *cell = -1; 7762 PetscFunctionReturn(0); 7763 } 7764 7765 #undef __FUNCT__ 7766 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7767 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7768 { 7769 PetscSection coordSection; 7770 Vec coordsLocal; 7771 const PetscScalar *coords; 7772 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7773 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7774 PetscBool found = PETSC_TRUE; 7775 PetscInt f; 7776 PetscErrorCode ierr; 7777 7778 PetscFunctionBegin; 7779 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7780 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7781 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7782 for (f = 0; f < 6; ++f) { 7783 /* Check the point is under plane */ 7784 /* Get face normal */ 7785 PetscReal v_i[3]; 7786 PetscReal v_j[3]; 7787 PetscReal normal[3]; 7788 PetscReal pp[3]; 7789 PetscReal dot; 7790 7791 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 7792 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 7793 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 7794 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 7795 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 7796 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 7797 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 7798 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 7799 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 7800 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 7801 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 7802 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 7803 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7804 7805 /* Check that projected point is in face (2D location problem) */ 7806 if (dot < 0.0) { 7807 found = PETSC_FALSE; 7808 break; 7809 } 7810 } 7811 if (found) *cell = c; 7812 else *cell = -1; 7813 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7814 PetscFunctionReturn(0); 7815 } 7816 7817 #undef __FUNCT__ 7818 #define __FUNCT__ "DMLocatePoints_Plex" 7819 /* 7820 Need to implement using the guess 7821 */ 7822 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7823 { 7824 PetscInt cell = -1 /*, guess = -1*/; 7825 PetscInt bs, numPoints, p; 7826 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7827 PetscInt *cells; 7828 PetscScalar *a; 7829 PetscErrorCode ierr; 7830 7831 PetscFunctionBegin; 7832 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7833 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7834 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7835 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7836 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7837 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7838 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7839 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); 7840 numPoints /= bs; 7841 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7842 for (p = 0; p < numPoints; ++p) { 7843 const PetscScalar *point = &a[p*bs]; 7844 7845 switch (dim) { 7846 case 2: 7847 for (c = cStart; c < cEnd; ++c) { 7848 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7849 switch (coneSize) { 7850 case 3: 7851 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7852 break; 7853 case 4: 7854 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7855 break; 7856 default: 7857 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7858 } 7859 if (cell >= 0) break; 7860 } 7861 break; 7862 case 3: 7863 for (c = cStart; c < cEnd; ++c) { 7864 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7865 switch (coneSize) { 7866 case 4: 7867 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7868 break; 7869 case 8: 7870 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7871 break; 7872 default: 7873 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7874 } 7875 if (cell >= 0) break; 7876 } 7877 break; 7878 default: 7879 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 7880 } 7881 cells[p] = cell; 7882 } 7883 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 7884 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 7885 PetscFunctionReturn(0); 7886 } 7887 7888 /******************************** FEM Support **********************************/ 7889 7890 #undef __FUNCT__ 7891 #define __FUNCT__ "DMPlexVecGetClosure" 7892 /*@C 7893 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 7894 7895 Not collective 7896 7897 Input Parameters: 7898 + dm - The DM 7899 . section - The section describing the layout in v, or NULL to use the default section 7900 . v - The local vector 7901 - point - The sieve point in the DM 7902 7903 Output Parameters: 7904 + csize - The number of values in the closure, or NULL 7905 - values - The array of values, which is a borrowed array and should not be freed 7906 7907 Level: intermediate 7908 7909 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7910 @*/ 7911 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 7912 { 7913 PetscScalar *array, *vArray; 7914 PetscInt *points = NULL; 7915 PetscInt offsets[32]; 7916 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 7917 PetscErrorCode ierr; 7918 7919 PetscFunctionBegin; 7920 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7921 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7922 if (!section) { 7923 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7924 } 7925 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7926 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7927 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7928 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7929 /* Compress out points not in the section */ 7930 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7931 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7932 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7933 points[q*2] = points[p]; 7934 points[q*2+1] = points[p+1]; 7935 ++q; 7936 } 7937 } 7938 numPoints = q; 7939 for (p = 0, size = 0; p < numPoints*2; p += 2) { 7940 PetscInt dof, fdof; 7941 7942 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7943 for (f = 0; f < numFields; ++f) { 7944 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7945 offsets[f+1] += fdof; 7946 } 7947 size += dof; 7948 } 7949 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7950 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 7951 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 7952 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 7953 for (p = 0; p < numPoints*2; p += 2) { 7954 PetscInt o = points[p+1]; 7955 PetscInt dof, off, d; 7956 PetscScalar *varr; 7957 7958 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7959 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 7960 varr = &vArray[off]; 7961 if (numFields) { 7962 PetscInt fdof, foff, fcomp, f, c; 7963 7964 for (f = 0, foff = 0; f < numFields; ++f) { 7965 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7966 if (o >= 0) { 7967 for (d = 0; d < fdof; ++d, ++offsets[f]) { 7968 array[offsets[f]] = varr[foff+d]; 7969 } 7970 } else { 7971 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7972 for (d = fdof/fcomp-1; d >= 0; --d) { 7973 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 7974 array[offsets[f]] = varr[foff+d*fcomp+c]; 7975 } 7976 } 7977 } 7978 foff += fdof; 7979 } 7980 } else { 7981 if (o >= 0) { 7982 for (d = 0; d < dof; ++d, ++offsets[0]) { 7983 array[offsets[0]] = varr[d]; 7984 } 7985 } else { 7986 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 7987 array[offsets[0]] = varr[d]; 7988 } 7989 } 7990 } 7991 } 7992 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7993 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 7994 if (csize) *csize = size; 7995 *values = array; 7996 PetscFunctionReturn(0); 7997 } 7998 7999 #undef __FUNCT__ 8000 #define __FUNCT__ "DMPlexVecRestoreClosure" 8001 /*@C 8002 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8003 8004 Not collective 8005 8006 Input Parameters: 8007 + dm - The DM 8008 . section - The section describing the layout in v, or NULL to use the default section 8009 . v - The local vector 8010 . point - The sieve point in the DM 8011 . csize - The number of values in the closure, or NULL 8012 - values - The array of values, which is a borrowed array and should not be freed 8013 8014 Level: intermediate 8015 8016 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8017 @*/ 8018 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8019 { 8020 PetscInt size = 0; 8021 PetscErrorCode ierr; 8022 8023 PetscFunctionBegin; 8024 /* Should work without recalculating size */ 8025 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8026 PetscFunctionReturn(0); 8027 } 8028 8029 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8030 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8031 8032 #undef __FUNCT__ 8033 #define __FUNCT__ "updatePoint_private" 8034 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8035 { 8036 PetscInt cdof; /* The number of constraints on this point */ 8037 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8038 PetscScalar *a; 8039 PetscInt off, cind = 0, k; 8040 PetscErrorCode ierr; 8041 8042 PetscFunctionBegin; 8043 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8044 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8045 a = &array[off]; 8046 if (!cdof || setBC) { 8047 if (orientation >= 0) { 8048 for (k = 0; k < dof; ++k) { 8049 fuse(&a[k], values[k]); 8050 } 8051 } else { 8052 for (k = 0; k < dof; ++k) { 8053 fuse(&a[k], values[dof-k-1]); 8054 } 8055 } 8056 } else { 8057 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8058 if (orientation >= 0) { 8059 for (k = 0; k < dof; ++k) { 8060 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8061 fuse(&a[k], values[k]); 8062 } 8063 } else { 8064 for (k = 0; k < dof; ++k) { 8065 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8066 fuse(&a[k], values[dof-k-1]); 8067 } 8068 } 8069 } 8070 PetscFunctionReturn(0); 8071 } 8072 8073 #undef __FUNCT__ 8074 #define __FUNCT__ "updatePointFields_private" 8075 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8076 { 8077 PetscScalar *a; 8078 PetscInt numFields, off, foff, f; 8079 PetscErrorCode ierr; 8080 8081 PetscFunctionBegin; 8082 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8083 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8084 a = &array[off]; 8085 for (f = 0, foff = 0; f < numFields; ++f) { 8086 PetscInt fdof, fcomp, fcdof; 8087 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8088 PetscInt cind = 0, k, c; 8089 8090 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8091 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8092 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8093 if (!fcdof || setBC) { 8094 if (orientation >= 0) { 8095 for (k = 0; k < fdof; ++k) { 8096 fuse(&a[foff+k], values[foffs[f]+k]); 8097 } 8098 } else { 8099 for (k = fdof/fcomp-1; k >= 0; --k) { 8100 for (c = 0; c < fcomp; ++c) { 8101 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8102 } 8103 } 8104 } 8105 } else { 8106 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8107 if (orientation >= 0) { 8108 for (k = 0; k < fdof; ++k) { 8109 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8110 fuse(&a[foff+k], values[foffs[f]+k]); 8111 } 8112 } else { 8113 for (k = fdof/fcomp-1; k >= 0; --k) { 8114 for (c = 0; c < fcomp; ++c) { 8115 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8116 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8117 } 8118 } 8119 } 8120 } 8121 foff += fdof; 8122 foffs[f] += fdof; 8123 } 8124 PetscFunctionReturn(0); 8125 } 8126 8127 #undef __FUNCT__ 8128 #define __FUNCT__ "DMPlexVecSetClosure" 8129 /*@C 8130 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8131 8132 Not collective 8133 8134 Input Parameters: 8135 + dm - The DM 8136 . section - The section describing the layout in v, or NULL to use the default sectionw 8137 . v - The local vector 8138 . point - The sieve point in the DM 8139 . values - The array of values, which is a borrowed array and should not be freed 8140 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8141 8142 Level: intermediate 8143 8144 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8145 @*/ 8146 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8147 { 8148 PetscScalar *array; 8149 PetscInt *points = NULL; 8150 PetscInt offsets[32]; 8151 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8152 PetscErrorCode ierr; 8153 8154 PetscFunctionBegin; 8155 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8156 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8157 if (!section) { 8158 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8159 } 8160 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8161 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8162 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8163 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8164 /* Compress out points not in the section */ 8165 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8166 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8167 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8168 points[q*2] = points[p]; 8169 points[q*2+1] = points[p+1]; 8170 ++q; 8171 } 8172 } 8173 numPoints = q; 8174 for (p = 0; p < numPoints*2; p += 2) { 8175 PetscInt fdof; 8176 8177 for (f = 0; f < numFields; ++f) { 8178 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8179 offsets[f+1] += fdof; 8180 } 8181 } 8182 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8183 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8184 if (numFields) { 8185 switch (mode) { 8186 case INSERT_VALUES: 8187 for (p = 0; p < numPoints*2; p += 2) { 8188 PetscInt o = points[p+1]; 8189 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8190 } break; 8191 case INSERT_ALL_VALUES: 8192 for (p = 0; p < numPoints*2; p += 2) { 8193 PetscInt o = points[p+1]; 8194 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8195 } break; 8196 case ADD_VALUES: 8197 for (p = 0; p < numPoints*2; p += 2) { 8198 PetscInt o = points[p+1]; 8199 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8200 } break; 8201 case ADD_ALL_VALUES: 8202 for (p = 0; p < numPoints*2; p += 2) { 8203 PetscInt o = points[p+1]; 8204 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8205 } break; 8206 default: 8207 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8208 } 8209 } else { 8210 switch (mode) { 8211 case INSERT_VALUES: 8212 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8213 PetscInt o = points[p+1]; 8214 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8215 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8216 } break; 8217 case INSERT_ALL_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_TRUE, o, &values[off], array); 8222 } break; 8223 case ADD_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, add, PETSC_FALSE, o, &values[off], array); 8228 } break; 8229 case ADD_ALL_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_TRUE, o, &values[off], array); 8234 } break; 8235 default: 8236 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8237 } 8238 } 8239 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8240 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8241 PetscFunctionReturn(0); 8242 } 8243 8244 #undef __FUNCT__ 8245 #define __FUNCT__ "DMPlexPrintMatSetValues" 8246 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8247 { 8248 PetscMPIInt rank; 8249 PetscInt i, j; 8250 PetscErrorCode ierr; 8251 8252 PetscFunctionBegin; 8253 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8254 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8255 for (i = 0; i < numIndices; i++) { 8256 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8257 } 8258 for (i = 0; i < numIndices; i++) { 8259 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8260 for (j = 0; j < numIndices; j++) { 8261 #if defined(PETSC_USE_COMPLEX) 8262 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8263 #else 8264 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8265 #endif 8266 } 8267 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8268 } 8269 PetscFunctionReturn(0); 8270 } 8271 8272 #undef __FUNCT__ 8273 #define __FUNCT__ "indicesPoint_private" 8274 /* . off - The global offset of this point */ 8275 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8276 { 8277 PetscInt dof; /* The number of unknowns on this point */ 8278 PetscInt cdof; /* The number of constraints on this point */ 8279 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8280 PetscInt cind = 0, k; 8281 PetscErrorCode ierr; 8282 8283 PetscFunctionBegin; 8284 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8285 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8286 if (!cdof || setBC) { 8287 if (orientation >= 0) { 8288 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8289 } else { 8290 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8291 } 8292 } else { 8293 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8294 if (orientation >= 0) { 8295 for (k = 0; k < dof; ++k) { 8296 if ((cind < cdof) && (k == cdofs[cind])) { 8297 /* Insert check for returning constrained indices */ 8298 indices[*loff+k] = -(off+k+1); 8299 ++cind; 8300 } else { 8301 indices[*loff+k] = off+k-cind; 8302 } 8303 } 8304 } else { 8305 for (k = 0; k < dof; ++k) { 8306 if ((cind < cdof) && (k == cdofs[cind])) { 8307 /* Insert check for returning constrained indices */ 8308 indices[*loff+dof-k-1] = -(off+k+1); 8309 ++cind; 8310 } else { 8311 indices[*loff+dof-k-1] = off+k-cind; 8312 } 8313 } 8314 } 8315 } 8316 *loff += dof; 8317 PetscFunctionReturn(0); 8318 } 8319 8320 #undef __FUNCT__ 8321 #define __FUNCT__ "indicesPointFields_private" 8322 /* . off - The global offset of this point */ 8323 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8324 { 8325 PetscInt numFields, foff, f; 8326 PetscErrorCode ierr; 8327 8328 PetscFunctionBegin; 8329 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8330 for (f = 0, foff = 0; f < numFields; ++f) { 8331 PetscInt fdof, fcomp, cfdof; 8332 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8333 PetscInt cind = 0, k, c; 8334 8335 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8336 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8337 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8338 if (!cfdof || setBC) { 8339 if (orientation >= 0) { 8340 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8341 } else { 8342 for (k = fdof/fcomp-1; k >= 0; --k) { 8343 for (c = 0; c < fcomp; ++c) { 8344 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8345 } 8346 } 8347 } 8348 } else { 8349 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8350 if (orientation >= 0) { 8351 for (k = 0; k < fdof; ++k) { 8352 if ((cind < cfdof) && (k == fcdofs[cind])) { 8353 indices[foffs[f]+k] = -(off+foff+k+1); 8354 ++cind; 8355 } else { 8356 indices[foffs[f]+k] = off+foff+k-cind; 8357 } 8358 } 8359 } else { 8360 for (k = fdof/fcomp-1; k >= 0; --k) { 8361 for (c = 0; c < fcomp; ++c) { 8362 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8363 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8364 ++cind; 8365 } else { 8366 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8367 } 8368 } 8369 } 8370 } 8371 } 8372 foff += fdof - cfdof; 8373 foffs[f] += fdof; 8374 } 8375 PetscFunctionReturn(0); 8376 } 8377 8378 #undef __FUNCT__ 8379 #define __FUNCT__ "DMPlexMatSetClosure" 8380 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8381 { 8382 DM_Plex *mesh = (DM_Plex*) dm->data; 8383 PetscInt *points = NULL; 8384 PetscInt *indices; 8385 PetscInt offsets[32]; 8386 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8387 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8388 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8389 PetscErrorCode ierr; 8390 8391 PetscFunctionBegin; 8392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8393 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8394 if (useDefault) { 8395 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8396 } 8397 if (useGlobalDefault) { 8398 if (useDefault) { 8399 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8400 } else { 8401 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8402 } 8403 } 8404 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8405 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8406 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8407 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8408 /* Compress out points not in the section */ 8409 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8410 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8411 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8412 points[q*2] = points[p]; 8413 points[q*2+1] = points[p+1]; 8414 ++q; 8415 } 8416 } 8417 numPoints = q; 8418 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8419 PetscInt fdof; 8420 8421 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8422 for (f = 0; f < numFields; ++f) { 8423 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8424 offsets[f+1] += fdof; 8425 } 8426 numIndices += dof; 8427 } 8428 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8429 8430 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8431 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8432 if (numFields) { 8433 for (p = 0; p < numPoints*2; p += 2) { 8434 PetscInt o = points[p+1]; 8435 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8436 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8437 } 8438 } else { 8439 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8440 PetscInt o = points[p+1]; 8441 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8442 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8443 } 8444 } 8445 if (useGlobalDefault && !useDefault) { 8446 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8447 } 8448 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8449 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8450 if (ierr) { 8451 PetscMPIInt rank; 8452 PetscErrorCode ierr2; 8453 8454 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8455 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8456 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8457 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8458 CHKERRQ(ierr); 8459 } 8460 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8461 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8462 PetscFunctionReturn(0); 8463 } 8464 8465 #undef __FUNCT__ 8466 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8467 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8468 { 8469 PetscSection coordSection; 8470 Vec coordinates; 8471 const PetscScalar *coords; 8472 const PetscInt dim = 2; 8473 PetscInt d, f; 8474 PetscErrorCode ierr; 8475 8476 PetscFunctionBegin; 8477 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8478 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8479 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8480 if (v0) { 8481 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8482 } 8483 if (J) { 8484 for (d = 0; d < dim; d++) { 8485 for (f = 0; f < dim; f++) { 8486 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8487 } 8488 } 8489 *detJ = J[0]*J[3] - J[1]*J[2]; 8490 #if 0 8491 if (detJ < 0.0) { 8492 const PetscReal xLength = mesh->periodicity[0]; 8493 8494 if (xLength != 0.0) { 8495 PetscReal v0x = coords[0*dim+0]; 8496 8497 if (v0x == 0.0) v0x = v0[0] = xLength; 8498 for (f = 0; f < dim; f++) { 8499 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8500 8501 J[0*dim+f] = 0.5*(px - v0x); 8502 } 8503 } 8504 detJ = J[0]*J[3] - J[1]*J[2]; 8505 } 8506 #endif 8507 PetscLogFlops(8.0 + 3.0); 8508 } 8509 if (invJ) { 8510 const PetscReal invDet = 1.0/(*detJ); 8511 8512 invJ[0] = invDet*J[3]; 8513 invJ[1] = -invDet*J[1]; 8514 invJ[2] = -invDet*J[2]; 8515 invJ[3] = invDet*J[0]; 8516 PetscLogFlops(5.0); 8517 } 8518 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8519 PetscFunctionReturn(0); 8520 } 8521 8522 #undef __FUNCT__ 8523 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8524 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8525 { 8526 PetscSection coordSection; 8527 Vec coordinates; 8528 const PetscScalar *coords; 8529 const PetscInt dim = 2; 8530 PetscInt d, f; 8531 PetscErrorCode ierr; 8532 8533 PetscFunctionBegin; 8534 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8535 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8536 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8537 if (v0) { 8538 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8539 } 8540 if (J) { 8541 for (d = 0; d < dim; d++) { 8542 for (f = 0; f < dim; f++) { 8543 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8544 } 8545 } 8546 *detJ = J[0]*J[3] - J[1]*J[2]; 8547 PetscLogFlops(8.0 + 3.0); 8548 } 8549 if (invJ) { 8550 const PetscReal invDet = 1.0/(*detJ); 8551 8552 invJ[0] = invDet*J[3]; 8553 invJ[1] = -invDet*J[1]; 8554 invJ[2] = -invDet*J[2]; 8555 invJ[3] = invDet*J[0]; 8556 PetscLogFlops(5.0); 8557 } 8558 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8559 PetscFunctionReturn(0); 8560 } 8561 8562 #undef __FUNCT__ 8563 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8564 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8565 { 8566 PetscSection coordSection; 8567 Vec coordinates; 8568 const PetscScalar *coords; 8569 const PetscInt dim = 3; 8570 PetscInt d, f; 8571 PetscErrorCode ierr; 8572 8573 PetscFunctionBegin; 8574 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8575 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8576 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8577 if (v0) { 8578 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8579 } 8580 if (J) { 8581 for (d = 0; d < dim; d++) { 8582 for (f = 0; f < dim; f++) { 8583 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8584 } 8585 } 8586 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8587 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8588 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8589 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8590 PetscLogFlops(18.0 + 12.0); 8591 } 8592 if (invJ) { 8593 const PetscReal invDet = 1.0/(*detJ); 8594 8595 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8596 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8597 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8598 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8599 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8600 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8601 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8602 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8603 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8604 PetscLogFlops(37.0); 8605 } 8606 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8607 PetscFunctionReturn(0); 8608 } 8609 8610 #undef __FUNCT__ 8611 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8612 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8613 { 8614 PetscSection coordSection; 8615 Vec coordinates; 8616 const PetscScalar *coords; 8617 const PetscInt dim = 3; 8618 PetscInt d; 8619 PetscErrorCode ierr; 8620 8621 PetscFunctionBegin; 8622 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8623 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8624 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8625 if (v0) { 8626 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8627 } 8628 if (J) { 8629 for (d = 0; d < dim; d++) { 8630 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8631 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8632 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8633 } 8634 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8635 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8636 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8637 PetscLogFlops(18.0 + 12.0); 8638 } 8639 if (invJ) { 8640 const PetscReal invDet = -1.0/(*detJ); 8641 8642 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8643 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8644 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8645 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8646 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8647 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8648 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8649 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8650 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8651 PetscLogFlops(37.0); 8652 } 8653 *detJ *= 8.0; 8654 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8655 PetscFunctionReturn(0); 8656 } 8657 8658 #undef __FUNCT__ 8659 #define __FUNCT__ "DMPlexComputeCellGeometry" 8660 /*@C 8661 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8662 8663 Collective on DM 8664 8665 Input Arguments: 8666 + dm - the DM 8667 - cell - the cell 8668 8669 Output Arguments: 8670 + v0 - the translation part of this affine transform 8671 . J - the Jacobian of the transform to the reference element 8672 . invJ - the inverse of the Jacobian 8673 - detJ - the Jacobian determinant 8674 8675 Level: advanced 8676 8677 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8678 @*/ 8679 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8680 { 8681 PetscInt dim, coneSize; 8682 PetscErrorCode ierr; 8683 8684 PetscFunctionBegin; 8685 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8686 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8687 switch (dim) { 8688 case 2: 8689 switch (coneSize) { 8690 case 3: 8691 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8692 break; 8693 case 4: 8694 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8695 break; 8696 default: 8697 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8698 } 8699 break; 8700 case 3: 8701 switch (coneSize) { 8702 case 4: 8703 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8704 break; 8705 case 8: 8706 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8707 break; 8708 default: 8709 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8710 } 8711 break; 8712 default: 8713 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8714 } 8715 PetscFunctionReturn(0); 8716 } 8717 8718 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8719 { 8720 switch (i) { 8721 case 0: 8722 switch (j) { 8723 case 0: return 0; 8724 case 1: 8725 switch (k) { 8726 case 0: return 0; 8727 case 1: return 0; 8728 case 2: return 1; 8729 } 8730 case 2: 8731 switch (k) { 8732 case 0: return 0; 8733 case 1: return -1; 8734 case 2: return 0; 8735 } 8736 } 8737 case 1: 8738 switch (j) { 8739 case 0: 8740 switch (k) { 8741 case 0: return 0; 8742 case 1: return 0; 8743 case 2: return -1; 8744 } 8745 case 1: return 0; 8746 case 2: 8747 switch (k) { 8748 case 0: return 1; 8749 case 1: return 0; 8750 case 2: return 0; 8751 } 8752 } 8753 case 2: 8754 switch (j) { 8755 case 0: 8756 switch (k) { 8757 case 0: return 0; 8758 case 1: return 1; 8759 case 2: return 0; 8760 } 8761 case 1: 8762 switch (k) { 8763 case 0: return -1; 8764 case 1: return 0; 8765 case 2: return 0; 8766 } 8767 case 2: return 0; 8768 } 8769 } 8770 return 0; 8771 } 8772 8773 #undef __FUNCT__ 8774 #define __FUNCT__ "DMPlexCreateRigidBody" 8775 /*@C 8776 DMPlexCreateRigidBody - create rigid body modes from coordinates 8777 8778 Collective on DM 8779 8780 Input Arguments: 8781 + dm - the DM 8782 . section - the local section associated with the rigid field, or NULL for the default section 8783 - globalSection - the global section associated with the rigid field, or NULL for the default section 8784 8785 Output Argument: 8786 . sp - the null space 8787 8788 Note: This is necessary to take account of Dirichlet conditions on the displacements 8789 8790 Level: advanced 8791 8792 .seealso: MatNullSpaceCreate() 8793 @*/ 8794 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8795 { 8796 MPI_Comm comm; 8797 Vec coordinates, localMode, mode[6]; 8798 PetscSection coordSection; 8799 PetscScalar *coords; 8800 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8801 PetscErrorCode ierr; 8802 8803 PetscFunctionBegin; 8804 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 8805 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8806 if (dim == 1) { 8807 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 8808 PetscFunctionReturn(0); 8809 } 8810 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8811 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8812 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8813 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8814 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8815 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8816 m = (dim*(dim+1))/2; 8817 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8818 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8819 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8820 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8821 /* Assume P1 */ 8822 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8823 for (d = 0; d < dim; ++d) { 8824 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8825 8826 values[d] = 1.0; 8827 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8828 for (v = vStart; v < vEnd; ++v) { 8829 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8830 } 8831 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8832 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8833 } 8834 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8835 for (d = dim; d < dim*(dim+1)/2; ++d) { 8836 PetscInt i, j, k = dim > 2 ? d - dim : d; 8837 8838 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8839 for (v = vStart; v < vEnd; ++v) { 8840 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8841 PetscInt off; 8842 8843 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8844 for (i = 0; i < dim; ++i) { 8845 for (j = 0; j < dim; ++j) { 8846 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8847 } 8848 } 8849 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8850 } 8851 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8852 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8853 } 8854 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8855 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8856 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 8857 /* Orthonormalize system */ 8858 for (i = dim; i < m; ++i) { 8859 PetscScalar dots[6]; 8860 8861 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8862 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8863 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8864 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 8865 } 8866 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8867 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8868 PetscFunctionReturn(0); 8869 } 8870 8871 #undef __FUNCT__ 8872 #define __FUNCT__ "DMPlexGetHybridBounds" 8873 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 8874 { 8875 DM_Plex *mesh = (DM_Plex*) dm->data; 8876 PetscInt dim; 8877 PetscErrorCode ierr; 8878 8879 PetscFunctionBegin; 8880 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8881 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8882 if (cMax) *cMax = mesh->hybridPointMax[dim]; 8883 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 8884 if (eMax) *eMax = mesh->hybridPointMax[1]; 8885 if (vMax) *vMax = mesh->hybridPointMax[0]; 8886 PetscFunctionReturn(0); 8887 } 8888 8889 #undef __FUNCT__ 8890 #define __FUNCT__ "DMPlexSetHybridBounds" 8891 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 8892 { 8893 DM_Plex *mesh = (DM_Plex*) dm->data; 8894 PetscInt dim; 8895 PetscErrorCode ierr; 8896 8897 PetscFunctionBegin; 8898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8899 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8900 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 8901 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 8902 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 8903 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 8904 PetscFunctionReturn(0); 8905 } 8906 8907 #undef __FUNCT__ 8908 #define __FUNCT__ "DMPlexGetVTKCellHeight" 8909 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8910 { 8911 DM_Plex *mesh = (DM_Plex*) dm->data; 8912 8913 PetscFunctionBegin; 8914 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8915 PetscValidPointer(cellHeight, 2); 8916 *cellHeight = mesh->vtkCellHeight; 8917 PetscFunctionReturn(0); 8918 } 8919 8920 #undef __FUNCT__ 8921 #define __FUNCT__ "DMPlexSetVTKCellHeight" 8922 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8923 { 8924 DM_Plex *mesh = (DM_Plex*) dm->data; 8925 8926 PetscFunctionBegin; 8927 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8928 mesh->vtkCellHeight = cellHeight; 8929 PetscFunctionReturn(0); 8930 } 8931 8932 #undef __FUNCT__ 8933 #define __FUNCT__ "DMPlexCreateNumbering_Private" 8934 /* We can easily have a form that takes an IS instead */ 8935 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 8936 { 8937 PetscSection section, globalSection; 8938 PetscInt *numbers, p; 8939 PetscErrorCode ierr; 8940 8941 PetscFunctionBegin; 8942 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8943 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 8944 for (p = pStart; p < pEnd; ++p) { 8945 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 8946 } 8947 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 8948 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8949 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 8950 for (p = pStart; p < pEnd; ++p) { 8951 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8952 } 8953 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8954 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8955 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8956 PetscFunctionReturn(0); 8957 } 8958 8959 #undef __FUNCT__ 8960 #define __FUNCT__ "DMPlexGetCellNumbering" 8961 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8962 { 8963 DM_Plex *mesh = (DM_Plex*) dm->data; 8964 PetscInt cellHeight, cStart, cEnd, cMax; 8965 PetscErrorCode ierr; 8966 8967 PetscFunctionBegin; 8968 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8969 if (!mesh->globalCellNumbers) { 8970 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8971 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8972 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 8973 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 8974 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 8975 } 8976 *globalCellNumbers = mesh->globalCellNumbers; 8977 PetscFunctionReturn(0); 8978 } 8979 8980 #undef __FUNCT__ 8981 #define __FUNCT__ "DMPlexGetVertexNumbering" 8982 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8983 { 8984 DM_Plex *mesh = (DM_Plex*) dm->data; 8985 PetscInt vStart, vEnd, vMax; 8986 PetscErrorCode ierr; 8987 8988 PetscFunctionBegin; 8989 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8990 if (!mesh->globalVertexNumbers) { 8991 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8992 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 8993 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 8994 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 8995 } 8996 *globalVertexNumbers = mesh->globalVertexNumbers; 8997 PetscFunctionReturn(0); 8998 } 8999 9000 #undef __FUNCT__ 9001 #define __FUNCT__ "DMPlexGetScale" 9002 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9003 { 9004 DM_Plex *mesh = (DM_Plex*) dm->data; 9005 9006 PetscFunctionBegin; 9007 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9008 PetscValidPointer(scale, 3); 9009 *scale = mesh->scale[unit]; 9010 PetscFunctionReturn(0); 9011 } 9012 9013 #undef __FUNCT__ 9014 #define __FUNCT__ "DMPlexSetScale" 9015 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9016 { 9017 DM_Plex *mesh = (DM_Plex*) dm->data; 9018 9019 PetscFunctionBegin; 9020 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9021 mesh->scale[unit] = scale; 9022 PetscFunctionReturn(0); 9023 } 9024 9025 9026 /******************************************************************************* 9027 This should be in a separate Discretization object, but I am not sure how to lay 9028 it out yet, so I am stuffing things here while I experiment. 9029 *******************************************************************************/ 9030 #undef __FUNCT__ 9031 #define __FUNCT__ "DMPlexSetFEMIntegration" 9032 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9033 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9034 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9035 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9036 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9037 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9038 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9039 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9040 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9041 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9042 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9043 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], 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 { 9050 DM_Plex *mesh = (DM_Plex*) dm->data; 9051 9052 PetscFunctionBegin; 9053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9054 mesh->integrateResidualFEM = integrateResidualFEM; 9055 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9056 mesh->integrateJacobianFEM = integrateJacobianFEM; 9057 PetscFunctionReturn(0); 9058 } 9059 9060 #undef __FUNCT__ 9061 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9062 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9063 { 9064 Vec coordinates; 9065 PetscSection section, cSection; 9066 PetscInt dim, vStart, vEnd, v, c, d; 9067 PetscScalar *values, *cArray; 9068 PetscReal *coords; 9069 PetscErrorCode ierr; 9070 9071 PetscFunctionBegin; 9072 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9073 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9074 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9075 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9076 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9077 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9078 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9079 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9080 for (v = vStart; v < vEnd; ++v) { 9081 PetscInt dof, off; 9082 9083 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9084 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9085 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9086 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9087 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9088 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9089 } 9090 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9091 /* Temporary, must be replaced by a projection on the finite element basis */ 9092 { 9093 PetscInt eStart = 0, eEnd = 0, e, depth; 9094 9095 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9096 --depth; 9097 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9098 for (e = eStart; e < eEnd; ++e) { 9099 const PetscInt *cone = NULL; 9100 PetscInt coneSize, d; 9101 PetscScalar *coordsA, *coordsB; 9102 9103 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9104 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9105 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9106 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9107 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9108 for (d = 0; d < dim; ++d) { 9109 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9110 } 9111 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9112 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9113 } 9114 } 9115 9116 ierr = PetscFree(coords);CHKERRQ(ierr); 9117 ierr = PetscFree(values);CHKERRQ(ierr); 9118 #if 0 9119 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9120 PetscReal detJ; 9121 9122 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9123 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9124 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9125 9126 for (PetscInt c = cStart; c < cEnd; ++c) { 9127 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9128 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9129 const int oSize = pV.getSize(); 9130 int v = 0; 9131 9132 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9133 for (PetscInt cl = 0; cl < oSize; ++cl) { 9134 const PetscInt fDim; 9135 9136 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9137 if (pointDim) { 9138 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9139 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9140 } 9141 } 9142 } 9143 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9144 pV.clear(); 9145 } 9146 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9147 ierr = PetscFree(values);CHKERRQ(ierr); 9148 #endif 9149 PetscFunctionReturn(0); 9150 } 9151 9152 #undef __FUNCT__ 9153 #define __FUNCT__ "DMPlexProjectFunction" 9154 /*@C 9155 DMPlexProjectFunction - This projects the given function into the function space provided. 9156 9157 Input Parameters: 9158 + dm - The DM 9159 . numComp - The number of components (functions) 9160 . funcs - The coordinate functions to evaluate 9161 - mode - The insertion mode for values 9162 9163 Output Parameter: 9164 . X - vector 9165 9166 Level: developer 9167 9168 Note: 9169 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9170 We will eventually fix it. 9171 9172 ,seealso: DMPlexComputeL2Diff() 9173 */ 9174 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9175 { 9176 Vec localX; 9177 PetscErrorCode ierr; 9178 9179 PetscFunctionBegin; 9180 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9181 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9182 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9183 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9184 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9185 PetscFunctionReturn(0); 9186 } 9187 9188 #undef __FUNCT__ 9189 #define __FUNCT__ "DMPlexComputeL2Diff" 9190 /*@C 9191 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9192 9193 Input Parameters: 9194 + dm - The DM 9195 . quad - The PetscQuadrature object for each field 9196 . funcs - The functions to evaluate for each field component 9197 - X - The coefficient vector u_h 9198 9199 Output Parameter: 9200 . diff - The diff ||u - u_h||_2 9201 9202 Level: developer 9203 9204 .seealso: DMPlexProjectFunction() 9205 */ 9206 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9207 { 9208 const PetscInt debug = 0; 9209 PetscSection section; 9210 Vec localX; 9211 PetscReal *coords, *v0, *J, *invJ, detJ; 9212 PetscReal localDiff = 0.0; 9213 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9214 PetscErrorCode ierr; 9215 9216 PetscFunctionBegin; 9217 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9218 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9219 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9220 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9221 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9222 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9223 for (field = 0; field < numFields; ++field) { 9224 numComponents += quad[field].numComponents; 9225 } 9226 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9227 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9228 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9229 for (c = cStart; c < cEnd; ++c) { 9230 const PetscScalar *x; 9231 PetscReal elemDiff = 0.0; 9232 9233 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9234 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9235 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9236 9237 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9238 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9239 const PetscReal *quadPoints = quad[field].quadPoints; 9240 const PetscReal *quadWeights = quad[field].quadWeights; 9241 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9242 const PetscInt numBasisComps = quad[field].numComponents; 9243 const PetscReal *basis = quad[field].basis; 9244 PetscInt q, d, e, fc, f; 9245 9246 if (debug) { 9247 char title[1024]; 9248 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9249 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9250 } 9251 for (q = 0; q < numQuadPoints; ++q) { 9252 for (d = 0; d < dim; d++) { 9253 coords[d] = v0[d]; 9254 for (e = 0; e < dim; e++) { 9255 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9256 } 9257 } 9258 for (fc = 0; fc < numBasisComps; ++fc) { 9259 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9260 PetscReal interpolant = 0.0; 9261 for (f = 0; f < numBasisFuncs; ++f) { 9262 const PetscInt fidx = f*numBasisComps+fc; 9263 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9264 } 9265 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9266 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9267 } 9268 } 9269 comp += numBasisComps; 9270 fieldOffset += numBasisFuncs*numBasisComps; 9271 } 9272 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9273 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9274 localDiff += elemDiff; 9275 } 9276 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9277 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9278 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9279 *diff = PetscSqrtReal(*diff); 9280 PetscFunctionReturn(0); 9281 } 9282 9283 #undef __FUNCT__ 9284 #define __FUNCT__ "DMPlexComputeResidualFEM" 9285 /*@ 9286 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9287 9288 Input Parameters: 9289 + dm - The mesh 9290 . X - Local input vector 9291 - user - The user context 9292 9293 Output Parameter: 9294 . F - Local output vector 9295 9296 Note: 9297 The second member of the user context must be an FEMContext. 9298 9299 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9300 like a GPU, or vectorize on a multicore machine. 9301 9302 .seealso: DMPlexComputeJacobianActionFEM() 9303 */ 9304 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9305 { 9306 DM_Plex *mesh = (DM_Plex*) dm->data; 9307 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9308 PetscQuadrature *quad = fem->quad; 9309 PetscSection section; 9310 PetscReal *v0, *J, *invJ, *detJ; 9311 PetscScalar *elemVec, *u; 9312 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9313 PetscInt cellDof = 0, numComponents = 0; 9314 PetscErrorCode ierr; 9315 9316 PetscFunctionBegin; 9317 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9318 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9319 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9320 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9321 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9322 numCells = cEnd - cStart; 9323 for (field = 0; field < numFields; ++field) { 9324 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9325 numComponents += quad[field].numComponents; 9326 } 9327 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9328 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9329 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); 9330 for (c = cStart; c < cEnd; ++c) { 9331 const PetscScalar *x; 9332 PetscInt i; 9333 9334 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9335 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9336 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9337 9338 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9339 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9340 } 9341 for (field = 0; field < numFields; ++field) { 9342 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9343 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9344 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9345 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9346 /* Conforming batches */ 9347 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9348 PetscInt numBlocks = 1; 9349 PetscInt batchSize = numBlocks * blockSize; 9350 PetscInt numBatches = numBatchesTmp; 9351 PetscInt numChunks = numCells / (numBatches*batchSize); 9352 /* Remainder */ 9353 PetscInt numRemainder = numCells % (numBatches * batchSize); 9354 PetscInt offset = numCells - numRemainder; 9355 9356 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9357 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9358 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9359 } 9360 for (c = cStart; c < cEnd; ++c) { 9361 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9362 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9363 } 9364 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9365 if (mesh->printFEM) { 9366 PetscMPIInt rank, numProcs; 9367 PetscInt p; 9368 9369 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9370 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9371 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9372 for (p = 0; p < numProcs; ++p) { 9373 if (p == rank) { 9374 Vec f; 9375 9376 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9377 ierr = VecCopy(F, f);CHKERRQ(ierr); 9378 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9379 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9380 ierr = VecDestroy(&f);CHKERRQ(ierr); 9381 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9382 } 9383 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9384 } 9385 } 9386 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9387 PetscFunctionReturn(0); 9388 } 9389 9390 #undef __FUNCT__ 9391 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9392 /*@C 9393 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9394 9395 Input Parameters: 9396 + dm - The mesh 9397 . J - The Jacobian shell matrix 9398 . X - Local input vector 9399 - user - The user context 9400 9401 Output Parameter: 9402 . F - Local output vector 9403 9404 Note: 9405 The second member of the user context must be an FEMContext. 9406 9407 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9408 like a GPU, or vectorize on a multicore machine. 9409 9410 .seealso: DMPlexComputeResidualFEM() 9411 */ 9412 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9413 { 9414 DM_Plex *mesh = (DM_Plex*) dm->data; 9415 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9416 PetscQuadrature *quad = fem->quad; 9417 PetscSection section; 9418 JacActionCtx *jctx; 9419 PetscReal *v0, *J, *invJ, *detJ; 9420 PetscScalar *elemVec, *u, *a; 9421 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9422 PetscInt cellDof = 0; 9423 PetscErrorCode ierr; 9424 9425 PetscFunctionBegin; 9426 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9427 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9428 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9429 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9430 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9431 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9432 numCells = cEnd - cStart; 9433 for (field = 0; field < numFields; ++field) { 9434 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9435 } 9436 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9437 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); 9438 for (c = cStart; c < cEnd; ++c) { 9439 const PetscScalar *x; 9440 PetscInt i; 9441 9442 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9443 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9444 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9445 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9446 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9447 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9448 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9449 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9450 } 9451 for (field = 0; field < numFields; ++field) { 9452 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9453 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9454 /* Conforming batches */ 9455 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9456 PetscInt numBlocks = 1; 9457 PetscInt batchSize = numBlocks * blockSize; 9458 PetscInt numBatches = numBatchesTmp; 9459 PetscInt numChunks = numCells / (numBatches*batchSize); 9460 /* Remainder */ 9461 PetscInt numRemainder = numCells % (numBatches * batchSize); 9462 PetscInt offset = numCells - numRemainder; 9463 9464 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); 9465 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], 9466 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9467 } 9468 for (c = cStart; c < cEnd; ++c) { 9469 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9470 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9471 } 9472 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9473 if (mesh->printFEM) { 9474 PetscMPIInt rank, numProcs; 9475 PetscInt p; 9476 9477 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9478 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9479 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9480 for (p = 0; p < numProcs; ++p) { 9481 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9482 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9483 } 9484 } 9485 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9486 PetscFunctionReturn(0); 9487 } 9488 9489 #undef __FUNCT__ 9490 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9491 /*@ 9492 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9493 9494 Input Parameters: 9495 + dm - The mesh 9496 . X - Local input vector 9497 - user - The user context 9498 9499 Output Parameter: 9500 . Jac - Jacobian matrix 9501 9502 Note: 9503 The second member of the user context must be an FEMContext. 9504 9505 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9506 like a GPU, or vectorize on a multicore machine. 9507 9508 .seealso: FormFunctionLocal() 9509 */ 9510 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9511 { 9512 DM_Plex *mesh = (DM_Plex*) dm->data; 9513 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9514 PetscQuadrature *quad = fem->quad; 9515 PetscSection section; 9516 PetscReal *v0, *J, *invJ, *detJ; 9517 PetscScalar *elemMat, *u; 9518 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9519 PetscInt cellDof = 0, numComponents = 0; 9520 PetscBool isShell; 9521 PetscErrorCode ierr; 9522 9523 PetscFunctionBegin; 9524 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9525 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9526 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9527 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9528 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9529 numCells = cEnd - cStart; 9530 for (field = 0; field < numFields; ++field) { 9531 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9532 numComponents += quad[field].numComponents; 9533 } 9534 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9535 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9536 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); 9537 for (c = cStart; c < cEnd; ++c) { 9538 const PetscScalar *x; 9539 PetscInt i; 9540 9541 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9542 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9543 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9544 9545 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9546 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9547 } 9548 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9549 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9550 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9551 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9552 PetscInt fieldJ; 9553 9554 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9555 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9556 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9557 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9558 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9559 /* Conforming batches */ 9560 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9561 PetscInt numBlocks = 1; 9562 PetscInt batchSize = numBlocks * blockSize; 9563 PetscInt numBatches = numBatchesTmp; 9564 PetscInt numChunks = numCells / (numBatches*batchSize); 9565 /* Remainder */ 9566 PetscInt numRemainder = numCells % (numBatches * batchSize); 9567 PetscInt offset = numCells - numRemainder; 9568 9569 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9570 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9571 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9572 } 9573 } 9574 for (c = cStart; c < cEnd; ++c) { 9575 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9576 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9577 } 9578 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9579 9580 /* Assemble matrix, using the 2-step process: 9581 MatAssemblyBegin(), MatAssemblyEnd(). */ 9582 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9583 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9584 9585 if (mesh->printFEM) { 9586 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9587 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9588 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9589 } 9590 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9591 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9592 if (isShell) { 9593 JacActionCtx *jctx; 9594 9595 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9596 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9597 } 9598 *str = SAME_NONZERO_PATTERN; 9599 PetscFunctionReturn(0); 9600 } 9601 9602 9603 #undef __FUNCT__ 9604 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9605 /*@C 9606 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9607 the local section and an SF describing the section point overlap. 9608 9609 Input Parameters: 9610 + s - The PetscSection for the local field layout 9611 . sf - The SF describing parallel layout of the section points 9612 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9613 . label - The label specifying the points 9614 - labelValue - The label stratum specifying the points 9615 9616 Output Parameter: 9617 . gsection - The PetscSection for the global field layout 9618 9619 Note: This gives negative sizes and offsets to points not owned by this process 9620 9621 Level: developer 9622 9623 .seealso: PetscSectionCreate() 9624 @*/ 9625 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9626 { 9627 PetscInt *neg; 9628 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9629 PetscErrorCode ierr; 9630 9631 PetscFunctionBegin; 9632 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9633 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9634 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9635 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9636 /* Mark ghost points with negative dof */ 9637 for (p = pStart; p < pEnd; ++p) { 9638 PetscInt value; 9639 9640 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9641 if (value != labelValue) continue; 9642 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9643 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9644 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9645 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9646 neg[p-pStart] = -(dof+1); 9647 } 9648 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9649 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 9650 if (nroots >= 0) { 9651 if (nroots > pEnd - pStart) { 9652 PetscInt *tmpDof; 9653 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9654 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9655 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9656 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9657 for (p = pStart; p < pEnd; ++p) { 9658 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 9659 } 9660 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9661 } else { 9662 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9663 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9664 } 9665 } 9666 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9667 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9668 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9669 9670 (*gsection)->atlasOff[p] = off; 9671 9672 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9673 } 9674 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9675 globalOff -= off; 9676 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9677 (*gsection)->atlasOff[p] += globalOff; 9678 9679 neg[p] = -((*gsection)->atlasOff[p]+1); 9680 } 9681 /* Put in negative offsets for ghost points */ 9682 if (nroots >= 0) { 9683 if (nroots > pEnd - pStart) { 9684 PetscInt *tmpOff; 9685 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9686 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9687 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9688 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9689 for (p = pStart; p < pEnd; ++p) { 9690 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 9691 } 9692 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9693 } else { 9694 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9695 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9696 } 9697 } 9698 ierr = PetscFree(neg);CHKERRQ(ierr); 9699 PetscFunctionReturn(0); 9700 } 9701